我想知道将滤镜应用于图像的正确方法是什么。我正在阅读的图像处理教科书只讨论过滤器的数学和理论方面,但并没有太多关注它的编程部分!
我想出了这个伪代码可以告诉我它是否正确,因为我将sobel边缘滤波器应用于图像并且我对输出不满意。我认为它检测到许多不必要的点作为边缘并错过了边缘的几个点。
int filter[][] = {{0d,-1d,0d},{-1d,8d,-1d},{0d,-1d,0d}};// I dont exactly remember the //sobel filter
int total = 0;
for(int i = 2;i<image.getWidth()-2;i++)
for(int j = 2;j<image.getHeight()-2;j++)
{
total = 0;
for(int k = 0;k<3;k++)
for(int l = 0;l<3;l++)
{
total += intensity(image.getRGB(i,j)) * filter[i+k][j+l];
}
if(total >= threshold){
image.setRGB(i,j,WHITE);
}
}
int intensity(int color)
{
return (((color >> 16) & 0xFF) + ((color >> 8) & 0xFF) + color)/3;
}
答案 0 :(得分:2)
两个问题:
(1)sober operator包括x方向和y方向
int filter[][] = {{1d,0d,-1d},{2d,0d,-2d},{1d,0d,-1d}};
和
int filter[][] = {{1d,2d,1d},{0d,0d,0d},{-1d,-2d,-1d}};
(2)卷积部分:
total += intensity(image.getRGB(i+k,j+l)) * filter[k][l];
答案 1 :(得分:1)
您的代码看起来并不安静。要将滤镜应用于图像,必须应用离散时间卷积算法http://en.wikipedia.org/wiki/Convolution。
进行卷积时,您想要将3x3滤镜滑过图像,一次移动一个像素。在每一步中,将滤波器“像素”的值乘以该特定滤波器“像素”下的图像像素的对应值(滤波器下的9个像素都受影响)。结果的值应该在你去的时候加到一个新的结果图像上。
阈值处理是可选的......
以下是使用一些注释修改的代码:
int filter[][] = {{0d,-1d,0d},{-1d,8d,-1d},{0d,-1d,0d}};
//create a new array for the result image on the heap
int newImage[][][3] = ...
//initialize every element in the newImage to 0
for(int i = 0;i<image.getWidth()-1;i++)
for(int j = 0;j<image.getHeight()-1;j++)
for (int k = 0; k<3; k++)
{
newImage[i][j][k] = 0;
}
//Convolve the filter and the image
for(int i = 1;i<image.getWidth()-2;i++)
for(int j = 1;j<image.getHeight()-2;j++)
{
for(int k = -1;k<2;k++)
for(int l = -1;l<2;l++)
{
newImage[i+k][j+l][1] += getRed(image.getRGB(i+k ,j+l)) * filter[k+1][l+1];
newImage[i+k][j+l][2] += getGreen(image.getRGB(i+k ,j+l)) * filter[k+1][l+1];
newImage[i+k][j+l][3] += getBlue(image.getRGB(i+k ,j+l)) * filter[k+1][l+1];
}
}
int getRed(int color)
{
...
}
int getBlue(int color)
{
...
}
int getGreen(int color)
{
...
}
请注意,上面的代码无法正确处理图像的边缘。如果你想让它绝对完美,你可以首先将滤镜滑动到屏幕外(因此第一个位置会将滤镜的右下角应用到图像的0,0像素。这样做真的很痛苦但是,通常更容易忽略边缘周围的2像素边界。
一旦你开始工作,你可以通过在水平方向和垂直方向上滑动Sobel滤波器来进行实验。您会注意到滤波器对垂直于行进方向(到滤波器)的线的作用最强。因此,为了获得最佳结果,请在水平方向和垂直方向上应用滤镜(使用相同的newImage)。这样你就可以同样很好地检测垂直线和水平线。 :)
答案 2 :(得分:1)
这里有一些严重的未定义行为。数组filter
为3x3,但您使用i+k
和j+l
的下标达到了图片的大小。看起来你错放了这个补充:
total += intensity(image.getRGB(i+k,j+l)) * filter[k][l];
答案 3 :(得分:0)
使用GPUImage,这对你来说非常好。