Ядро свертки с использованием определенной пользователем функции.Как бороться с отрицательными значениями пикселей? - PullRequest
0 голосов
/ 17 февраля 2019

Я объявил функцию, которая будет использоваться для вычисления свертки изображения с использованием произвольного ядра 3x3.Я также создал скрипт, который будет предлагать пользователю выбрать оба изображения, а также ввести ядро ​​свертки по своему выбору.Однако я не знаю, как поступить с отрицательными значениями пикселей, которые возникнут для различных ядер.Как мне внедрить условие в мой скрипт, которое будет работать с этими отрицательными значениями?

Это моя функция:

    function y = convul(x,m,H,W)
    y=zeros(H,W);

    for i=2:(H-1)
        for j=2:(W-1)
         Z1=(x(i-1,j-1))*(m(1,1));
         Z2=(x(i-1,j))*(m(1,2));
         Z3=(x(i-1,j+1))*(m(1,3));
         Z4=(x(i,j-1))*(m(2,1));
         Z5=(x(i,j))*(m(2,2));
         Z6=(x(i,j+1))*(m(2,3));
         Z7=(x(i+1,j-1))*(m(3,1));
         Z8=(x(i+1,j))*(m(3,2));
         Z9=(x(i+1,j+1))*(m(3,3));
         y(i,j)=Z1+Z2+Z3+Z4+Z5+Z6+Z7+Z8+Z9;
        end 
    end 

И это сценарий, который я написал, который предлагает пользователю ввести изображение и выбрать ядро ​​по своему выбору:

    [file,path]=uigetfile('*.bmp');
    x = imread(fullfile(path,file));        
    x_info=imfinfo(fullfile(path,file));    

    W=x_info.Width;                 
    H=x_info.Height;                
    L=x_info.NumColormapEntries;    
    prompt='Enter a convulation kernel m: ';
    m=input(prompt)/9;
    y=convul(x,m,H,W);
    imshow(y,[0,(L-1)]);

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

Это оригинальное изображение:

Original Image

Это изображение, которое я получаю, когда использую ядро ​​[-1 -1 -1; -1 9 -1;-1 -1 -1]:

Edited image

Я не знаю, что я делаю неправильно.

1 Ответ

0 голосов
/ 19 февраля 2019

MATLAB довольно уникален тем, как он обрабатывает операции между различными типами данных.Если x равно uint8 (как, вероятно, в этом случае), а m равно double (как, вероятно, и в этом случае), то эта операция:

Z1=(x(i-1,j-1))*(m(1,1));

возвращаетзначение uint8, а не double.Арифметика в MATLAB всегда принимает тип не двойного аргумента.(И вы не можете делать арифметику между двумя разными типами, если только один из них не равен double.)

MATLAB выполняет целочисленную арифметику с насыщением.Это означает, что uint8(5) * -1 дает 0, а не -5, потому что uint8 не может представлять отрицательное значение.

Так что все ваши Z1 .. Z9 являются значениями uint8, отрицательные результаты былиустановите на 0. Теперь вы добавляете все это, опять же с насыщением, приводя к значению не более 255. Это значение присваивается выходу (двойному).Таким образом, похоже, что вы делаете свои вычисления правильно и выводите двойной массив, но вы все еще ограничиваете свой результат странным образом.

Корректная реализация будет приводить каждое из значений от x до double перед умножением на потенциально отрицательное число.Например:

for i = 2:H-1
   for j = 2:W-1
      s = 0;
      s = s + double(x(i-1,j-1))*m(1,1);
      s = s + double(x(i-1,j))*m(1,2);
      s = s + double(x(i-1,j+1))*m(1,3);
      s = s + double(x(i,j-1))*m(2,1);
      s = s + double(x(i,j))*m(2,2);
      s = s + double(x(i,j+1))*m(2,3);
      s = s + double(x(i+1,j-1))*m(3,1);
      s = s + double(x(i+1,j))*m(3,2);
      s = s + double(x(i+1,j+1))*m(3,3);
      y(i,j) = s;
   end 
end

(обратите внимание, что я исключил использование вами 9 различных переменных, я думаю, что это чище, и я также удалил много ненужных скобок!)

Прощереализация будет:

for i = 2:H-1
   for j = 2:W-1
      s = double(x(i-1:i+1,j-1:j+1)) .* m;
      y(i,j) = sum(s(:));
   end 
end
...