OpenCV中的傅里叶的门道

接触到傅里叶-梅林算法,需要用到傅里叶变换,于是去查了一下OpenCV中的实现方法,没想到习以为常的傅里叶变换之中的门道还不少。

//傅里叶变换https://blog.csdn.net/keith_bb/article/details/53389819Mat I = imread("Lena.jpg", IMREAD_GRAYSCALE);       //读入图像灰度图//判断图像是否加载成功if (I.empty()){cout << "图像加载失败!" << endl;return -1;}elsecout << "图像加载成功!" << endl << endl;Mat padded;                 //以0填充输入图像矩阵int m = getOptimalDFTSize(I.rows);//为了使dft()运算更高效,改变尺寸,注意参数是行/列int n = getOptimalDFTSize(I.cols);//一个数组尺寸是2、3、5的倍数(例如:300 = 5*5*3*2*2)同样有很高的处理效率//填充输入图像I,输入矩阵为padded,上方和左方不做填充处理copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));//中间四个参数是int型,代表四个方向填充的长度,填充之后得到paddedMat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };//Mat_<float>对应的是CV_32F 这是创建了一个Mat类型的数组,两个元素大小都是padded,类型都是float为延扩后的图像增添一个初始化为0的通道Mat complexI;merge(planes, 2, complexI);     //将planes融合合并成一个多通道数组complexI//这个函数将单通道的数组融合起来,第一个参数是指向mat的指针/*imshow("complexI", complexI);waitKey();*///会溢出,因为complex是mat数组,用于存放实部和虚部dft(complexI, complexI);        //进行傅里叶变换 src不能是padded//注意这里的输入图像不是原图也不是padded,而是融合得到的complexI//支持图像原地计算 (输入输出为同一图像)//计算幅值,转换到对数尺度(logarithmic scale)//=> log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))split(complexI, planes);        //planes[0] = Re(DFT(I),planes[1] = Im(DFT(I))//即planes[0]为实部,planes[1]为虚部magnitude(planes[0], planes[1], planes[0]);     //将求得的幅度放在planes[0],planes[0] = magnitudeMat magI = planes[0];magI += Scalar::all(1);//加1(为了取对数之后全为整数吧0之后才取对数,为了将灰度值跨度缩小,增强可视化效果log(magI, magI);       //线性尺度转换到对数尺度(logarithmic scale)//剪切和象限变换//如果有奇数行或列,则对频谱进行裁剪magI = magI(Rect(0, 0, magI.cols&-2, magI.rows&-2));//这个按位与什么意思?//x&-2代表x与-2按位相与,-2的二进制形式为:1111 1110,在x与-2按位相与后,不管x是奇数还是偶数,最后x都会变成一个偶数https://blog.csdn.net/autocyz/article/details/48803859//重新排列傅里叶图像中的象限,使得原点位于图像中心int cx = magI.cols / 2;int cy = magI.rows / 2;Mat q0(magI, Rect(0, 0, cx, cy));       //左上角图像划定ROI区域Mat q1(magI, Rect(cx, 0, cx, cy));      //右上角图像Mat q2(magI, Rect(0, cy, cx, cy));      //左下角图像Mat q3(magI, Rect(cx, cy, cx, cy));     //右下角图像//变换左上角和右下角象限Mat tmp;q0.copyTo(tmp);q3.copyTo(q0);tmp.copyTo(q3);//变换右上角和左下角象限q1.copyTo(tmp);q2.copyTo(q1);tmp.copyTo(q2);//归一化处理,用0-1之间的浮点数将矩阵变换为可视的图像格式Mat magI01;normalize(magI, magI01, 0, 1, CV_MINMAX);//0和1分别是下限和上限,范围归一化,而不是数值归一化imshow("输入图像", I);imshow("频谱图", magI01);//imshow对float数据会扩大255倍,这也是归一化到0~1的原因imwrite("Fouier0101.jpg", magI01);

傅里叶变换后求得的幅值没有经过对数尺度变换,而直接范围归一化在0~1:


没有对数尺度变换,也没有范围归一化:


可以看到直接求得的幅值都很大,即频率成分都很高。

对数尺度变换后,但没有范围归一化:

看不出来什么差别,不过中心点黑点变得不明显了。

