在OpenCV环境下写的灰度图像二维傅里叶换,幅值计算,波谱平移和将数值归一化到0到255区间的四个函数

在OpenCV环境下写的灰度图像二维傅里叶换,幅值计算,频谱平移和将数值归一化到0到255区间的四个函数

欢迎大家加入图像识别技术交流群:271891601,另外,特别欢迎成都从事图像识别工作的朋友交流,我的QQ号2487872782
-----------------------------------------------

灰度图像的二维傅里叶变换(cv_gray_fft2),二维傅里叶变换结果的幅值计算(cv_abs),频谱平移(cv_gray_fft2shift),将数值归一化到0到255区间(cv_range_0to255)是非常常用的四个功能!所以写成四个函数,方便将来调用,源码如下:

源码下载链接:http://pan.baidu.com/s/1skRqaRV

源码中用到的图片下载链接:http://pan.baidu.com/s/1slilbPF

---------------------------------------------------------------------------------------------

#include <opencv2/opencv.hpp>  

#include <opencv2/legacy/compat.hpp> 
#include <fstream>
using namespace std;  
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")  

void cv_gray_fft2(IplImage *src, IplImage *dst)  //注意:此函数仅适用灰度图像,src因为是灰度图像,所以通道数要求为1,dst的属性为:IPL_DEPTH_64F,2(两通道)
{
IplImage *image_Re = 0, *image_Im = 0, *Fourier = 0;
image_Re = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 1);  //实部
image_Im = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 1);  //虚部
Fourier = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 2);//2 channels,分别存储image_Re、image_Im

// Real part conversion from u8 to 64f (double)
cvConvertScale(src, image_Re);

// Imaginary part (zeros)
cvZero(image_Im);

// Join real and imaginary parts and stock them in Fourier image
cvMerge(image_Re, image_Im, 0, 0, Fourier);

// Application of the forward Fourier transform
cvDFT(Fourier, dst, CV_DXT_FORWARD);
cvReleaseImage(&image_Re);
cvReleaseImage(&image_Im);
cvReleaseImage(&Fourier);
}

void cv_abs(IplImage *src,IplImage *fft2_out, IplImage *dst)//src就是灰度图像原始数据,fft2_out要求是cv_gray_fft2的dst数据类型,即"64F, 2";dst为"64F, 1"
{
IplImage *image_Re = 0, *image_Im = 0;
image_Re = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 1);  //实部
image_Im = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 1);  //虚部
cvSplit(fft2_out,image_Re,image_Im,0,0);  
cvPow(image_Re,image_Re,2);                 
    cvPow(image_Im,image_Im,2);
cvAdd(image_Re,image_Im,image_Re,NULL);
cvPow(image_Re,dst,0.5);

cvReleaseImage(&image_Re);
cvReleaseImage(&image_Im);
}

void cv_gray_fft2shift(IplImage *src)//参数是"64F, 2"
{
int nRow, nCol, i, j, cy, cx;  
double tmp13, tmp24;

//Rearrange the quadrants of Fourier image so that the origin is at the image center  
    nRow = src->height;  
    nCol = src->width;  
    cy = nRow/2; // image center  
    cx = nCol/2;  
    //CV_IMAGE_ELEM为OpenCV定义的宏,用来读取图像的像素值,这一部分就是进行中心变换  
    for( j = 0; j < cy; j++ ){  
        for( i = 0; i < cx; i++ ){  
            //中心化,将整体份成四块进行对角交换  
            tmp13 = CV_IMAGE_ELEM( src, double, j, i);  
            CV_IMAGE_ELEM( src, double, j, i) = CV_IMAGE_ELEM(  
                src, double, j+cy, i+cx);  
            CV_IMAGE_ELEM( src, double, j+cy, i+cx) = tmp13;  
  
            tmp24 = CV_IMAGE_ELEM( src, double, j, i+cx);  
            CV_IMAGE_ELEM( src, double, j, i+cx) =  
                CV_IMAGE_ELEM( src, double, j+cy, i);  
            CV_IMAGE_ELEM( src, double, j+cy, i) = tmp24;  
        }  
    }  
}

void cv_range_0to255(IplImage *src, IplImage *dst)//两个参数都是"64F, 2"
{
double m,M; 
double scale;  
double shift;  

cvMinMaxLoc(src,&m,&M,NULL,NULL); 
scale = 255/(M - m);  
shift = -m * scale;  
cvConvertScale(src,dst,scale,shift);  
}

int main()
{
int i=0;//循环变量
//从文件中加载原图  
IplImage *pSrcImage = cvLoadImage("coins.png", CV_LOAD_IMAGE_UNCHANGED);  

//创建输出的图像
IplImage *pOutImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_64F,1);

