图像数据类型引发的思考

最近在研究图像的频域处理时碰到一个小问题:利用fft算法得到一幅图像的频谱,并通过显示此频谱的图像来进行可视化分析。程序如下:

I=imread('9.tif');

>> f=fft2(I);

>>fc= fftshift(abs(f));

>> imshow(fc)


这与书上得到的频谱图像差距很大:


仔细对比发现,代码和书上唯一不同的地方只有最后一句:imshow(fc,[]),那么问题应该就是出在这儿了。于是doc imshow:


扫描二维码关注公众号,回复: 894748 查看本文章

第二种用法的大致意思就是:【low,high】表示显示灰度的动态范围,低于low的值全部显示为黑色,高于high的值显示为白色,其他的值在low~high之间,显示为黑到白的均匀分配。如果为【】,则将I中最小和最大值分别作为low和high。

那么,使用第一种imshow(I)用法时,动态范围默认是多少呢?在一些书上看到说是默认【0,255】,但是经过实验却发现不是这样,有时为【0,255】,有时为【0,1】,无可奈何之下,想到查看imshow函数体,结果终于发现:


划线部分解释了:如果输入图像是单精度或双精度类型,则默认动态范围为【0,1】,否则为【0,255】。这样就很好的解开了上面的频谱图像差异的原因,I经过fft变换后为double型,且值绝大部分都大于1,而imshow(I)的默认动态范围为【0,1】,所以大范围都会显示为白色,只有一小部分为0的值显示为黑色。经查看,此时fc中最大值为204000,因此使用imshow(I,[])后动态范围被拉到【0,204000】,效果就是上面第二幅频谱图像。为了验证猜想,现在将动态范围调整到【0,500】,效果应该介于上面两幅频谱图像之间。使用语句imshow(fc,[0,500]):


到此为止,我想到之前在对图像进行运算前,总是先转换成double型,最后显示时没转成uint8型也能够正常显示。如下所示:

I=imread('0.tif');

I=im2double(I);

imshow(I);


讲道理的话,这样说不通啊!!!图像的灰度值肯定一大部分是远大于1的,动态范围缩小到【0,1】后,应该显示一幅几乎全白的图片才对啊!我想到一个问题,既然有了double函数,为什么又要弄个im2double呢?这其中肯定有戏。于是乎open im2double,果然发现问题所在:


若然开朗,原来在im2double内部已经对图像灰度值做了归一化处理,所以才能在【0,1】动态范围内显示一幅正常的图像。最后,再来验证一下上面的猜想"图像的灰度值肯定一大部分是远大于1的,动态范围缩小到【0,1】后,应该显示一幅几乎全白的图片才对啊!"这次不用im2double,用double函数就好了:

I=imread('0.tif');

I=double(I);

imshow(I);


和猜想的一样,大部分显示为白色,只有红圈标记处有一些黑点。到此为止,猜想结束,这次让我认识到,遇到不懂的函数还是多看看作者的注释,可以的话(某些函数体不公开,例如fft),最好open function打开函数体看看。

稍等,还有一个问题,很多图像处理书籍在频域处理方面,都通过显示此频谱的图像来进行可视化分析,这样虽然可以,但我个人觉得还是不够直观,新手可能会遇到诸如我这样的问题,我还是觉得用三维绘图显示频率幅度更直,如下图所示,很轻松就能看出能量大多分布在低频区域。


上图显示4个1/4周期。


猜你喜欢

转载自blog.csdn.net/u013608424/article/details/72865852
今日推荐