对数尺度变换后归一化在0~1:

没有对数尺度变换,直接归一化在0~255:

对数尺度变换后归一化在0~255:

对数尺度变换后归一化在0~2:

Normalize之后imshow问题:

将图像范围归一化在0~1,图像会是近似成全黑的,imwrite保存到本地后查看图像也验证了确实如此,但为什么opencv打开的频谱图效果良好呢?(OpenCV的工作路径是项目下的,不是解决方案)

咨询了一下师兄,师兄认为是imshow的问题,因为matlab中的imshow就可选对不同数据进行不同的展示方法。猜测imshow对normalize之后是0~1之间的浮点数有一个特别的操作,而不是简单的将0~1之间的浮点数作为最终展示的图像的灰度值。查了一下资料果然如此:

    如果载入的图像是8位无符号类型(8-bitunsigned),就显示图像本来的样子。

    如果图像是16位无符号类型(16-bitunsigned)或32位整型(32-bit integer),便用像素值除以256。也就是说,值的范围是[0,255 x 256]映射到[0,255]。

如果图像是32位浮点型(32-bitfloating-point),像素值便要乘以255。也就是说,该值的范围是[0,1]映射到[0,255]。有个术语称之为亮度图像。但为什么归一化到0~1再乘255和直接归一化在0~255的效果不同呢,这是因为取对数后的频谱依然存在大量大于255的幅值,如果直接归一化在0~255,这些大于255的数值依然是255.归一化在0~1再乘255相当于进行了缩放,先缩小范围在0~1(尽管大量的值依然集中在1附近),然后按比例放大到图像灰度值的范围。

有的资料甚至说OpenCV的imshow不允许处理除了uchar(8-bitunsigned)以外的数据类型。如果保存成jpeg格式,每个像素用24bit真彩表示,JPG是有损压缩。JPG是有损压缩,PNG是无损压缩,bmp没有经过压缩。

DFT函数问题:

dft(complexI,complexI);DFT要分别计算实部和虚部,把要处理的图像作为输入的实部、一个全零的图像作为输入的虚部。dft()输入和输出应该分别为单张图像,所以要先用merge()把实虚部图像合并,分别处于图像comImg的两个通道内。计算得到的实虚部仍然保存在comImg的两个通道内。

傅里叶变换的最优尺寸问题

getOptimalDFTSize函数得到最优的行列数,然后使用copyMakeBorder进行填充。数组的大小是2的整数次幂的情况,dft变换的速度是最快的。当然,大部分情况下,数组的大小不会是2的次幂,但是如果其大小可以分解为2、3、5的累成也是能够提高dft的效率的。

附dft在python中的实现:

#!/usr/bin/env.python
#!/usr/bin/env.python
import cv2 as cv
import numpy as np
from matplotlib import pyplot as pltimg = cv.imread('Joseph_Fourier_250.jpg', 0)
f = np.fft.fft2(img)  # 快速傅里叶变换算法得到频率分布
fshift = np.fft.fftshift(f)  # 默认结果中心点位置是在左上角,转移到中间位置fimg = np.log(np.abs(fshift)+1)  # fft 结果是复数,求绝对值结果才是振幅(化为实数)
cv.imwrite("dft.bmp",fimg);
fimg0=np.log(np.abs(f)+1)  #取对数可以将数据变化范围缩小# 展示结果
plt.subplot(131), plt.imshow(img, 'gray'), plt.title('Original Fourier')
plt.subplot(132), plt.imshow(fimg0, 'gray'), plt.title('Fourier Fourier')
plt.subplot(133), plt.imshow(fimg, 'gray'), plt.title('Fourier Fourier-shift')
plt.show()

Python代码没有图像填充等操作,直接对图像进行dft变换,中心平移后取对数。但保存频谱图再查看会发现保存的频谱图的灰度值依然在0~1区间。


Reference:

1.      代码opencv\sources\samples\cpp\dft.cpp

2.      乘以255https://blog.csdn.net/honey1992/article/details/50055615

3.      imshow不允许除uchar以外https://blog.csdn.net/kelvin_yan/article/details/50033981

4.      JPG、PNGhttps://www.cnblogs.com/skyfsm/p/7136709.html

5.      http://johnhany.net/2013/11/dft-based-text-rotation-correction/