//创建中间结果图像
IplImage *cv_gray_fft2_out = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_64F,2);//注意这里是二通道!
IplImage *cv_abs_out = cvCreateImage(cvGetSize(pSrcImage),  IPL_DEPTH_64F, 1);

cv_gray_fft2(pSrcImage,cv_gray_fft2_out);

double watch_cv_gray_fft2_out_Re[100];//利用调试时的局部变量窗口观察cvDFTOut实部的前100个值,看与MATLAB运行的结果否相同
double watch_cv_gray_fft2_out_Im[100];//利用调试时的局部变量窗口观察cvDFTOut虚部的前100个值,看与MATLAB运行的结果否相同
for(i=0;i<10;i++)//一般情况下观察10个值就够了
{
watch_cv_gray_fft2_out_Re[i]=cvGet2D(cv_gray_fft2_out,0,i).val[0];  
}
for(i=0;i<10;i++)//一般情况下观察10个值就够了
{
watch_cv_gray_fft2_out_Im[i]=cvGet2D(cv_gray_fft2_out,0,i).val[1];  
}

cv_abs(pSrcImage,cv_gray_fft2_out,cv_abs_out);
double watch_cv_abs_out[100];//利用调试时的局部变量窗口观察cv_abs_out的前100个值,看与MATLAB运行的结果否相同
for(i=0;i<10;i++)//一般情况下观察10个值就够了
{
watch_cv_abs_out[i]=cvGet2D(cv_abs_out,0,i).val[0];  
}

cv_gray_fft2shift(cv_abs_out);
double watch_cv_gray_fft2shift_out[100];//利用调试时的局部变量窗口观察cv_gray_fft2shift_out的前100个值,看与MATLAB运行的结果否相同
for(i=0;i<10;i++)//一般情况下观察10个值就够了
{
watch_cv_gray_fft2shift_out[i]=cvGet2D(cv_abs_out,0,i).val[0];  
}

cv_range_0to255(cv_abs_out,pOutImage);
double watch_cv_range_0to255_out[100];//利用调试时的局部变量窗口观察cv_range_0to255_out的前100个值,看与MATLAB运行的结果否相同
for(i=0;i<10;i++)//一般情况下观察10个值就够了
{
watch_cv_range_0to255_out[i]=cvGet2D(pOutImage,0,i).val[0];  
}
return 0;
}

---------------------------------------------------------------------------------------------

上面四个函数与MATLAB运行的结果一致,MATLAB程序如下:

---------------------------------------------------------------------------------------------

clear all;
clc;
I=imread('coins.png');
F=fft2(I);
MatlabFFt2Out=F;
MatlabAbsOut=abs(F);
MatlabFftshiftOut=fftshift(MatlabAbsOut);
T=MatlabFftshiftOut;
max_T=max(max(T));
min_T=min(min(T));
shift_T=-min_T*255/(max_T-min_T);
MatlabRange0to255=T.*255/(max_T-min_T)+shift_T;

---------------------------------------------------------------------------------------------

运行截图如下:

cv_gray_fft2

在OpenCV环境下写的灰度图像二维傅里叶换,幅值计算,波谱平移和将数值归一化到0到255区间的四个函数

在OpenCV环境下写的灰度图像二维傅里叶换,幅值计算,波谱平移和将数值归一化到0到255区间的四个函数在OpenCV环境下写的灰度图像二维傅里叶换,幅值计算,波谱平移和将数值归一化到0到255区间的四个函数

cv_abs

在OpenCV环境下写的灰度图像二维傅里叶换,幅值计算,波谱平移和将数值归一化到0到255区间的四个函数在OpenCV环境下写的灰度图像二维傅里叶换,幅值计算,波谱平移和将数值归一化到0到255区间的四个函数

cv_gray_fft2shift

在OpenCV环境下写的灰度图像二维傅里叶换,幅值计算,波谱平移和将数值归一化到0到255区间的四个函数

在OpenCV环境下写的灰度图像二维傅里叶换,幅值计算,波谱平移和将数值归一化到0到255区间的四个函数

cv_range_0to255

在OpenCV环境下写的灰度图像二维傅里叶换,幅值计算,波谱平移和将数值归一化到0到255区间的四个函数

在OpenCV环境下写的灰度图像二维傅里叶换,幅值计算,波谱平移和将数值归一化到0到255区间的四个函数

-----------------------------------------------

欢迎大家加入图像识别技术交流群:271891601,另外,特别欢迎成都从事图像识别工作的朋友交流,我的QQ号2487872782