前言:此实验为利用低通滤波器实现图像平滑。本文并不介绍此实验的做法,而是解决,在算子函数和主函数逻辑正常的情况下,实验结果无法正常显示的细节问题。
%experiment_4_2
clc;
clear;
I1=imread('wire.jpg');
% I=rgb2gray(I);
figure;
subplot(2,2,1),imshow(I1);
title('原图像');
I=imnoise(I1,'salt & pepper',0.04);
I2=imnoise(I1,'salt & pepper',0.04);
I=im2double(I);%如果图像不是double类型的则转化为double
subplot(2,2,2);imshow(I);
title('加噪声后的图像')
s=fftshift(fft2(I));
s1=fftshift(fft2(I2));
% subplot(2,2,3);
% imshow(abs(s),[]);
% title('图像傅里叶变换后所得频谱');
subplot(2,2,3);
imshow(log(abs(s)),[]);
title('原始图像取对数后所得频谱')
Ideal(s);%
% butter(s);
% Index(s);
% Gradient(s);
理想梯度函数
%Ideal.m
function Ideal(s)
[a,b]=size(s);
a0=round(a/2);
b0=round(b/2);%找到中心点
d=10;
for i=1:a
for j=1:b
distance=sqrt((i-a0)^2+(j-b0)^2);
if distance<=d h=1;
else h=0;
end;
s(i,j)=h*s(i,j);
end;
end;
figure;
subplot(1,2,1);
imshow(log(s),[]),title('理想高通滤波器所得频谱');
**s=uint8(real(ifft2(ifftshift(s))));**
subplot(1,2,2);
**imshow(s,[]);**
title('理想高通滤波所得图像');
end
以上情况为将uint8数据类型用imshow(,[])格式显示(此函数作用:显示基于缩放显示的灰度图像imshow以[min(I(:)) max(I(:))]为显示范围,即I中最小值显示为黑色,最大值显示为白色。)即 自定义显示范围,多用于double类型数组显示。
s=uint8(real(ifft2(ifftshift(s))));
换成
s=im2uint8(real(ifft2(ifftshift(s))));
显示结果
至此,问题得到解决。
上述图片无法显示的问根源在数据类型转换问题:
1)将double类型数据转化为uint8,用uint8(img)or im2uint8(img)?
uint8(img):uint8型是0~255范围,其只是能将255.0转化为255而已
im2uint8(img):double类型数据保存图片是0-1,,此函数能将0-1的double值映射到0-255.
2)将uint8类型转化为double类型,用double(img) or im2double(img)?
但是matlab默认double类型图片数据是位于0-1之间的,而uint8是位于0-255。所以如果矩阵数据图像是double类型(0-1之间)可直接im2uint8,这样不仅完成数据类型转换,而且将0-1之间映射为了0~255之间的数据。
但是如果图像矩阵数据是double类型的0-255,直接im2uint8转换的话,matlab会将大于1的数据都转换为255,0-1之间的数据才会映射到0-255之间整型的数据。例如下面程序:
img64 = [1,2,3,4];
I8 = im2uint8(img64); % I8结果为[255 255 255 255]
总结:由于MATLAB的特性,一般用uint8保存图片,而计算时为保证精度,要转化为double。在转化的时候,要根据矩阵的范围和数据类型,合理选择转化函数就会避免此情况。
s=uint8(real(ifft2(ifftshift(s))));
变成
s=real(ifft2(ifftshift(s)));
imshow(s);
两者有略微区别,这是因为imshow(A)与imshow(A,[])两者都是显示图片, 如果A的灰度都在20以下,但确实又有灰度变化,你直接imshow看起来几乎都是黑的,imshow(A,[])后会从最小到最大拉伸显示,使显示的图片对比度差距更明显,所以会感觉上一张图片的内容会更加丰富一些,体现的理想滤波器的振铃效应也更加明显一些。可以确定的是,在子函数中将逆傅里叶变换的函数强制转化为uint8类型矩阵会丢失信息。
在matlab处理完数据好,我们希望显示或者imwrite写入图片时候,需要注意。如果直接对double之间的数据矩阵I运行imshow(I),我们会发现有时候显示的是一个白色的图像。
这是因为imshow()显示图像时对double型是认为在0-1范围内,即大于1时都是显示为白色,而imshow显示uint8型时是0-255范围。所以对double类型的图像显示的时候,要么归一化到0-1之间,要么将double类型的0-255数据转为uint8类型。解决方法如下:
imshow(I/255); % 将图像矩阵转化到0-1之间
imshow(I,[]); % 自动调整数据的范围以便于显示
inshow(uint8(I)); % 转成uint8