您的位置:首页 > 运维架构

OpenCV中傅里叶变换和反变换的运用

2014-05-17 13:07 344 查看
#include <opencv2\core\core.hpp>

#include <opencv2\highgui\highgui.hpp>

#include <opencv2\imgproc\imgproc.hpp>

using namespace std;

using namespace  cv;

void main()

{
Mat img = imread("lena.jpg",CV_LOAD_IMAGE_GRAYSCALE); //读入图像 转化为八位灰度图
imshow("source",img); //原图像显示
int h = cv::getOptimalDFTSize(img.rows); //图像尺寸的修正目的在于计算过程中可以优化,加快计算
int w = cv::getOptimalDFTSize(img.cols);
Mat padded;
cv::copyMakeBorder(img,padded,0,h-img.rows,0,w-img.cols,BORDER_CONSTANT,::Scalar::all(0)); 
//扩充成最优尺寸,注意:此处是复制了img的数据到padded,并非简单通过指针和img共享内存
//但这种情况则没有复制: 因为dst本身就和img共享了内存,只是简单的扩充了边界
//Mat img = imread("xxx.jpg");
//Mat dst = img;
//cv::copyMakeBorder(img,dst,2,2,2,2,BORDER_CONSTANT,Scalar::all(0));

Mat plane[] = {Mat_<float>(padded),Mat::zeros(padded.size(),CV_32F)}; //实部为img,虚部填充0
Mat complexImg;
cv::merge(plane,2,complexImg); //可以理解为组合成2通道(实部+虚部)图像
dft(complexImg,complexImg); //DFT变换后的数据复制到原处,没有另外开辟内存

//--------------------------------------------------------------------------
//dft变换后利用idft变换恢复原图像,显示效果与原图像相差无几,
Mat frequencyImg;
complexImg.copyTo(frequencyImg);
Mat iDft[] = {Mat::zeros(padded.size(),CV_32F),Mat::zeros(padded.size(),CV_32F)};
::idft(frequencyImg,frequencyImg);
::split(frequencyImg,iDft);
::magnitude(iDft[0],iDft[1],iDft[0]);
cv::normalize(iDft[0],iDft[0],1,0,CV_MINMAX);
imshow("iDFT",iDft[0]); //dft idft 后的图像
//-------------------------------------------------------------------------

//-------------------------------------------------------------------------------
//根据DFT的能力集中地特点,即图像信息集中在低频部分
//先取出图像四个角(低频部分)的小块区域(其余灰度置为0),在idft反变换回去,和原图像进行比较
//显示结果表明只取出反变换后的16%信息,在利用idft反变换,发现与原图相差不太大
//这是图像处理中利用正交变换(包括傅里叶变换)的能量集中特性(图像有损压缩中有利用)
Mat partFrequencyImg;
complexImg.copyTo(partFrequencyImg);
int nx1 = int(0.2f*padded.cols);
int nx2 = int(0.8f*padded.cols);
int ny1 = int(0.2f*padded.rows);
int ny2 = int(0.8f*padded.rows);
partFrequencyImg.colRange(nx1,nx2).setTo(Scalar::all(0));
partFrequencyImg.rowRange(ny1,ny2).setTo(Scalar::all(0));
Mat iPartDft[] = {Mat::zeros(padded.size(),CV_32F),Mat::zeros(padded.size(),CV_32F)};
::idft(partFrequencyImg,partFrequencyImg);
::split(partFrequencyImg,iPartDft);
::magnitude(iPartDft[0],iPartDft[1],iPartDft[0]);
cv::normalize(iPartDft[0],iPartDft[0],1,0,CV_MINMAX);
imshow("iPartDFT",iPartDft[0]); //取dft变换后的部分低频部分,利用idft反变换后的图像
//--------------------------------------------------------------------------

::split(complexImg,plane); //实部plane[0] 虚部plane[1]
::magnitude(plane[0],plane[1],plane[0]);//计算幅频 结果保存到plane[0]
imshow("dft",plane[0]); //显示出来的幅频图,看不出任何有效信息,需要做增强处理

plane[0] += Scalar::all(1); //整体加1的目的在于log计算后非负
cv::log(plane[0],plane[0]); //log可起到拉伸,增大对比度的作用
cv::normalize(plane[0],plane[0],1,0,CV_MINMAX);//整体映射到0~1,也称归一化处理
imshow("enhance",plane[0]); //增强后的图像,显示效果明显改善

//保证plane[0]的行列均为偶数 以下将低频部分往中心移动
int cx = plane[0].cols / 2;
int cy = plane[0].rows / 2;
Mat m1(plane[0],cv::Rect(0,0,cx,cy)); //左上部分
Mat m2(plane[0],cv::Rect(cx,0,cx,cy)); //右上部分
Mat m3(plane[0],cv::Rect(0,cy,cx,cy)); //左下部分
Mat m4(plane[0],cv::Rect(cx,cy,cx,cy)); //右下部分
Mat temp;
m1.copyTo(temp); //左上与右下交换
m4.copyTo(m1);
temp.copyTo(m4);
m2.copyTo(temp);// 右上与左下交换
m3.copyTo(m2);
temp.copyTo(m3);
imshow("shift",plane[0]); //低频中心化的图像
waitKey(0);
}











内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息