使用用户定义函数的卷积内核。如何处理负像素值?

时间:2019-02-17 18:45:35

标签: matlab image-processing convolution

我已经声明了一个函数,该函数将使用任意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 :(得分:0)

MATLAB在处理不同数据类型之间的操作方面非常独特。如果xuint8(在这种情况下很可能),而mdouble(在这种情况下很可能),则此操作:

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

返回一个uint8值,而不是一个double。 MATLAB中的算法始终采用非double参数的类型。 (而且,除非其中一种是double,否则您不能在两种不同的类型之间进行算术运算。)

MATLAB进行带饱和的整数运算。这意味着uint8(5) * -1给出0,而不是-5,因为uint8不能代表负值。

因此,您所有的Z1 .. Z9均为uint8值,负结果已设置为0。现在,您将所有这些都加法并再次饱和,得出的值为最多255。此值分配给输出(双精度)。因此,看起来您正在正确执行计算并输出一个double数组,但是您仍在以奇怪的方式限制结果。

正确的实现会将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