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

问题描述 投票:1回答:1

我已经声明了一个函数,它将用于使用任意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)]);

我试图使用卷积的绝对值,以及尝试在输出图像中定位负片,但没有任何效果。

这是原始图片:

这是我使用内核时得到的图像[-1 -1 -1; -1 9 -1; -1 -1 -1]:

我不知道我做错了什么。

matlab image-processing convolution
1个回答
0
投票

MATLAB在处理不同数据类型之间的操作方面非常独特。如果xuint8(因为它可能在这种情况下),并且mdouble(因为它可能在这种情况下),那么这个操作:

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
© www.soinside.com 2019 - 2024. All rights reserved.