罗伯茨操作员只是使图像更亮

时间:2011-07-12 16:22:25

标签: matlab image-processing edge-detection

我发布了另一个关于Roberts运算符的问题,但我决定发布一个新的问题,因为从那时起我的代码发生了重大变化。

我的代码运行,但它不会生成正确的图像,而是图像变得稍微亮一点。

我没有在算法中发现错误,但我知道这不是正确的输出。如果我将此程序的输出与edge(<image matrix>,'roberts',<threshold>);或维基百科上的图像进行比较,它看起来就像在那里显示的罗伯茨运算符的效果。

代码:

function [] = Robertize(filename)

Img = imread(filename);
NewImg = Img;

SI = size(Img);

I_W = SI(2)
I_H = SI(1) 

Robertsx = [1,0;0,-1];
Robertsy = [0,-1;1,0];

M_W = 2; % do not need the + 1, I assume the for loop means while <less than or equal to>

% x and y are reversed... 

    for y=1 : I_H
        for x=1 : I_W 

            S = 0;

            for M_Y = 1 : M_W
                for M_X = 1 : M_W


                    if (x + M_X - 1  < 1) || (x + M_X - 1 > I_W)
                       S = 0;      
                       %disp('out of range, x');

                       continue
                    end

                    if (y + M_Y - 1  < 1) || (y + M_Y - 1 > I_H)
                       S = 0; 
                       %disp('out of range, y');

                       continue      
                    end

                   S = S + Img(y + M_Y - 1 , x + M_X - 1) * Robertsx(M_Y,M_X);
                   S = S + Img(y + M_Y - 1, x + M_X - 1) * Robertsy(M_Y,M_X);

               % It is y + M_Y - 1 because you multiply Robertsx(1,1) *
               % Img(y,x).

                end

            end

            NewImg(y,x) = S;
        end


    end  


imwrite(NewImg,'Roberts.bmp');
end

3 个答案:

答案 0 :(得分:3)

我认为你可能误解了Roberts Cross运算符的工作原理。使用this page作为指南。请注意,它声明您将原始图像单独与X和Y运算符进行卷积。然后,您可以通过取特定像素的两个(x和y)梯度值的平方和的平方根来计算最终梯度(即“总边缘内容”)值。您现在正在将x和y值相加到单个图像中,这将无法给出正确的结果。

修改

我会尝试更好地解释一下。求和而不是平方根/平方根的问题是你可以得到负值。根据边缘方向,使用此运算符的负值是自然的。这可能是您认为图像“变亮”的原因 - 因为当您在MATLAB中显示图像时,负值变为黑色,零值变为灰色,正值变为白色。这是我运行代码时获得的图像(有一些更改 - 主要是将NewImg设置为zeros(size(Img)),因此它是double类型而不是uint8。{{ 1}}类型不允许负值...这是我得到的图像:Resulting image

在尝试保存文件时,您必须非常小心。请致电uint8,而不是致电imwrite。这将自动重新调整imshow(NewImg,[]) - 值图像中的值以正确显示它们,其中最负数等于黑色,最正数等于白色。因此,在边缘内容很少的区域(如天空),我们会期待灰色,这就是我们得到的!

答案 1 :(得分:1)

我运行了你的代码并获得了你描述的效果。看看一切看起来如何轻松:

enter image description here 图1 - 左侧的原始,右侧的原始罗伯茨转换

我系统上的图像实际上已经饱和了。我的图像是uint8,操作将图像推过255或低于0(对于负面),一切都变得更轻。

通过更改imread中的代码行转换为双倍,如

Img = double(rgb2gray( imread(filename)));

(注意我的图像是彩色的,所以我也进行了rgb转换。你可以使用

Img = double(( imread(filename)));

我得到了改进的图像:

enter image description here 左边的原件,右边的修正代码。

请注意,我也可以使用2d卷积而不是循环来生成此结果:

Robertsx = [1,0;0,-1];
Robertsy = [0,-1;1,0];

dataR = conv2(data, Robertsx) + conv2(data, Robertsy);

figure(2);
imagesc(dataR);
colormap gray
axis image

以下结果:

enter image description here

答案 2 :(得分:0)

这是一个示例实现。您可以使用自己的2D卷积/相关函数轻松替换CONV2 / IMFILTER:

%# convolve image with Roberts kernels
I = im2double(imread('lena512_gray.jpg'));    %# double image, range [0,1]
hx = [+1 0;0 -1]; hy = [0 +1;-1 0];
%#Gx = conv2(I,hx);
%#Gy = conv2(I,hy);
Gx = imfilter(I,hx,'conv','same','replicate');
Gy = imfilter(I,hy,'conv','same','replicate');

%# gradient approximation
G = sqrt(Gx.^2+Gy.^2);
figure, imshow(G), colormap(gray), title('Gradient magnitude [0,1]')

%# direction of the gradient
Gdir = atan2(Gy,Gx);
figure, imshow(Gdir,[]), title('Gradient direction [-\pi,\pi]')
colormap(hot), colorbar%, caxis([-pi pi])

%# quiver plot
ySteps = 1:8:size(I,1);
xSteps = 1:8:size(I,2);
[X,Y] = meshgrid(xSteps,ySteps);
figure, imshow(G,[]), hold on
quiver(X, Y, Gx(ySteps,xSteps), Gy(ySteps,xSteps), 3)
axis image, hold off

%# binarize gradient, and compare against MATLAB EDGE function
BW = im2bw(G.^2, 6*mean(G(:).^2));
figure
subplot(121), imshow(BW)
subplot(122), imshow(edge(I,'roberts'))   %# performs additional thinning step

gradient direction vectorField binary_edges