1

Roberts 演算子に関する別の質問を投稿しましたが、その時からコードが大幅に変更されたため、新しい質問を投稿することにしました。

私のコードは実行されますが、正しい画像が生成されず、代わりに画像がわずかに明るくなります。

アルゴリズムに間違いは見つかりませんでしたが、これが正しい出力ではないことはわかっています。このプログラムの出力をedge(<image matrix>,'roberts',<threshold>);やウィキペディアの画像と比較すると、そこに示されている 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
4

3 に答える 3

3

ロバーツクロス演算子の仕組みを誤解している可能性があります。このページをガイドとして使用してください。X 演算子と Y 演算子を使用して元の画像を個別に畳み込むと記載されていることに注意してください。次に、特定のピクセルの 2 つの (x および y) 勾配値の平方和の平方根をとることにより、最終的な勾配 (つまり、「エッジの合計」) 値を計算できます。現在、x 値と y 値を 1 つの画像に合計しているため、正しい結果が得られません。

編集

もう少しうまく説明しようと思います。平方/平方根ではなく合計の問題は、負の値になる可能性があることです。エッジの向きに応じて、この演算子を使用すると負の値が自然になります。これが、イメージが「明るくなる」と考える理由かもしれません。MATLAB でイメージを表示すると、負の値は黒になり、ゼロの値は灰色になり、正の値は白になるためです。コードを実行したときに得られる画像を次に示します (いくつかの変更を加えて、主に .ではなく型にNewImgなるzeros(size(Img))ように設定します。型は負の値を許可しません... これが私が取得する画像です: .doubleuint8uint8結果の画像

ファイルを保存しようとするときも、非常に注意する必要があります。を呼び出す代わりにimwrite、を呼び出しますimshow(NewImg,[])。これにより、 値の画像の値が自動的に再スケーリングされ、double正しく表示されます。最も負の数は黒に等しく、最も正の数は白に等しくなります。したがって、エッジ コンテンツがほとんどない領域 (空など) では、灰色が予想され、それが得られます。

于 2011-07-12T16:49:18.687 に答える
1

私はあなたのコードを実行し、あなたが説明した効果を得ました。すべてが明るく見える様子をご覧ください:

ここに画像の説明を入力 図 1 - 左がオリジナル、右がオリジナルの roberts 変換

私のシステムの画像は実際には飽和していました。私のイメージは uint8 で、操作はイメージを 255 を超えて、または 0 未満 (マイナス側) にプッシュし、すべてが明るくなりました。

imread のコード行を double に変換するように変更する

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

次の結果の場合:

ここに画像の説明を入力

于 2011-07-12T17:07:05.757 に答える
0

実装例を次に示します。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

勾配 方向 ベクトルフィールド binary_edges

于 2011-07-14T17:37:44.430 に答える