罗伯茨算子只是让图像更明亮

发布于 2024-11-19 16:39:05 字数 1532 浏览 8 评论 0原文

我发布了关于 Roberts 运算符的另一个问题,但我决定发布一个新问题,因为自那时以来我的代码发生了显着变化。

我的代码运行,但它没有生成正确的图像,而是图像变得稍微更亮。

我没有发现算法中的错误,但我知道这不是正确的输出。如果我将此程序的输出与 edge(,'roberts',); 或维基百科上的图像进行比较,它看起来与所示的 roberts 运算符的效果完全不同那里。

代码:

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

I posted another question about the Roberts operator, but I decided to post a new one since my code has changed significantly since that time.

My code runs, but it does not generate the correct image, instead the image becomes slightly brighter.

I have not found a mistake in the algorithm, but I know this is not the correct output. If I compare this program's output to edge(<image matrix>,'roberts',<threshold>);, or to images on wikipedia, it looks nothing like the effect of the roberts operator shown there.

code:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

分分钟 2024-11-26 16:39:05

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

编辑

我会尽力解释得更好一些。使用求和而不是平方/平方根的问题是您最终可能会得到负值。根据边缘方向,使用此运算符自然会出现负值。这可能就是您认为图像“变亮”的原因 - 因为当您在 MATLAB 中显示图像时,负值变为黑色,零值变为灰色,正值变为白色。这是我运行代码时得到的图像(进行了一些更改 - 主要将 NewImg 设置为 zeros(size(Img)) 所以它是一个 double 类型而不是 uint8 类型不允许负值...这是我得到的图像:结果图像

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

I think you may be misinterpreting how the Roberts Cross operator works. Use this page as a guide. Notice that it states that you convolve the original image separately with the X and Y operator. Then, you may calculate the final gradient (i.e. "total edge content") value by taking the square root of the sum of squares of the two (x and y) gradient values for a particular pixel. You're presently summing the x and y values into a single image, which will not give the correct results.

EDIT

I'll try to explain a bit better. The problem with summation instead of squaring/square root is that you can end up with negative values. Negative values are natural using this operator depending on the edge orientation. That may be why you think the image 'lightens' -- because when you display the image in MATLAB the negative values go to black, the zero values go to grey, and the positive values go to white. Here's the image I get when I run your code (with a few changes -- mostly setting NewImg to be zeros(size(Img)) so it's a double type instead of uint8. uint8 types don't allow negative values... Here's the image I get:Resulting image.

You have to be very careful when trying to save files as well. Instead of calling imwrite, call imshow(NewImg,[]). That will automatically rescale the values in the double-valued image to show them correctly, with the most negative number being equal to black and most positive equal to white. Thus, in areas with little edge content (like the sky), we would expect grey and that's what we get!

我三岁 2024-11-26 16:39:05

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

在此处输入图像描述
图 1 - 左侧为原始图像,右侧为原始罗伯茨变换图像

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

通过更改 imread 中的代码行以转换为双精度

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

(请注意,我的图像是彩色的,因此我也进行了 rgb 转换。您可以使用

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

我得到了改进的图像:

在此处输入图像描述
左边是原始代码,右边是更正后的代码。

请注意,我也可以使用 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

对于以下结果:

在此处输入图像描述

I ran your code and got the effect you described. See how everything looks lighter:

enter image description here
Figure 1 - Original on the left, original roberts transformation on the right

The image on my system was actually saturated. My image was uint8 and the operations were pushing the image past 255 or under 0 (for the negative side) and everything became lighter.

By changing the line of code in the imread to convert to double as in

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

(note my image was color so I did an rgb conversion, too. You might use

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

I got the improved image:

enter image description here
Original on left, corrected code on right.

Note that I could also produce this result using 2d convolution rather than your loop:

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

For the following result:

enter image description here

甜心小果奶 2024-11-26 16:39:05

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

%# 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
方向
vectorField
binary_edges

Here is an example implementation. You could easily replace CONV2/IMFILTER with your own 2D convolution/correlation function:

%# 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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文