如何改进我的sobel算子边缘检测?

时间:2014-08-24 06:46:20

标签: matlab image-processing computer-vision sobel

我正试图进入计算机视觉领域,开始我在MATLAB中实现了一个Sobel滤波器,我在这里读到:http://en.wikipedia.org/wiki/Sobel_operator

以下是代码:

image = double(image);
kernelx = [ -1, 0, 1;
           -2, 0, 2;
          -1, 0, 1];

kernely = [  1, 2, 1;
             0, 0, 0;
            -1, 0, 1];

height = size(image,1);
width = size(image,2);
channel = size(image,3);

for i = 2:height - 1
    for j = 2:width - 1
        for k = 1:channel
            magx = 0;
            magy = 0;
            for a = 1:3
                for b = 1:3
                    magx = magx + (kernelx(a, b) * image(i + a - 2, j + b - 2, k));
                    magy = magy + (kernely(a, b) * image(i + a - 2, j + b - 2, k));
                end;
            end;     
            edges(i,j,k) = sqrt(magx^2 + magy^2); 
        end;
    end;
end; 

这是我测试过的图像:

结果如下:

我不知道从哪里开始,我已经尝试过线条细化或阈值处理,我应该采取哪些措施让这次运行得更好?

2 个答案:

答案 0 :(得分:2)

y方向的内核似乎不正确,应该是

[1,2,1;    0,0,0;   -1,-2,-1];

此外,如果你想改进边缘检测,你可以看一下滞后,它是一种简单的方法来完成一些可能错过的图像中明显的轮廓

http://en.wikipedia.org/wiki/Canny_edge_detector#Tracing_edges_through_the_image_and_hysteresis_thresholding

答案 1 :(得分:2)

首先

结果

Resulting Cat after run over by Sobel

内核中的1个错误

正如Bharat Singh指出的那样,你的y-Kernel看起来不对。 (后来的分析显示它改变了结果,但这不是主要问题。)如果你想要,你可以在我下面的代码中使用原始内核来查看结果。 (对于子孙后代:kernely(3,:) = [-1, 0, 1];)基本上,它看起来像输入图像。

2使用卷积快速调试

在您做任何其他事情之前,只需使用Matlab提供的卷积功能。 另外,为了加快速度,请使用conv2。在进行实验时,您可能希望使用parfor而不是外部for - 循环。卷积在我的机器上瞬间完成,parfor版本需要几分钟。

3 imshow导致问题

还有一个名为imagesc的替代方案,可以自动缩放图像。或者你可以致电imshow(image, [])。但是在这种情况下的问题是每个通道看起来都正确但是Matlab自动混合通道不起作用。 (请记住它们不再是RGB,而更像是R通道衍生物| dR |的大小等)

通过单独查看每个结果通道(imshow(E(:,:,1), []))或欧几里德平均值(请参阅我的代码)来检查这一点。如果你运行imshow(E, []),你会得到惊人的亮点。如果您先通过rgb2gray传递,也会发生同样的情况。

代码

image = imread('cat.jpg');

image = double(image);
kernelx = [ -1, 0, 1;
           -2, 0, 2;
          -1, 0, 1];

kernely = [  1, 2, 1;
             0, 0, 0;
            -1, -2, -1];

height = size(image,1);
width = size(image,2);
channel = size(image,3);

edges = zeros(height, width, channel);

if exist('chooseSlow', 'var')
    parfor i = 2:height - 1
        for j = 2:width - 1
            for k = 1:channel
                magx = 0;
                magy = 0;
                for a = 1:3
                    for b = 1:3
                        magx = magx + (kernelx(a, b) * image(i + a - 2, j + b - 2, k));
                        magy = magy + (kernely(a, b) * image(i + a - 2, j + b - 2, k));
                    end;
                end;
                edges(i,j,k) = sqrt(magx^2 + magy^2);
            end;
        end;
    end;
end

%% Convolution approach
E = zeros(height, width, channel);
for k=1:channel
    Magx = conv2(image(:,:,k), kernelx, 'same');
    Magy = conv2(image(:,:,k), kernely, 'same');
    E(:,:,k) = sqrt(Magx .^2 + Magy .^2);
end

imshow(sqrt(E(:,:,1).^2 + E(:,:,2).^2 + E(:, :, 3) .^2 ), []);
print('result.png', '-dpng');