使用3x3高斯卷积核模糊图像?

4
我希望创建一种方法,使用3x3高斯核模糊24位图像。
我得到了以下内容。
3x3高斯核: http://i.stack.imgur.com/YAEQR.png A是原始图像,B是结果图像。
B(i,j) =
1/16 * A(i-1,j-1) +1/8 * A(i,j-1) +1/16 * A(i+1,j-1) +1/8 * A(i-1,j) +1/4 * A(i,j) +1/8 *A(i+1,j) +1/16 * A(i-1,j+1) +1/8 * A(i,j+1) +1/16 * A(i+1,j+1)  

方法:

public static BufferedImage gaussianBlur(Image img)

其中img是输入图像的引用变量。
返回值是生成图像对象的地址。

我应该将图像分成9个部分来实现这种方法吗?


为什么你要这样做? - Oliver Charlesworth
你需要考虑的是使用图像的旧值而不是新值。 - RamonBoza
2个回答

12

你不需要将其分成9个部分。至少我没有看到有充分的理由这样做。

但在此过程中,最好要小心,记得将图像数据复制到某个地方,并始终使用该数据来计算新图像,避免使用新图像数据来计算新图像。


同时,我不明白为什么你需要编写自己的函数来对图像进行高斯模糊。这可以很容易地实现,如下所示:

float[] matrix = {
    1/16f, 1/8f, 1/16f, 
    1/8f, 1/4f, 1/8f, 
    1/16f, 1/8f, 1/16f, 
};

BufferedImageOp op = new ConvolveOp( new Kernel(3, 3, matrix) );
blurredImage = op.filter(sourceImage, destImage);

0
不要将其分成几部分。如果你有一张大图片,该怎么办呢? 你应该先编写一个函数,检查过滤器是否在图像边界内。在C语言中,它可能是这样的:

int filterWithinImage(Matrix m1, Matrix m2, int i, int j) {
  int b; //min number of pixels that the center of the filter needs to be
         // away from any border of the image to be inbounds


  /***********************odd size filter only*************************/
  //when filter size is odd there is well defined convenient center
  // of the filter
  if (isOdd(m2.height) && isOdd(m2.width)) {
    //to check the bounds subtract 1 from the width and divide by 2
    b = (m2.width - 1) / 2;
    //look at the left border
    if ((j - b)<0) return 0;
    //top border
    if ((i - b)<0) return 0;
    //right border
    if ((j + b)>(m1.width-1)) return 0;
    //bottom border
    if ((i + b)>(m1.height -1)) return 0;
  }
  return 1;
}

然后编写单独的函数来计算强度:

double calculateValue(Matrix m1,Matrix m2,int imagei, int imagej) {
  double out = 0;//return value
  int i, j, fli, flj; //for iterating over the filter
  int b = (m2.height -1) / 2;//max number that we add to the center coordinates
                            //to get to the edge of the filter
  fli = 0; flj = 0;
  for(i = imagei - b; i < imagei + b +1; i++) {
    for(j = imagej - b; j < imagej + b +1; j++) {
          //    if (i == 599)
      //printf("calc func image i: %d,  image j %d, b %d,  filter i %d,  filter j %d\n",
      // i,j,b,fli,flj);      
      out += m1.map[i][j] * m2.map[fli][flj++];
    }
    fli++;
    flj=0;
  }
  return out;
}

然后只需编写applyFilter函数。 m2是需要旋转180度的过滤器。 Matrix applyFilter(Matrix m1, Matrix m2) { int x,y; //先旋转过滤器 Matrix rotFilter = createMatrix(m2.height,m2.width); for (x = 0; x < m2.height; x++) for (y = 0; y < m2.width; y++) { rotFilter.map[y][x] = m2.map[m2.height-y-1][m2.width-x-1]; }

  Matrix mOut = createMatrix(m1.height, m1.width);
  int i,j;
  for (i = 0; i < m1.height; i++) {
    for (j = 0; j < m1.width; j++) {
      if (!filterWithinImage(m1,rotFilter,i,j)) { //filter is out of bounds
    mOut.map[i][j] = 0;
      }
      else {
    mOut.map[i][j] = calculateValue(m1,rotFilter,i,j);
      }
    }
  }
  return mOut;
}

这是一种通用的方法,需要修改以适应Java数据结构,但算法是相同的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接