opencv之离散傅里叶变换(DFT)
2016-07-16 16:56
525 查看
opencv之离散傅里叶变换
函数解读:
C++: int getOptimalDFTSize(int vecsize)源码解读;
[cpp] viewplain copy
print?
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
<span style="font-size:18px;">int cv::getOptimalDFTSize( int size0 )
{
int a = 0, b = sizeof(optimalDFTSizeTab)/sizeof(optimalDFTSizeTab[0]) -1;
if( (unsigned)size0 >= (unsigned)optimalDFTSizeTab )
return -1;
while( a < b )//二分查找合适的size
{
int c = (a + b) >> 1;
if( size0 <= optimalDFTSizeTab[c] )
b = c;
else
a = c+1;
}
returnoptimalDFTSizeTab[b];
}</span>
optimalDFTSizeTab定义在namespace cv中,里边的数值为2^x*3^y*5^z
static const int optimalDFTSizeTab[] = {1,2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16,…, 2123366400, 2125764000};
copyMakeBorder
[b]C++: void copyMakeBorder(InputArraysrc, OutputArray dst, int top, int bottom, int left,int right, int borderType,
const Scalar& value=Scalar())
src: 源图像
dst: 目标图像,和源图像有相同的类型,dst.cols=src.cols+left+right; dst.rows=src.rows+dst.top+dst.bottom
top:
bottom:
left:
right: 以上四个参数指定了在src图像周围附加的像素个数。
borderType: 边框类型
value: 当borderType==BORDER_CONSTANT时需要指定该值。
示例代码:
[cpp] viewplain copy
print?
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
<span style="font-size:18px;">#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(){
Mat src = imread("fruits.jpg");
if(!src.data)
{
return -1;
}
Mat src_gray;
cvtColor(src,src_gray,CV_RGB2GRAY);//灰度图像做傅里叶变换
int m = getOptimalDFTSize(src_gray.rows);//2,3,5的倍数有更高效率的傅里叶转换
int n = getOptimalDFTSize(src_gray.cols);
Mat dst;
///把灰度图像放在左上角,在右边和下边扩展图像,扩展部分填充为0;
copyMakeBorder(src_gray,dst,0,m-src_gray.rows,0,n-src_gray.cols,BORDER_CONSTANT,Scalar::all(0));
cout<<dst.size()<<endl;
//新建一个两页的array,其中第一页用扩展后的图像初始化,第二页初始化为0
Mat planes[] = {Mat_<float>(dst), Mat::zeros(dst.size(), CV_32F)};
Mat completeI;
merge(planes,2,completeI);//把两页合成一个2通道的mat
//对上边合成的mat进行傅里叶变换,支持原地操作,傅里叶变换结果为复数。通道1存的是实部,通道2存的是虚部。
dft(completeI,completeI);
split(completeI,planes);//把变换后的结果分割到各个数组的两页中,方便后续操作
magnitude(planes[0],planes[1],planes[0]);//求傅里叶变换各频率的幅值,幅值放在第一页中。
Mat magI = planes[0];
//傅立叶变换的幅度值范围大到不适合在屏幕上显示。高值在屏幕上显示为白点,
//而低值为黑点,高低值的变化无法有效分辨。为了在屏幕上凸显出高低变化的连续性,我们可以用对数尺度来替换线性尺度:
magI += 1;
log(magI,magI);//取对数
magI= magI(Rect(0,0,src_gray.cols,src_gray.rows));//前边对原始图像进行了扩展,这里把对原始图像傅里叶变换取出,剔除扩展部分。
//这一步的目的仍然是为了显示。 现在我们有了重分布后的幅度图,
//但是幅度值仍然超过可显示范围[0,1] 。我们使用 normalize() 函数将幅度归一化到可显示范围。
normalize(magI,magI,0,1,CV_MINMAX);//傅里叶图像进行归一化。
//重新分配象限,使(0,0)移动到图像中心,
//在《数字图像处理》中,傅里叶变换之前要对源图像乘以(-1)^(x+y)进行中心化。
//这是是对傅里叶变换结果进行中心化
int cx = magI.cols/2;
int cy = magI.rows/2;
Mat tmp;
Mat q0(magI,Rect(0,0,cx,cy));
Mat q1(magI,Rect(cx,0,cx,cy));
Mat q2(magI,Rect(0,cy,cx,cy));
Mat q3(magI,Rect(cx,cy,cx,cy));
q0.copyTo(tmp);
q3.copyTo(q0);
tmp.copyTo(q3);
q1.copyTo(tmp);
q2.copyTo(q1);
tmp.copyTo(q2);
namedWindow("InputImage");
imshow("InputImage",src);
namedWindow("SpectrumImage");
imshow("SpectrumImage",magI);
waitKey();
return0;
}</span>
实验结果:
代码已上传至gihub:opencv之离散傅里叶变换
转载:http://blog.csdn.net/ubunfans/article/details/24787569
相关文章推荐
- linux优化基础之更改“字符集”
- Linux下查看哪些文件占用磁盘空间比较大
- Linux 服务器安装配置 TimeMachine
- linux系统下python tab键补全(2步搞定)
- linux线程控制
- Opencv图像识别从零到精通(7)----图像平移、旋转、镜像
- 我的OpenCV学习笔记:VideoCapture类
- Hadoop 相关命令说明
- linux系统实用程序(1)
- Apache服务器运维笔记(4)----服务器扩展部分
- 云直播系统架构与实施
- Linux进程间通讯(IPC)------FIFO
- Centos6服务器部署JavaWeb项目(tomcat6+jdk6)
- CentOS6.7下安装MySQL
- 【COCI2012 Task 5】T6 poplocavanje ([JZOJ3172]贴瓷砖)(AC自动机模板)
- CentOS6.7下安装MySQL
- CentOS6.7下安装MySQL
- linux中搜索文件
- tomcat系统架构简介
- 安装crontab