6.      补码按位与偶数https://blog.csdn.net/autocyz/article/details/48803859


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/493681.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Science:人类迎来目前最为全面的癌症染色质可及性图谱

来源&#xff1a;吴晓波频道摘要&#xff1a;肿瘤在世界范围内导致人类死亡的首要原因之一&#xff0c;尤其是随着医疗水平的发展&#xff0c;人类的寿命的不断延长&#xff0c;癌症逐渐成为威胁人类健康的首要因素。肿瘤在世界范围内导致人类死亡的首要原因之一&#xff0c;尤…

傅里叶变换频谱的可视化保存

在上一篇关于傅里叶变换的博客中&#xff0c;知道了imshow的一个小trick&#xff1a;对normalize得到的0~1之间的浮点数构成的矩阵会进行放大255的操作&#xff0c;得到可视化的灰度图。即便是在python中也是如此操作的&#xff0c;只不过python中的函数封装得更加严密&#xf…

她取代马斯克成特斯拉新董事长 究竟什么来头?

来源&#xff1a;智车科技摘要&#xff1a;就如乔布斯之于苹果&#xff0c;对很多人来说&#xff0c;马斯克对特斯拉而言也有非凡的意义。甚至可以说&#xff0c;特斯拉的品牌吸引力很大程度上来自于“钢铁侠”本人。但由于当初任性发布“私有化”消息&#xff0c;被美国证交会…

十二天深入理解计算机系统(一)

计算机系统漫游 1 信息就是位上下文 系统中所有的信息都是由一串位表示的&#xff0c;在不同的上下文中&#xff0c;一个同样的字节序列可能表示一个整数、浮点数、字符串或者机器指令。 2 文本文件和二进制文件 有ASCII字符构成的文件称为文本文件&#xff0c;所有其他文件都是…

李航《统计学习方法》-----朴素贝叶斯

朴素贝叶斯法nave Bayes&#xff0c;在nave的中间字母上其实有两个点&#xff0c;查了一下才发现是法语中的分音符&#xff0c;在发音过程中发挥作用。但这不是重要的&#xff0c;重要的是在这种学习方法中贝叶斯承担了什么样的角色。 首先简单证明一下贝叶斯公式。联合概率Joi…

IEEE专访李开复:人类已打开潘多拉盒子,封堵AI变革只会徒劳

来源&#xff1a;《IEEE Spectrum》摘要&#xff1a;近期&#xff0c;李开复新书《AI未来》在美国同样反响不俗。在荣登多个排行榜后&#xff0c;IEEE旗下《IEEE Spectrum》&#xff0c;对李开复进行了专访&#xff0c;谈到了众多当前AI领域最受关注的话题。而且从《IEEE Spect…

Rand函数使用和对补码的理解

下面是在牛客网看到的一道题; //假设这n个数的序号依次为0,1,2,...,n-1,数组名为num void knuth1(int* pNum, int m, int n){srand((unsigned int)time(0));for (int i0; i<n; i){if (rand()%(n-i) < m)//rand()%(n-i)的取值范围是[0, n-i&#xff09;{cout << p…

深度学习巨头Yoshua Bengio清华演讲: 深度学习通往人类水平人工智能的挑战

来源&#xff1a;专知摘要&#xff1a;2018年11月7日晚&#xff0c;被称为“深度学习三巨头”之一的蒙特利尔大学计算机科学与运算研究系教授Yoshua Bengio在清华大学做了《深度学习抵达人类水平人工智能所面临的挑战&#xff08;Challenges for Deep Learning towards Human-L…

了解GAN网络

GAN网络&#xff0c;第一次听说它就不明觉厉。其他网络都是对输入图像进行某种处理&#xff0c;得到某种特定的输出。而GAN网络居然可以“无中生有”&#xff0c;无论是去除马赛克&#xff0c;还是换脸&#xff0c;还是对灰度图像上色&#xff0c;都显得不可思议&#xff0c;怎…

新能源汽车:大变革催生十万亿市场空间

来源&#xff1a;新时代证券&#xff08;开文明&#xff09;新能源汽车发展空间巨大&#xff0c;随着新能源汽车性能提升以及痛点的改善&#xff0c;新能源汽车带来的冲击越来越大&#xff0c;渗透率随之提升。根据BNEF预测&#xff0c;到2025年全球新能源汽车的销量将达到1100…

