Робертс Оператор просто делает изображение ярче - PullRequest
1 голос
/ 12 июля 2011

Я опубликовал еще один вопрос об операторе Робертса, но я решил опубликовать новый, поскольку с того времени мой код значительно изменился.

Мой код выполняется, но он не генерирует правильное изображение, вместо этого изображение становится немного ярче.

Я не нашел ошибку в алгоритме, но я знаю, что это неверный вывод. Если я сравню вывод этой программы с 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 ]

3 голосов
/ 12 июля 2011

Я думаю, что вы, возможно, неправильно истолковываете, как работает оператор Roberts Cross. Используйте эту страницу в качестве руководства. Обратите внимание, что в нем говорится, что вы сверните исходное изображение отдельно с помощью операторов X и Y. Затем вы можете рассчитать окончательное значение градиента (то есть «общее содержание ребер»), взяв квадратный корень из суммы квадратов двух (x и y) значений градиента для конкретного пикселя. В настоящее время вы суммируете значения x и y в одно изображение, что не даст правильных результатов.

EDIT

Я постараюсь объяснить немного лучше. Проблема с суммированием вместо квадратного / квадратного корня состоит в том, что вы можете получить отрицательные значения. Отрицательные значения естественны при использовании этого оператора в зависимости от ориентации ребра. Возможно, поэтому вы думаете, что изображение «светлее» - потому что при отображении изображения в MATLAB отрицательные значения переходят в черный цвет, нулевые значения переходят в серый, а положительные значения переходят в белый. Вот изображение, которое я получаю, когда запускаю ваш код (с некоторыми изменениями - в большинстве случаев для NewImg устанавливается значение zeros(size(Img)), поэтому тип double вместо типов uint8. uint8 не допускает отрицательных значений ... Вот изображение, которое я получаю: Resulting image.

Вы также должны быть очень осторожны при попытке сохранить файлы. Вместо того, чтобы звонить imwrite, звоните imshow(NewImg,[]). Это автоматически изменит масштаб значений в double -значном изображении, чтобы показать их правильно, с самым отрицательным числом, равным черному, и самым положительным, равным белому. Таким образом, в областях с небольшим краевым содержимым (например, в небе) мы ожидаем серый цвет, и это то, что мы получаем!

1 голос
/ 12 июля 2011

Я запустил твой код и получил эффект, который ты описал. Посмотрите, как все выглядит светлее:

enter image description here Рисунок 1 - Оригинал слева, оригинальное преобразование Робертса справа

Изображение в моей системе было действительно насыщенным. Мое изображение было uint8, и операции выдвигали изображение за 255 или ниже 0 (для отрицательной стороны), и все стало светлее.

Изменяя строку кода в imread для преобразования в double, как в

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

0 голосов
/ 14 июля 2011

Вот пример реализации. Вы можете легко заменить 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 direction vectorField binary_edges

...