问题复制MATLAB
我正在尝试了解Matlab的Imfilter
函数的工作方式。
im = imread("cameraman.tif");
% Kernel for sharpening the image
kernel = [
0 -1 0;
-1 5 -1;
0 -1 0];
im2 = zeros(size(im));
for y = 1 : size(im,1) - 3
for x = 1 : size(im,2) - 3
sum = 0;
for ky = 1:3
for kx = 1:3
xx = x + kx - 1;
yy = y + ky - 1;
sum = sum + im(yy,xx)*kernel(ky,kx);
end
end
im2(y,x) = sum;
end
end
% Map im2 to 0 - 255
im2 = im2 - min(im2(:));
im2 = im2 / max(im2(:)) * 255;
im2 = uint8(im2);
subplot(131), imshow(im), title('Original Image')
subplot(132), imshow(imfilter(im,kernel)), title('Matlab imfilter')
subplot(133), imshow(im2), title('My filter')
边界的差异不是我的关注,而是我的结果(右侧的子图)与MATLAB产生的(中间子图)显然不同,尽管使用了相同的内核。
我可以知道会有什么偏差?据我所知,内核贴片将应用于图像元素,并在结果上概括。有人可以让我知道我想念什么吗?谢谢。
I am trying to understand how MATLAB's imfilter
function works.
im = imread("cameraman.tif");
% Kernel for sharpening the image
kernel = [
0 -1 0;
-1 5 -1;
0 -1 0];
im2 = zeros(size(im));
for y = 1 : size(im,1) - 3
for x = 1 : size(im,2) - 3
sum = 0;
for ky = 1:3
for kx = 1:3
xx = x + kx - 1;
yy = y + ky - 1;
sum = sum + im(yy,xx)*kernel(ky,kx);
end
end
im2(y,x) = sum;
end
end
% Map im2 to 0 - 255
im2 = im2 - min(im2(:));
im2 = im2 / max(im2(:)) * 255;
im2 = uint8(im2);
subplot(131), imshow(im), title('Original Image')
subplot(132), imshow(imfilter(im,kernel)), title('Matlab imfilter')
subplot(133), imshow(im2), title('My filter')
Differences at the boundaries are not my concern but my result (the subplot at the right) is clearly different than what MATLAB produces (the middle subplot) although the same kernel was used.
May I know what could be the deviation? As far as I know, kernel patch will be applied to the image element-wise and be summed over the result. Could someone let me know what I am missing? Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的错误是在这一行中:
这并不明显,但是Matlab在使用不同的数据类型进行算术时会做出一个奇怪的选择。在MATLAB中,默认情况下,所有数字阵列(所有值)都是双重的。
sum
是double*初始化时(sum = 0
),内核
和im2
也是如此。但是im
是一个8位未签名的整数数组。因此,im(YY,xx)*内核(KY,KX)
对UINT8进行倍增8。这是将不同数据类型组合在操作中的奇怪情况。当使用整数数组进行算术时,另一个操作数必须具有相同的类型,除非它是双标量表(1x1双阵列)。在这种情况下,标量值将转换为整数类型,然后应用操作。同样,整数算术饱和,这意味着整数范围之外的任何结果都夹在范围内(没有其他语言中的溢出)。
因此,
im(YY,XX)*内核(KY,KX)
导致UINT8。接下来,sum +< uint8结果>
也是UINT8值,该值分配给sum
。现在sum
是UINT8!要解决此问题,请
*请注意,所有内容都是一个数组。
0
是一个1x1数组。未经请求的建议:
您不应缩放
im2
图像,您应该将其直接投放到uint8
。 MATLAB将为您限制[0,255]范围的值。缩放会导致对比的丢失。不要使用
sum
作为变量名称。sum
是一个内置功能,您可以使用此变量来遮盖它(使其不可用)。运行代码后,您不能再做sum(im(:))
。内部两个循环非常容易矢量化:
或最近版本的Matlab,
(并在此处注意
sum
函数的需求!)Your bug is in this line:
This is not obvious, but MATLAB makes a strange choice when doing arithmetic with different data types. In MATLAB, by default all numeric arrays (all values) are doubles.
sum
is double* when you initialize it (sum = 0
), as arekernel
andim2
. Butim
is an 8-bit unsigned integer array. Soim(yy,xx)*kernel(ky,kx)
does a multiplication of a uint8 with a double. This is the strange case of combining different data types in an operation.When doing arithmetic with an integer array, the other operand must be of the same type, unless it is a double scalar (a 1x1 double array). In this case, the scalar value is converted to the integer type, then the operation is applied. Also, integer arithmetic is saturated, meaning that any result outside of the integer range is clamped to the range (there is no overflow as in other languages).
So
im(yy,xx)*kernel(ky,kx)
results in a uint8. Next,sum + <uint8 result>
is also a uint8 value, which is assigned tosum
. Nowsum
is uint8!To fix this, do
* Also note that everything is an array.
0
is a 1x1 array.Unsolicited advice:
You should not scale the
im2
image, you should directly cast it touint8
. MATLAB will clamp the values to the [0,255] range for you. Scaling causes loss of contrast.Don't use
sum
as a variable name.sum
is a built-in function, which you shadow (make unavailable) with this variable. After running your code, you can no longer dosum(im(:))
, for example.The inner two loops are very easily vectorized:
or, in very recent versions of MATLAB,
(And note the need for the
sum
function here!)