dlib+vs2013+opencv实现人脸特征点检测

刷知乎的时候发现dlib做特征点检测和人脸识别的效果都好于OpenCV&#xff0c;就想着动手玩一下。没想到也是遇坑重重。 首先&#xff0c;在官网 install命令和setup.py文件进行安装时报错&#xff0c;先是报错cmake没有找到&#xff0c;添加了环境变量之后仍然报错c11需要在vs…

对号入座,看看未来几年机器人是否会取代你的工作

来源&#xff1a;资本实验室摘要&#xff1a;面对未来&#xff0c;你是否准备好了&#xff1f;“机器是否会取代人类的工作”是当前讨论最多的话题之一。这主要源自于近几年以人工智能为代表的新技术的快速发展与商业化。尽管各研究机构的预测数据有所不同&#xff0c;但相同的…

冈萨雷斯《数字图像处理》读书笔记(十一)——表示和描述

虽然不是专门研究图像分割的&#xff08;峰兄才是&#xff09;&#xff0c;但多少接触了一点&#xff0c;并且图像分割是图像处理中的最为复杂的&#xff0c;通过图像分割可以很好地认识图像处理的好多方法。今天看的是边界追踪和链码的表示。网易计算机视觉工程师的第一道选择…

细胞内钾多钠少——原初生物的第三大遗迹?

来源&#xff1a;科学网在我们每日的饮食中&#xff0c;食盐&#xff08;氯化钠&#xff09;是少不了的&#xff0c;难以想象我们怎么能够每天吃完全没有盐味的食物。不仅人类如此&#xff0c;许多动物&#xff0c;例如食草的动物如牛和羊&#xff0c;也会主动寻找土表盐粒。我…

冈萨雷斯《数字图像处理》读书笔记(九)——形态学图像处理

形态学来自于生物学&#xff0c;研究动植物的形态和结构。运用在图像中可提取如边界、骨架和凸壳。初学形态学都是在二值化的图像上研究&#xff0c;之后可以扩展到灰度图像。 膨胀和腐蚀 数学形态学与集合论分不开&#xff0c;因为形态学中的操作是基于两个集合的&#xff0…

云计算行业现状及未来发展趋势

来源&#xff1a;国元证券、乐晴智库摘要&#xff1a;按照服务类型云计算被分为IaaS、PaaS、SaaS。▌云计算产业链构成按照服务类型云计算被分为IaaS、PaaS、SaaS。IaaS基础设施及服务:IaaS主要提供计算基础设施服务&#xff0c;主要包括CPU、内存、存储、网络、虚拟化软件、分…

冈萨雷斯《数字图像处理》读书笔记(三)——空间滤波

滤波这个词来源于频域处理&#xff0c;因为它的目的就是针对频率分量而言的&#xff0c;滤除一定的频率分量。但其实滤波在时域&#xff08;图像中对应为空域&#xff09;中也可以完成相应的操作&#xff0c;比如低通滤波器滤除了代表细节的高频分量&#xff0c;我们可以直接在…

WinInet:HTTPS 请求出现无效的证书颁发机构的处理

首先&#xff0c;微软提供的WinInet库封装了对网页访问的方法。 最近工作需要从https服务器获取数据&#xff0c;都知道https和http网页的访问方式不同&#xff0c;多了一道证书认证程序&#xff0c;这样就使得https在请求起来比http要复杂的多&#xff1b;好在&#xff0c;Win…

热度下的冷思考——智能眼镜到底有没有前途?

来源&#xff1a;环球网我们曾期望Google眼镜能够成为革命性的新产品&#xff0c;因为它某种程度上实现了大家对未来的幻想。然而Google眼镜作为概念产品虽然有趣&#xff0c;但它仍然太不成熟&#xff0c;而且因为存在侵犯隐私的可能还被大众抵触&#xff0c;更重要的是它花去…

TFRecords文件的存储与读取

将cats和dogs两个文件夹各1000张图片存储为&#xff1a;train.tfrecords#将图片文件生成train record import os import tensorflow as tf from PIL import Image #生成cats和dogs的record文件 path./data/train filenamesos.listdir(path) writertf.python_io.TFRecordWriter(…