1

我一直在尝试制作自己的卷积运算符,而不是使用 Java 自带的内置卷积运算符。我在此图像链接上应用了内置卷积运算符

使用带有高斯滤波器的内置卷积算子我得到了这个图像。 关联

现在我使用我的代码运行相同的图像

public static int convolve(BufferedImage a,int x,int y){
 int red=0,green=0,blue=0;
      float[] matrix = { 
 0.1710991401561097f, 0.2196956447338621f, 0.1710991401561097f, 
 0.2196956447338621f, 0.28209479177387814f, 0.2196956447338621f, 
 0.1710991401561097f, 0.2196956447338621f, 0.1710991401561097f, 
 };
      for(int i = x;i<x+3;i++){
          for(int j = y;j<y+3;j++){
              int color = a.getRGB(i,j);
              red += Math.round(((color >> 16) & 0xff)*matrix[(i-x)*3+j-y]);
              green += Math.round(((color >> 8) & 0xff)*matrix[(i-x)*3+j-y]);
              blue += Math.round(((color >> 0) & 0xff)*matrix[(i-x)*3+j-y]);

          }
      }

    return (a.getRGB(x, y)&0xFF000000) | (red << 16) | (green << 8) | (blue);
}

我得到的结果是这样的。 关联

另外,我如何优化我编写的代码。内置卷积运算符需要 1~2 秒,而我的代码即使没有达到预期的确切目的,也需要 5~7 秒!

我在上传时不小心旋转了我的源图像。所以请忽略这一点。

4

1 回答 1

1

首先,在循环的每个循环中,您都不必要地(并且错误地)将结果从 float 转换为 int。您的red,greenblue应该是 float 类型,并且只有在卷积之后才应该转换回整数(当转换回 RGB 时):

  float red=0.0f, green = 0.0f, blue = 0.0f
  for(int i = x;i<x+3;i++){
      for(int j = y;j<y+3;j++){
          int color = a.getRGB(i,j);
          red += ((color >> 16) & 0xff)*matrix[(i-x)*3+j-y];
          green += ((color >> 8) & 0xff)*matrix[(i-x)*3+j-y];
          blue += ((color >> 0) & 0xff)*matrix[(i-x)*3+j-y];

      }
  }

return (a.getRGB(x, y)&0xFF000000) | (((int)red) << 16) | (((int)green) << 8) | ((int)blue);

结果中的颜色渗出是因为您的系数matrix错误:

0.1710991401561097f + 0.2196956447338621f + 0.1710991401561097f +
0.2196956447338621f + 0.28209479177387814f + 0.2196956447338621f +
0.1710991401561097f + 0.2196956447338621f + 0.1710991401561097f =

1.8452741

模糊卷积矩阵中的系数之和应为 1.0。当您将此矩阵应用于图像时,您可能会获得超过 255 种颜色。当这种情况发生时,通道会“渗入”下一个通道(蓝色到绿色等)。具有此矩阵的完全绿色图像将导致:

绿色 = 255 * 1.8452741 ~= 471 = 0x01D7;
 RGB = 0xFF01D700;

这是一种不太强烈的绿色,带有一丝红色。

您可以通过将系数除以 来解决此问题1.8452741,但您要确保:

(int)(255.0f * (系数总和)) = 255

如果不是,您需要添加一个检查,将通道的大小限制为 255,并且不要让它们环绕。例如:

if (red > 255.0f)
   red = 255.0f;

关于效率/优化:
速度上的差异可能是由这种不必要的转换和调用 Math.Round 来解释的,但更可能的候选者是您访问图像的方式。我对 BufferedImage 和 Raster 不够熟悉,无法就访问底层图像缓冲区的最有效方法向您提供建议。

于 2013-11-10T11:18:29.277 回答