我已经声明了一个函数,该函数将使用任意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]:
我不知道我在做什么错。
答案 0 :(得分:0)
MATLAB在处理不同数据类型之间的操作方面非常独特。如果x
是uint8
(在这种情况下很可能),而m
是double
(在这种情况下很可能),则此操作:>
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