基于MFC和opencv的FFT
在网上折腾了一阵子,终于把这个程序写好了,程序是基于MFC的,图像显示的部分和获取图像的像素点是用到了opencv的一些函数,不过FFT算法没有用opencv的(呵呵,老师不让),网上的二维的FFT程序一般都是把图像分别进行行变换后进行列变换的,在编程过程中遇到了一些问题,是这样的,FFT算法算完后得到的复数矩阵怎么imshow?问题就出现在这,我原来的程序因为归一化到0-255时,程序运行特别慢(用了个CArray,找出array里的最大值和最小值,然后(每一个复数矩阵求模后-最小值)/(最大值-最小值),不满才怪呵呵,得出FFT结果是全黑的)。参考了别人的归一化
/*-----------------------------------------------------------------------------
* 计算功率谱
* 和归一化
*
*-----------------------------------------------------------------------------*/
// 行
for(i = ; i < h; i++)
{
// 列
for(j = ; j < w; j++)
{
// 计算频谱
dTemp = sqrt(FD[j * h + i].real() * FD[j * h + i].real() +
FD[j * h + i].imag() * FD[j * h + i].imag()) / ; // 判断是否超过255
if (dTemp > )
{
// 对于超过的,直接设置为255
dTemp = ;
} image.at<uchar>(i,j)=(uchar)dTemp;
// 更新源图像 }
}
主要代码:
/*
* =====================================================================================
*
* Filename: fft_dlgDlg.cpp
* Environment:opencv2.4.4 vs2010
*
* Description: 基于MFC的FFT程序
*
*
*
* Version: 1.0
* Created: 2013/10/19 19:24:06
* Author: yuliyang
I*
* Mail: wzyuliyang911@gmail.com
* Blog: http://www.cnblogs.com/yuliyang
*
* =====================================================================================
*/ // fft_dlgDlg.cpp : 实现文件
// #include "stdafx.h"
#include "fft_dlg.h"
#include "fft_dlgDlg.h"
#include "afxdialogex.h" #include <complex>
#include <math.h>
#include <stdio.h>
#include <Windows.h>
#include "opencv\highgui.h"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
#define PI 3.1415936; #ifdef _DEBUG
#define new DEBUG_NEW
#endif // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialogEx
{
public:
CAboutDlg(); // 对话框数据
enum { IDD = IDD_ABOUTBOX }; protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现
protected:
DECLARE_MESSAGE_MAP()
}; CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
} void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
} BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP() // Cfft_dlgDlg 对话框 Cfft_dlgDlg::Cfft_dlgDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(Cfft_dlgDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
} void Cfft_dlgDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
} BEGIN_MESSAGE_MAP(Cfft_dlgDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_OPEN_FILE, &Cfft_dlgDlg::OnBnClickedOpenFile) END_MESSAGE_MAP() // Cfft_dlgDlg 消息处理程序 BOOL Cfft_dlgDlg::OnInitDialog()
{
CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
} // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
} void Cfft_dlgDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
} // 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。 void Cfft_dlgDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), ); // 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + ) / ;
int y = (rect.Height() - cyIcon + ) / ; // 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
} //当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR Cfft_dlgDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
} void Cfft_dlgDlg::OnBnClickedOpenFile()
{
// TODO: 在此添加控件通知处理程序代码 /*-----------------------------------------------------------------------------
* 选择文件名
*-----------------------------------------------------------------------------*/ CString strFileName,strszFilter,strtitle,strext;
strszFilter="位图文件(*.bmp)|*.bmp|位图文件(*.jpg)|*.jpg|全部文件(*.*)|*.*||";
CFileDialog bmpdlg(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,strszFilter,NULL);
if(IDOK == bmpdlg.DoModal())
{
strFileName = bmpdlg.GetPathName();
strtitle=bmpdlg.GetFileTitle();
strext=bmpdlg.GetFileExt(); }
if (strFileName.IsEmpty())
{
//MessageBox((LPCTSTR)strFileName);
MessageBox("请选择一副图像"); return ;
} /*-----------------------------------------------------------------------------
* opencv读入图像
*
*
*-----------------------------------------------------------------------------*/
Mat image=imread(strFileName.GetBuffer(),); //unsigned char* lpSrc;
// 中间变量
double dTemp;
// 循环变量
LONG i;
LONG j;
// 进行付立叶变换的宽度和高度(2的整数次方)
LONG w;
LONG h;
int wp;
int hp;
// 赋初值
w = ;
h = ;
wp = ;
hp = ; /*-----------------------------------------------------------------------------
* 填充到2的幂次方
*
*
*-----------------------------------------------------------------------------*/
// 计算进行付立叶变换的宽度和高度(2的整数次方)
while(w * <= image.cols)
{
w *= ;
wp++;
} while(h * <= image.rows)
{
h *= ;
hp++;
}
// 分配内存
complex<double> *TD = new complex<double>[w * h];
complex<double> *FD = new complex<double>[w * h];
// 行
for(i = ; i < h; i++)
{
// 列
for(j = ; j < w; j++)
{
// 给时域赋值
TD[j + w * i] = complex<double>(image.at<uchar>(i,j), ); /* opencv函数读取图像像素到复数矩阵里 */
}
}
/*-----------------------------------------------------------------------------
* 把二维的FFT换成分别对行方向和列方向进行一维的FFT
*
*
*-----------------------------------------------------------------------------*/
for(i = ; i < h; i++)
{
// 对y方向进行快速付立叶变换
FFT(&TD[w * i], &FD[w * i], wp);
}
// 保存变换结果
for(i = ; i < h; i++)
{
for(j = ; j < w; j++)
{
TD[i + h * j] = FD[j + w * i];
}
} for(i = ; i < w; i++)
{
// 对x方向进行快速付立叶变换
FFT(&TD[i * h], &FD[i * h], hp);
} /*-----------------------------------------------------------------------------
* 计算功率谱
* 和归一化
*
*-----------------------------------------------------------------------------*/
// 行
for(i = ; i < h; i++)
{
// 列
for(j = ; j < w; j++)
{
// 计算频谱
dTemp = sqrt(FD[j * h + i].real() * FD[j * h + i].real() +
FD[j * h + i].imag() * FD[j * h + i].imag()) / ; // 判断是否超过255
if (dTemp > )
{
// 对于超过的,直接设置为255
dTemp = ;
} image.at<uchar>(i,j)=(uchar)dTemp;
// 更新源图像 }
} /*-----------------------------------------------------------------------------
* 释放内存
*
*
*-----------------------------------------------------------------------------*/
// 删除临时变量
delete TD;
delete FD; /*-----------------------------------------------------------------------------
* 进行图像的中心化
*
*
*-----------------------------------------------------------------------------*/
int cy = image.rows/; /* 中心点位置 cx ,cy */
int cx = image.cols/;
uchar tmp13,tmp24; //imshow("未中心化的功率谱",image); IplImage center_image=IplImage(image);
for( j = ; j < cy; j++ ){
for( i = ; i < cx; i++ ){
//中心化,将整体份成四块进行对角交换
tmp13 = CV_IMAGE_ELEM( ¢er_image, uchar, j, i);
CV_IMAGE_ELEM( ¢er_image, uchar, j, i) = CV_IMAGE_ELEM(
¢er_image, uchar, j+cy, i+cx);
CV_IMAGE_ELEM( ¢er_image, uchar, j+cy, i+cx) = tmp13; tmp24 = CV_IMAGE_ELEM( ¢er_image, uchar, j, i+cx);
CV_IMAGE_ELEM( ¢er_image, uchar, j, i+cx) =
CV_IMAGE_ELEM( ¢er_image, uchar, j+cy, i);
CV_IMAGE_ELEM( ¢er_image, uchar, j+cy, i) = tmp24;
}
} /*-----------------------------------------------------------------------------
* 用于保存FFT图像
*
*
*-----------------------------------------------------------------------------*/
Mat img(¢er_image,);
if (BST_CHECKED == ::IsDlgButtonChecked(m_hWnd,IDC_CHECK_SAVE))
{ strtitle="FFT_"+strtitle+"."+strext; //MessageBox(strtitle.GetBuffer(0));
imwrite(strtitle.GetBuffer(),img); }
imshow("中心化后的功率谱",img); waitKey();
// 返回
//return TRUE; } /*
* === FUNCTION ======================================================================
* Name: FFT
* Description: 计算一维FFT
* =====================================================================================
*/
void Cfft_dlgDlg::FFT(complex<double> * TD, complex<double> * FD, int r)
{ LONG count;
// 循环变量
int i,j,k;
// 中间变量
int bfsize,p;
// 角度
double angle;
complex<double> *W,*X1,*X2,*X;
// 计算付立叶变换点数
count = << r;
// 分配运算所需存储器
W = new complex<double>[count / ];
X1 = new complex<double>[count];
X2 = new complex<double>[count];
// 计算加权系数
for(i = ; i < count / ; i++)
{
angle =-*i*PI;
angle =angle/(double)count;
W[i] = complex<double> (cos(angle), sin(angle));
}
// 将时域点写入X1
memcpy(X1, TD, sizeof(complex<double>) * count); /*-----------------------------------------------------------------------------
*
* 采用蝶形算法进行快速付立叶变换
*
*-----------------------------------------------------------------------------*/ for(k = ; k < r; k++)
{
for(j = ; j < << k; j++)
{
bfsize = << (r-k);
for(i = ; i < bfsize / ; i++)
{
p = j * bfsize;
X2[i + p] = X1[i + p] + X1[i + p + bfsize / ];
X2[i + p + bfsize / ] = (X1[i + p] - X1[i + p + bfsize / ]) * W[i * (<<k)];
}
}
X = X1;
X1 = X2;
X2 = X;
}
// 重新排序
for(j = ; j < count; j++)
{
p = ;
for(i = ; i < r; i++)
{
if (j&(<<i))
{
p+=<<(r-i-);
}
}
FD[j]=X1[p];
}
// 释放内存
delete W;
delete X1;
delete X2;
}
运行效果如下:
提供程序一份:
http://pan.baidu.com/s/1ehvwy
基于MFC和opencv的FFT的更多相关文章
- 转:基于开源项目OpenCV的人脸识别Demo版整理(不仅可以识别人脸,还可以识别眼睛鼻子嘴等)【模式识别中的翘楚】
文章来自于:http://blog.renren.com/share/246648717/8171467499 基于开源项目OpenCV的人脸识别Demo版整理(不仅可以识别人脸,还可以识别眼睛鼻子嘴 ...
- 基于MFC的socket编程(异步非阻塞通信)
对于许多初学者来说,网络通信程序的开发,普遍的一个现象就是觉得难以入手.许多概念,诸如:同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)等,初学者往往迷惑不清, ...
- 基于MFC简单图片裁剪工具
话说这几天又没干啥正事,看书没效率,游戏也没怎么玩,尼玛时间都去哪儿了! --------------------------------------------------------------- ...
- windows平台下基于QT和OpenCV搭建图像处理平台
在之前的博客中,已经分别比较详细地阐述了"windows平台下基于VS和OpenCV"以及"Linux平台下基于QT和OpenCV"搭建图像处理框架,并 ...
- 基于MFC开发的指纹识别系统.
MFC-FingerPrint 基于MFC开发的指纹识别系统. 效果图如下: 在第12步特征入库中,会对当前指纹的mdl数据与databases中所有的mdl进行对比,然后返回识别结果. 一.载入图像 ...
- 基于python的快速傅里叶变换FFT(二)
基于python的快速傅里叶变换FFT(二)本文在上一篇博客的基础上进一步探究正弦函数及其FFT变换. 知识点 FFT变换,其实就是快速离散傅里叶变换,傅立叶变换是数字信号处理领域一种很重要的算法. ...
- 最全的基于MFC的ActiveX控件开发教程
浏览器插件之ActiveX开发(一) 一般的Web应用对于浏览器插件能不使用的建议尽量不使用,因为其涉及到安全问题以及影响用户安装(或自动下载注册安装)体验问题.在有特殊需求(如涉及数据安全的金融业务 ...
- 基于MFC的ActiveX控件开发教程------------浏览器插件之ActiveX开发
浏览器插件之ActiveX开发(一) 一般的Web应用对于浏览器插件能不使用的建议尽量不使用,因为其涉及到安全问题以及影响用户安装(或自动下载注册安装)体验问题.在有特殊需求(如涉及数据安全的金融业务 ...
- Beginning SDL 2.0(5) 基于MFC和SDL的YuvPlayer
本文是在“Beginning SDL 2.0(4) YUV加载及渲染”(以下简称BS4)基础上做的功能完善,如果你对之间介绍的内容了解不多,麻烦先阅读之前的内容. 本文主要介绍如何完成一个基于MFC和 ...
随机推荐
- C++ Primer笔记整理
1. 迭代器:迭代器是一种对象,它可以看做是游标,用来遍历标准模板库中的部分或者全部元素. 每个迭代器指向容器中确定的地址,此外,迭代器还提供一些基本操作符:*.++.==.!=.=. 2. 模板:是 ...
- 写个Python练练手吧
在Python的交互式命令行写程序,好处是一下就能得到结果,坏处是没法保存,下次还想运行的时候,还得再敲一遍. 所以,实际开发的时候,我们总是使用一个文本编辑器来写代码,写完了,保存为一个.py文件, ...
- WPF中Timer与DispatcherTimer类的区别
前几天在WPF中写了一个轨迹回放的功能,我想稍微做过类似项目的,都晓得采用一个时间控件或者时间对象作为调度器,我在这么做的时候,出现了问题,于是将程序中的Timer换成了DispatchTimer,然 ...
- 增加oracle数据库最大连接数
这几天碰到系统不能登陆的情况,初步判断可能是数据库连接满了,(后来检查不是这个原因),做了一次增加数据库最大连接数操作.操作步骤如下 操作系统:Red Hat Enterprise Linux Ser ...
- C#版二维码生成器
前言 本文所使用的二维码生成代码是谷歌开源的条形码图像处理库完成的,c#版的代码可去 这里 -- 下载压缩包. 截止目前为止最新版本为2.2,提供以下编码格式的支持: UPC-A and UPC ...
- 自定义View(6)paint设置图图层重叠时的显示方式,包含清空canvas
Paint.setXfermode 这个函数设置两个图层相交时的模式 在已有的图层上绘图将会在其上面添加一层新的图层. 如果新的图层是完全不透明的,那么它将完全遮挡住下面的图层,而setXfermod ...
- bzoj1063
仔细观察可以发现,这个规划路径很像树链剖分 树链剖分的经典定理:任意一个点到根的所经过轻边不超过logn 而这个规划路径所走公路相当于轻边,也就是说,不便利度不会很大 那么直接dp即可,设f[x,i, ...
- Qt之自定义界面(右下角冒泡)
简述 网页右下角上经常会出现一些提示性的信息,桌面软件中也比较常见,类似360新闻.QQ消息提示一样! 这种功能用动画实现起来很简单,这节我们暂时使用定时器来实现,后面章节会对动画框架进行详细讲解. ...
- UVa 11021 (概率 递推) Tribles
Tribble是麻球? 因为事件都是互相独立的,所以只考虑一只麻球. 设f(i)表示一只麻球i天后它以及后代全部死亡的概率,根据全概率公式: f(i) = P0 + P1 * f(i-1) + P2 ...
- bzoj2561: 最小生成树
如果出现在最小生成树上,那么此时比该边权值小的边无法连通uv.据此跑最小割(最大流)即可. #include<cstdio> #include<cstring> #includ ...