C 实现Sobel过滤器时会产生奇怪的结果
我一直在学习计算机视觉,想用C语言实现一些简单的技术。对于第一种技术,我正在做Sobel边缘检测滤波器。我理解它是如何工作的,所以我认为编写代码应该相当容易,但我得到了非常奇怪的结果 我使用的是下图: 结果呢 新结果!: 应该注意的是,我使用的是.ppm图像格式(链接指向jpgs,因为我找不到支持.ppm的图像主机) 无论如何,下面是我实现Sobel的代码部分:C 实现Sobel过滤器时会产生奇怪的结果,c,image-processing,C,Image Processing,我一直在学习计算机视觉,想用C语言实现一些简单的技术。对于第一种技术,我正在做Sobel边缘检测滤波器。我理解它是如何工作的,所以我认为编写代码应该相当容易,但我得到了非常奇怪的结果 我使用的是下图: 结果呢 新结果!: 应该注意的是,我使用的是.ppm图像格式(链接指向jpgs,因为我找不到支持.ppm的图像主机) 无论如何,下面是我实现Sobel的代码部分: /********************************************************** This
/**********************************************************
This program takes in an image file and applies the Sobel
Filter edge detection technique to it.
**********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "ppmReader.h"
void sobelFilter(){
//Sobel kernels dx (horizontal) and dy (vertical)
int horizFilter[3][3] = {{ 1, 0, -1},
{ 2, 0, -2},
{ 1, 0, -1}};
int vertFilter[3][3] = {{ 1, 2, 1},
{ 0, 0, 0},
{-1, -2, -1}};
int pixVal = 0;
int horizPixVal = 0;
int vertPixVal = 0;
int x, y, i, j;
//Quick check to make sure dimensions are correct
printf("Using a Width of: %d\n", width);
printf("Using a Height of: %d\n\n", height);
//Start filtering process here
for(x = 0; x < width; x++){
for(y = 0; y < height; y++){
pixVal = 0;
horizPixVal = 0;
vertPixVal = 0;
if(!((x == 0) || (x == width-1) || (y == 0) || (y == height-1))){ //If the current pixel is along the border, ignore it and set to zero
for(i = -1; i <= 1; i++){ //because the kernel does not align to it
for(j = -1; j <= 1; j++){
horizPixVal += (int)(image[y + j][x + i][0]) * horizFilter[i + 1][j + 1]; //Only need to focus on one of the RGB values since the output is
vertPixVal += (int)(image[y + j][x + i][0]) * vertFilter[i + 1][j + 1]; //greyscale and all three values are the same
}
}
}
pixVal = sqrt((horizPixVal * horizPixVal) + (vertPixVal * vertPixVal)); //Calculate magnitude
pixVal = sqrt(horizPixVal * horizPixVal);
if(pixVal > 255) pixVal = 255; //Clamp value within 8-bit range
filteredImage[y][x][0] = (unsigned char)pixVal;
}
}
}
/**********************************************************
该程序接收图像文件并应用Sobel
滤波边缘检测技术。
**********************************************************/
#包括
#包括
#包括
#包括“ppmReader.h”
void sobelFilter(){
//Sobel内核dx(水平)和dy(垂直)
int horizFilter[3][3]={{1,0,-1},
{ 2, 0, -2},
{ 1, 0, -1}};
int vertFilter[3][3]={{1,2,1},
{ 0, 0, 0},
{-1, -2, -1}};
int-pixVal=0;
int horizPixVal=0;
int vertPixVal=0;
int x,y,i,j;
//快速检查以确保尺寸正确
printf(“使用的宽度为:%d\n”,宽度);
printf(“使用高度:%d\n\n”,高度);
//在这里开始过滤过程
对于(x=0;x 对于(i=-1;i图像通常首先以y
坐标索引,然后以x
坐标索引,如下所示:
... image[y + j][x + i] ...
这是一个惯例,让人们在处理C语言中的图像时不会感到困惑。不幸的是,它与Matlab使用的有点矛盾,所以我只希望您在C语言中完成这一切
此外,表示红色/绿色/蓝色值是交错的,因此“颜色平面”必须是最后一个索引:
... image[y + j][x + i][0] ...
除非在将输入文件加载到内存时对其进行了一些重新排序。您没有显示从该文件读取的代码,因此很难知道它是否进行了任何重新排序
添加:读取和写入文件应遵循光栅顺序,即在继续下一行之前完成一行的像素:
for(y = 0; y < height; y++){
for(x = 0; x < width; x++){
...
}
}
(y=0;y{
对于(x=0;x
还建议以这种方式进行处理;这不是绝对必须的,但它将减少混乱,并可能使处理速度更快(通过更有效地使用CPU缓存)。您应该使用一些更小、更简单的测试映像(例如,所有“1”或单独的“1”)对此进行调试.我看不出该代码中有任何明显的问题(当然不会给出您看到的输出),尽管存在一些较小的问题(例如,您不应该对图像使用指针数组;而应该使用单个1D数组来提高速度)。你的问题几乎可以肯定是与之前或之后的代码有关,尽管你相信。@Dave-我同意1D数组,并计划在我修复了该问题后这样做,以使代码更干净。我从其他人的示例开始使用3d数组,但我被这个问题缠住了,决定可以使用草率的数组退一步。很高兴你能证实我的想法,没有明显的问题,计算似乎是正确的。@奥利-我将尝试更小的图像,以便获得调试所需的原始数据点,谢谢。你是否为
image
和filteredImage
设置/分配了内存?你能显示这部分代码吗?不,我没有.ppm reader/writer函数中的任何重新排序,因此我继续将索引调整为[y][x][color]您指定的格式,它提供了更好的结果!我没有完全填充框中的白色,而是正确地检测边缘!这很好,但图像仍然是上图中的三倍重叠。我本来打算发布所有三个函数,但我认为一个问题发布的代码可能太多。Shou我能把所有的都贴出来吗?你也许能自己弄明白。请尝试,如果你失败了,请描述你的尝试;如果你需要阅读和写作功能的帮助,请贴出来。是的,我会尝试看看我能找到什么,我花了好几个小时在Sobel函数上,什么也没找到。现在你已经告诉我了索引作为一个问题,我要走这条路,感觉更有希望。谢谢!我只是想回来说声谢谢!你的建议奏效了,在我发布上述评论并再次查看你的帖子后,我很快就发现了我索引中的错误。这是我最后一次说我100%确定问题没有发生这个或那个。(老实说,作为一名计算机“科学家”,我应该早就知道了!我感到羞愧哈哈)
... image[y + j][x + i][0] ...
for(y = 0; y < height; y++){
for(x = 0; x < width; x++){
...
}
}