我試圖了解 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 產生的結果(中間的子圖),盡管使用了相同的內核。

我可以知道可能是什么偏差嗎?據我所知,內核補丁將按元素應用于影像并在結果上求和。有人可以讓我知道我錯過了什么嗎?謝謝。
uj5u.com熱心網友回復:
你的錯誤在這一行:
sum = sum im(yy,xx)*kernel(ky,kx);
這并不明顯,但 MATLAB 在對不同資料型別進行算術運算時做出了一個奇怪的選擇。在 MATLAB 中,默認情況下所有數值陣列(所有值)都是雙精度數。sum初始化時是 double* ( sum = 0),kernel和im2. 但是im是一個 8 位無符號整數陣列。im(yy,xx)*kernel(ky,kx)uint8 與雙精度數的乘法也是如此。這是在一個操作中組合不同資料型別的奇怪情況。
對整數陣列進行算術運算時,另一個運算元必須屬于同一型別,除非它是雙精度標量(1x1 雙精度陣列)。在這種情況下,將標量值轉換為整數型別,然后應用操作。此外,整數算術是飽和的,這意味著整數范圍之外的任何結果都被限制在該范圍內(沒有其他語言中的溢位)。
所以im(yy,xx)*kernel(ky,kx)結果是一個uint8。接下來,sum <uint8 result>也是一個 uint8 值,分配給sum. 現在sum是uint8!
要解決此問題,請執行
sum = sum double(im(yy,xx)) * kernel(ky,kx);
* 另請注意,一切都是陣列。0是一個 1x1 陣列。
不請自來的建議:
您不應該縮放
im2影像,您應該直接將其轉換為uint8. MATLAB 將為您將值限制在 [0,255] 范圍內。縮放會導致對比度損失。不要
sum用作變數名。sum是一個內置函式,您可以使用此變數對其進行隱藏(使其不可用)。例如,在運行您的代碼后,您將無法再做sum(im(:))。內部的兩個回圈很容易矢量化:
tmp = double(im(x (0:2), y (0:2))) .* kernel; im2(y,x) = sum(tmp(:));或者,在最新版本的 MATLAB 中,
im2(y,x) = sum(double(im(x (0:2), y (0:2))) .* kernel, 'all');(并注意此處需要該
sum功能!)
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/480648.html
上一篇:將影像檔案夾批量調整為兩種不同的大小并重命名檔案imagemagick(MacOS)
下一篇:在3D中銳化內核過濾器
