快速中值滤波算法
- 格式:doc
- 大小:267.00 KB
- 文档页数:17
Micr ocomputer Applica tions V ol.27,No.8,2011开发应用微型电脑应用2011年第27卷第8期5文章编号:1007-757X(2011)08-0050-03一种快速并行中值滤波算法的实现辛月兰摘要:介针对传统中值滤波算法计算量大、耗时较长的缺点提出了一种快速并行中值滤波算法。
对于3×3滑动窗口,窗口的9个数据是并行传给计算比较模块的,第二级的计算也是并行进行的。
新算法有效减少了重复比较操作的执行,同时也大幅减少了比较次数。
对于3×3滑动窗口,新算法的比较次数为13次,相对于传统中值滤波的30次,比较次数少了2倍多。
比较次数的减少,意味着算法复杂度的降低和图像滤波处理速度的提高。
并且通过仿真实验可知,对于椒盐噪声的滤除,算法能够达到与中值滤波同样的视觉处理效果。
关键词:并行处理;中值滤波;预处理;快速算法;图像处理中图分类号:0246文献标志码:A0引言实际图像在采集、形成、传输过程中,不可避免会受到噪声干扰,严重影响视觉效果,对后续的边缘检测、图像分割、特征提取、模式识别等产生影响。
因此,去噪是一项非常重要的预处理步骤[1]。
中值滤波是一种常用的抑制噪声的非线性方法,它可以克服线性滤波如最小均方滤波和均值滤波给图像边缘带来的模糊,从而获得较为满意的复原效果;它能较好地保护边界,对于消除图像的椒盐噪声非常有效,但有时会失掉图像中的细线和小块的目标区域[2-3]。
理想的滤波算法应该只对噪声点进行处理,而保留信号灰度值不变。
Sun and Neuvo[4]和Florencio and Schafer[5]分别提出了开关中值滤波的方法,更好地保留了图像细节,但噪声点判断方法是通过假定噪声水平上的硬阈值方法,使得其推广能力受到了限制。
H.L.Eng 和K.K.Ma[6]提出噪声自适应软开关中值滤波(NASM)算法,它是一种软阈值的判断方法,这种算法自适应性虽然比其它的开关中值滤波算法强,但其计算时间随噪声密度的增大而增加,如当噪声密度为70%时,NASM 算法所用的时间大约为中值滤波算法的17倍,因此不能满足实时图像处理。
数字图像处理之快速中值滤波算法快速中值滤波算法 : 在图像处理中,在进⾏如边缘检测这样的进⼀步处理之前,通常需要⾸先进⾏⼀定程度的降噪。
中值滤波是⼀种⾮线性数字滤波器技术,经常⽤于去除图像或者其它信号中的噪声。
这个设计思想就是检查输⼊信号中的采样并判断它是否代表了信号,使⽤奇数个采样组成的观察窗实现这项功能。
观察窗⼝中的数值进⾏排序,位于观察窗中间的中值作为输出。
然后,丢弃最早的值,取得新的采样,重复上⾯的计算过程。
中值滤波是图像处理中的⼀个常⽤步骤,它对于斑点噪声和椒盐噪声来说尤其有⽤。
保存边缘的特性使它在不希望出现边缘模糊的场合也很有⽤。
为了演⽰中值滤波器的⼯作过程,我们给下⾯的数组加上观察窗 3 ,重复边界的数值: x = [2 80 6 3] y[1] = Median[2 2 80] = 2 y[2] = Median[2 80 6] = Median[2 6 80] = 6 y[3] = Median[80 6 3] = Median[3 6 80] = 6 y[4] = Median[6 3 3] = Median[3 3 6] = 3 于是 y = [2 6 6 3] 其中 y 是 x 的中值滤波输出。
普通中值滤波算法伪代码: Input: image X of size m*n, kernel radius r. output: image Y as X. for i = r to m - r do for j = r to n - r do initialize list A[] for a = i-r to i+r for b = j-r to j+r add X(a, b) to A[] end end sort A[] then Y(i ,j) = A[A.size/2] end end 处理前: 处理后: 但是,上述算法在像素处理处的复杂度为O(r2). OpenCV实现代码:#include "cv.h"#include "highgui.h"#include <iostream>using namespace std;using namespace cv;int main(int argc, char* argv[]){Mat src = imread("beauty.jpg");Mat dst;//参数是按顺序写的//⾼斯滤波//src:输⼊图像//dst:输出图像//Size(5,5)模板⼤⼩,为奇数//x⽅向⽅差//Y⽅向⽅差GaussianBlur(src,dst,Size(5,5),0,0);imwrite("gauss.jpg",dst);//中值滤波//src:输⼊图像//dst::输出图像//模板宽度,为奇数medianBlur(src,dst,3);imwrite("med.jpg",dst);//均值滤波//src:输⼊图像//dst:输出图像//模板⼤⼩//Point(-1,-1):被平滑点位置,为负值取核中⼼blur(src,dst,Size(3,3),Point(-1,-1));imwrite("mean.jpg",dst);//双边滤波//src:输⼊图像//dst:输⼊图像//滤波模板半径//颜⾊空间标准差//坐标空间标准差bilateralFilter(src,dst,5,10.0,2.0);//这⾥滤波没什么效果,不明⽩imwrite("bil.jpg",dst);waitKey();return0;}View Code 快速中值滤波算法: O(r)复杂度的Huang算法:<> 这个代码的核⼼在于维护⼀个kernel直⽅图,可以实现快速的读取和删除扫描区域的像素值。
中值滤波的快速算法
中值滤波的快速算法有很多种,常见的有以下几种:
1. 快速排序算法:使用快速排序对滤波窗口中的像素值进行排序,然后取排序后的中间值作为滤波结果。
这种算法时间复杂度为O(nlogn),其中n是滤波窗口的大小。
2. 快速选择算法:快速选择算法是一种改进的快速排序算法。
它不需要完全对滤波窗口进行排序,而是通过选择一部分元素进行比较,找到第k小的值。
这种算法时间复杂度为O(n),
其中n是滤波窗口的大小。
3. 堆排序算法:使用堆数据结构对滤波窗口中的像素值进行排序,然后取堆顶元素作为滤波结果。
这种算法时间复杂度为
O(nlogn),其中n是滤波窗口的大小。
4. 快速中值滤波算法:该算法使用线性时间的中值搜索算法,通过选择一个约束条件,将滤波窗口中的像素分成两个部分,然后在这两个部分中搜索中值。
这种算法时间复杂度为O(n),其中n是滤波窗口的大小。
以上是常见的几种中值滤波的快速算法,根据实际应用场景和需求可以选择适合的算法。
• 98•武汉迈迪克光电股份有限公司陈军旗 南开大学滨海学院 赵凤怡• 99•就能够构建出快速中值滤波的硬件模块,满足图像实时处理的要求。
2 设计实现2.1 滑动窗口模块基于邻域操作的图像处理算法广泛采用滑动窗口技术,用于获取待处理图像相关位置的原始数据(汤露,程姝,基于FPGA的实时中值滤波算法硬件设计,工业控制计算机,2018年第2期20-22页)。
本设计中采用3*3的窗口模板,模块的结构如图2所示。
4个LineBuffer和9个单寄存器组成模块的缓存单元,每个LineBuffer由双口RAM构成,其位宽和存储深度由视频图像的数据规模决定,至少要满足一行数据的存储要求;列缓存对每一行的输出进行移位操作,实现3个元素的顺序输出;多路选择器负责对输入输出的数据进行路由选择,保证输出数据的结构特征,满足算法设计的技术要求。
组成行缓存的4个LineBuffer在视频行同步信号的边沿切换工作状态,形成 “乒乓操作”结构。
任意时刻,保持一个LineBuffer处于写状态,其它三个LineBuffer处于读状态。
在同步信号的控制下依序切换,4个周期形成一个循环,周而复始。
由于4个LineBuffer的输出状态不断切换,为保证输出数据在空间上的顺序关系,需要对输出的3行数据进行重定位。
考虑到算法第一步要求对每一列的数据进行排序,本质上就已经打乱了原始数据的顺序关系。
因此可以直接对LineBuffer的输出数据进行排序输出,这样进入列缓存的数据已经完成算法要求的第一步处理,直接生成了中间序列。
2.2 快速排序算法的原理与与处理流程已经在论文2.2节有详细介绍,其中第一步已经在生成滑动窗口的过程完成,接下来需要对滑动窗口内每一行的三个元素分别进行排序,实现的代码如下所示。
其中X1为第一行的最大值,X2为第二行的中间值,X3为第三行的最小值,它们三个构成第三步对角线上的三个元素。
按照相同的方法,对X(n)重新排序,其中值即为最终的输出结果。
常用数字滤波算法
常用的数字滤波算法包括:
1. 移动平均滤波(Moving Average Filter):通过对一段时间内的
样本值取平均值来减小噪音的影响。
2. 中值滤波(Median Filter):通过将一组样本值按大小排序,然
后选择中间值作为滤波结果,从而去除异常值的影响。
3. 限幅滤波(Clipping Filter):将样本值限制在一个给定范围内,超出范围的值被替换为边界值,从而去除异常值的影响。
4. 卡尔曼滤波(Kalman Filter):基于状态估计的滤波算法,使用
模型预测和观测值校正的方式,适用于动态系统的滤波和估计。
5. 维纳滤波(Wiener Filter):根据信噪比的估计,利用频域的自
相关函数和谱估计对信号进行滤波,适用于去除加性噪声。
6. 自适应滤波(Adaptive Filter):根据输入信号的统计特性不断
更新滤波器参数,以动态调整滤波器的性能,适用于非平稳信号的滤波。
7. 快速傅里叶变换滤波(FFT Filter):通过将时域信号转换为频
域信号,滤除不需要的频率分量,然后再将频域信号转换回时域信号。
这些算法可以根据具体应用的需要选择合适的滤波方法。
数据处理中的几种常用数字滤波算法
在数据处理中,常用的数字滤波算法有以下几种:
1. 移动平均滤波(Moving Average Filter):将一组连续的数据取
平均值作为滤波结果。
该算法简单易实现,可以有效消除噪声,但会引入
一定的延迟。
2. 中值滤波(Median Filter):将一组连续的数据排序,并取中间
值作为滤波结果。
该算法适用于去除周期性干扰或脉冲噪声,但对于快速
变化的信号可能无法有效滤除。
3. 加权移动平均滤波(Weighted Moving Average Filter):给予
不同的数据点不同的权重,并将加权平均值作为滤波结果。
该算法可以根
据需要调整不同数据点的权重,适用于对不同频率成分有不同抑制要求的
情况。
4. 递推平滑滤波(Recursive Smoothing Filter):根据当前输入
数据与上一次滤波结果的关系,通过递推公式计算得到滤波结果。
递推平
滑滤波可以实现实时滤波,但对于快速变化的信号可能会引入较大的误差。
5. 卡尔曼滤波(Kalman Filter):适用于估计具有线性动力学特性
的系统状态,并结合观测值进行滤波。
卡尔曼滤波算法综合考虑了系统模
型和观测模型的不确定性,因此能够提供较好的估计结果。
这些数字滤波算法在实际应用中可以根据需求进行选择和组合,以实
现对信号的有效滤波和噪声抑制。
中值滤波算法步骤:(1)对窗内的每⾏像素按降序排序,得到最⼤值、中间值和最⼩值。
(2)把三⾏的最⼩值即第三列相⽐较,取其中的最⼤值。
(3)把三⾏的最⼤值即第⼀列相⽐较,取其中的最⼩值。
(4)把三⾏的中间值即第⼆列相⽐较,再取⼀次中间值。
(5)把前⾯的到的三个值再做⼀次排序,获得的中值即该窗⼝的中值。
代码:close all;clear all;clc;I=imread('C:\Users\luoqi\Desktop\图⽚\影院\file.jpg');if ndims(I)==3I=rgb2gray(I);end[m,n]=size(I);%%%添加⾼斯⽩噪声J=zeros(m,n);simd=20*rand(1);% for i=1:m% for j=1:2:n% t1=rand(1);% t2=rand(1);% z1=simd*cos(2*pi*t1)*sqrt(-2*log(t2));% z2=simd*sin(2*pi*t1)*sqrt(-2*log(t2));% J(i,j)=I(i,j)+z1;% if j+1<=n% J(i,j+1)=I(i,j+1)+z2;% end% end% end% for i=1:m% for j=1:n% if J(i,j)>255% J(i,j)=255;% elseif J(i,j)<0% J(i,j)=0;% end% end% end%J=uint8(J);%figure(1);%imshow(J);%%%添加椒盐噪声J=imnoise(I,'salt & pepper',0.02);figure(1);imshow(J);%%%中值滤波% for i=2:m-1% for j=2:n-1% median3x3=[J(i-1,j-1),J(i-1,j),J(i-1,j+1);% J(i,j-1),J(i,j),J(i,j+1);% J(i+1,j-1),J(i+1,j),J(i+1,j+1);];% sort1=sort(median3x3,2,'descend');% sort2=sort([sort1(1),sort1(4),sort1(7)],'descend');% sort3=sort([sort1(2),sort1(5),sort1(8)],'descend');% sort4=sort([sort1(3),sort1(6),sort1(9)],'descend');% mid_num=sort([sort2(3),sort3(2),sort4(1)],'descend');% J(i,j)=mid_num(2);% end% end%%%matlab⾃带函数J=medfilt2(J);figure(2) imshow(J);。
中值滤波算法公式 中值滤波是一种常用的信号处理方法,用于去除图像或信号中的噪声。
它通过取邻域内像素的中值来替代当前像素的值,从而平滑图像或信号。
中值滤波算法的基本思想是将邻域内的像素值进行排序,然后取中间值作为当前像素的新值。
该算法的主要步骤如下: 1. 定义邻域大小:选择一个合适的邻域大小,通常是一个正方形区域。
这个区域可以是3x3、5x5乃至更大的尺寸。
2. 定位邻域:在图像中,以当前像素为中心,定位邻域大小。
3. 提取邻域像素值:根据邻域的位置,提取出所有邻域内的像素值。
4. 排序邻域像素值:对提取出的邻域像素值进行排序,从小到大排列。
5. 计算中值:取排序后的邻域像素值的中间值作为当前像素的新值。
6. 更新图像:将当前像素的新值更新到原始图像中。
7. 遍历整个图像:对所有像素都按照以上步骤处理,得到滤波后的图像。
中值滤波算法的优点在于可以有效地去除图像或信号中的椒盐噪声、斑点噪声等,同时保持图像或信号的边缘信息不被模糊化。
由于使用了中值,该算法对于异常值也具有一定的抗干扰能力。
然而,中值滤波也存在一些缺点。
首先,它无法处理大面积的噪声,因为中值滤波只能对某一个像素点进行处理。
其次,在处理图像边缘区域时,由于邻域的大小限制,可能导致边缘附近的像素值被错误地替换。
中值滤波算法在图像处理领域广泛应用。
例如,在数字图像传输过程中,由于传输或存储过程中的噪声干扰,图像容易出现噪点,这时可以利用中值滤波算法来降低噪声的影响。
另外,在数字摄影中,拍摄照片时可能会产生图像噪声,通过中值滤波可以有效去除这些噪声。
总之,中值滤波算法是一种简单而有效的信号处理方法。
通过取邻域内像素的中值来替代当前像素的值,可以去除图像或信号中的噪声。
尽管算法存在一些限制,但在很多实际应用中,中值滤波算法仍然是一种非常有用的工具。
中值滤波算法公式:
中值滤波器在处理图像时,将像素点的值设置为邻域像素值的中值。
具体来说,对于一维情况,如果序列为{x1, x2, ..., xn},中值滤波器的输出为:
median(x1, x2, ..., xn)
对于二维情况,中值滤波器通常用于消除图像中的噪声。
假设有一个二维矩阵,中值滤波器的输出为:
median(x11, x12, ..., x22)
其中,x11, x12, ..., x22是二维矩阵中每个像素点的邻域像素值。
注意:中值滤波算法对于去除图像中的椒盐噪声特别有效,但对于高斯噪声效果较差。
在更具体的应用中,中值滤波算法可以有多种变种。
例如,可以选择不同的邻域大小,可以选择对所有像素应用滤波器,或者只对特定类型的像素应用滤波器。
在某些情况下,还可以使用更复杂的排序算法来计算中值,以提高处理速度。
中值滤波算法的优点是简单且易于实现。
它不需要知道像素的统计特性,也不需要对像素值进行复杂的数学运算。
此外,中值滤波器对于去除由异常值引起的噪声特别有效。
然而,中值滤波算法也有一些局限性。
例如,它可能会改变图像的边缘细节,因为它将像素值设置为邻域像素值的中值,而不是原始像素值。
此外,对于高斯噪声,中值滤波算法可能不是最佳选择,因为高斯噪声的分布特性与中值滤波器的去除效果不太匹配。
在实际应用中,需要根据具体需求选择适当的滤波算法。
中值滤波算法适用于去除椒盐噪声,但对于其他类型的噪声,可能需要使用其他类型的滤波器,如高斯滤波器、均值滤波器或自适应滤波器等。
快速中值滤波算法————————————————————————————————作者: ————————————————————————————————日期:南昌大学实验报告学生姓名:洪僡婕学号: 6100411159专业班级: 数媒111班实验类型:■验证□综合□设计□创新实验日期:4.29 实验成绩:一、实验项目名称数字图像处理二、实验目的实现快速中值滤波算法三、实验内容用VC++实现中值滤波的快速算法四、主要仪器设备及耗材PC机一台五、实验步骤// ImageProcessingDoc.cpp: implementation of the CImageProcessingDoc class//#include "stdafx.h"#include "ImageProcessing.h"#include "ImageProcessingDoc.h"#include "GreyRatio.h"#include <math.h>#define PI (acos(0.0)* 2)#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_ char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// CImageProcessingDocIMPLEMENT_DYNCREATE(CImageProcessingDoc, CDocument)BEGIN_MESSAGE_MAP(CImageProcessingDoc, CDocument)ﻩ//{{AFX_MSG_MAP(CImageProcessingDoc)ﻩON_COMMAND(ID_HISTOGRAM_ADJUSTIFCATION, OnHistogramAdjustifcation)ﻩON_COMMAND(ID_FFT, OnFft)ON_COMMAND(ID_SALT_PEPPER_NOICE,OnSaltPepperNoice)ON_COMMAND(ID_RANDOM_NOISE,OnRandomNoise)ON_COMMAND(ID_MEDIAN_FILTERING, OnMedianFiltering)ﻩON_COMMAND(ID_DCT, OnDct)ON_COMMAND(ID_FWT, OnFwt)ON_COMMAND(ID_DHT, OnDht)ﻩON_COMMAND(ID_WAVELET_TRANSFORM, OnWaveletTransform) ON_COMMAND(ID_GREY_ADJUSTIFCATION, OnGreyAdjustifcation)ﻩON_COMMAND(ID_GREY_LINEAR_ADJUSTIFCATION, OnGreyLinearAdjustifcation)ﻩON_COMMAND(ID_GREY_SEGLINEAR_ADJUSTIFCATION, OnGreySeglinearAdjustifcation)ON_COMMAND(ID_2DGRAD, On2dgrad)ﻩON_COMMAND(ID_ROBERT, OnRobert)ﻩ//}}AFX_MSG_MAPEND_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CImageProcessingDoc construction/destructionCImageProcessingDoc::CImageProcessingDoc(){ﻩ// TODO: add one-timeconstructioncodeheremImageFile = NULL;b = FALSE;nRows = 256;nCols = 256;mSourceData = NULL;pSourceData =NULL;ﻩbDataIsProcessed = FALSE;mResultData = FALSE;pResultData =FALSE;FourierDataR = NULL;ﻩFourierDataI = NULL;}CImageProcessingDoc::~CImageProcessingDoc(){}BOOL CImageProcessingDoc::OnNewDocument(){if (!CDocument::OnNewDocument())ﻩreturn FALSE;// TODO: addreinitialization code here// (SDI documents will reuse this document)ﻩreturn TRUE;}/////////////////////////////////////////////////////////////////////////////// CImageProcessingDoc serializationvoid CImageProcessingDoc::Serialize(CArchive& ar) {ﻩif (ar.IsStoring()){// TODO: add storing codehereﻩ}ﻩelse{ﻩ//TODO: addloading code hereﻩ}}/////////////////////////////////////////////////////////////////////////////// CImageProcessingDoc diagnostics#ifdef _DEBUGvoid CImageProcessingDoc::AssertValid() const{CDocument::AssertValid();}void CImageProcessingDoc::Dump(CDumpContext&dc)const{ﻩCDocument::Dump(dc);}#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////// CImageProcessingDoc commandsBOOL CImageProcessingDoc::OnOpenDocument(LPCTSTRlpszPathName) {ﻩint x;ﻩint y;if (!CDocument::OnOpenDocument(lpszPathName))ﻩreturn FALSE;ﻩ// TODO: Add your specialized creation code hereif(mSourceData) {ﻩfree(mSourceData);ﻩﻩmSourceData = NULL;ﻩ}ﻩif (!(mSourceData = (unsigned char *)malloc(nRows*nCols*sizeof(unsigned char))))ﻩreturn FALSE;ﻩif (pSourceData) {free(pSourceData);ﻩ pSourceData = NULL;ﻩ}if (!(pSourceData= (unsigned char *)malloc(3*nRows*nCols*s izeof(unsigned char))))ﻩﻩreturn FALSE;ﻩif (mResultData) {ﻩfree(mResultData);mResultData =NULL;ﻩ}if (!(mResultData =(unsigned char*)malloc(nRows*nCols*sizeof(unsigned char))))return FALSE;ﻩif (pResultData) {ﻩfree(pResultData);ﻩpResultData = NULL;ﻩ}if (!(pResultData = (unsigned char *)malloc(3*nRows*nCols*sizeof(unsignedchar))))ﻩreturn FALSE;if (mImageFile) {ﻩfclose(mImageFile);ﻩmImageFile =NULL;}if (!(mImageFile = fopen(lpszPathName,"rb"))){free(mSourceData);returnFALSE;ﻩ}if (fread(mSourceData,sizeof(unsigned char),nRows*nCols,mImageFile)!= (unsigned)nCols*nRows) {ﻩfree(mSourceData);ﻩﻩfclose(mImageFile);mImageFile = NULL;ﻩb = false;ﻩreturn FALSE;}for(y = 0; y < nRows; y++){for(x = 0; x < nCols;x++){pSourceData[3*y*nCols+3*x] = mSourceData[y*nCol s+x];pSourceData[3*y*nCols+3*x+1] = mSourceData[y*nC ols+x];pSourceData[3*y*nCols+3*x+2] = mSourceData[y*nCols+x];ﻩ}b = TRUE;return TRUE;}void CImageProcessingDoc::OnHistogramAdjustifcation(){// TODO: Add your commandhandler code hereﻩint x,y;ﻩdouble *mR;ﻩdouble*mS;ﻩmR = new double[256];mS = new double[256];for(x=0;x<256;x++){ﻩﻩmR[x] = mS[x] = 0.0;ﻩ}ﻩ//统计直方图for(y = 0; y < nRows;y++){for(x = 0;x< nCols; x++){mR[mSourceData[y*nCols+x]] ++;}for(x=0;x<256;x++){ﻩ for(y=0;y<x;y++)ﻩﻩ mS[x] += mR[y];mS[x] /=nRows*nCols;ﻩ}//直方图变换for(y =0; y < nRows; y++)for(x = 0; x < nCols; x++)mResultData[y*nRows+x] = (char) (255*mS[mSourceData[y*nRows+x]]);ﻩ//灰度计算for(y = 0; y < nRows; y++){for(x = 0;x< nCols; x++){pResultData[3*y*nCols+3*x] = mResultData[y*nCo ls+x];pResultData[3*y*nCols+3*x+1] = mResultData[y*nCols +x];pResultData[3*y*nCols+3*x+2] = mResultData[y*nCols +x];ﻩ}//更新显示UpdateAllViews(NULL);}// FFTandIFFT 一维傅立叶变换与逆变换函数// 输入时域数据实部Tr,虚部Ti// 输出频域数据实部Tr,虚部Ti// 序列长度N,N等于2的r次幂// FFTorIFFT,逻辑变量,非零做正变换,零做反变换voidCImageProcessingDoc::FFTandIFFT(float *Tr,float *Ti, int N, bool FFTorIFFT) {ﻩintr; //迭代次数int l,j,k;//循环变量ﻩint p; //用于蝶形计算加权系数的指数ﻩintB; //对偶结点距离float X,Y,XX,YY;ﻩfloat w;ﻩfloat cosw,sinw;ﻩif (!FFTorIFFT) { //如果做傅立叶逆变换,则必须对数列除以N ﻩfor(l=0;l<N;l++){ﻩTr[l]/= N;ﻩTi[l] /=N;ﻩ}ﻩ}//计算循环次数rr= 0; l = N;ﻩwhile(l /=2) r++;//倒序int LH =N/2;int i;ﻩfloat temp;j = 0;for (i=1;i<N-1;i++){ﻩk = LH;ﻩwhile(j>=k) {ﻩﻩj = j-k;ﻩk = k/2;}j= j + k;ﻩif (i<=j) {ﻩ temp = Tr[i]; Tr[i] = Tr[j];Tr[j] = temp;ﻩﻩ temp = Ti[i]; Ti[i]= Ti[j]; Ti[j] = temp;ﻩﻩ}ﻩ}ﻩfor(l=0; l<= r; l++) //共r级{B =1<<(l-1); //第l层对偶结点距离为2^(l-1)for(j=0; j < B;j++){ﻩp = j*(1<<(r-l));w= 2*PI*p/N;ﻩﻩfor(k=j;k<N-1;k+=(1<<l)) {if (FFTorIFFT) { //若做傅立叶正变换cosw =cos(-w);ﻩsinw =sin(-w);}else{ //傅立叶反变换cosw =cos(w);ﻩsinw =sin(w);ﻩﻩ}ﻩﻩ X = Tr[k] + Tr[k+B]*cosw - Ti[k+B] * sinw;ﻩ Y = Ti[k] + Tr[k+B]*sinw + Ti[k+B] *cosw;XX = Tr[k] - Tr[k+B]*cosw + Ti[k+B] * sinw; ﻩﻩﻩ YY = Ti[k] - Tr[k+B]*sinw - Ti[k+B]* cosw;ﻩﻩTr[k] = X;ﻩTi[k] =Y;ﻩﻩTr[k+B] = XX;ﻩ Ti[k+B] = YY;ﻩ}ﻩ}}}void CImageProcessingDoc::OnFft(){// TODO: Add your command handler code hereint i,j;int ii,jj;ﻩfloat temp;float *Tr;ﻩfloat *Ti;Tr = new float[nCols];Ti = new float[nCols];if ( FourierDataR) {ﻩdelete FourierDataR;FourierDataR = NULL;}if ( FourierDataI) {delete FourierDataI;ﻩFourierDataR = NULL;}FourierDataR = new float[nRows*nCols];ﻩFourierDataI = new float[nRows*nCols];ﻩfor(i=0;i<nRows;i++){for(j=0;j<nCols;j++){ //图像数据先给傅立叶变换数组FourierDataR[i*nCols+j] = (float) mSourceData[i*nCols+j]; ﻩ FourierDataI[i*nCols+j] = 0.0;ﻩ}for (i=0;i<nRows;i++){ //每行进行傅立叶变换for (j=0;j<nCols;j++){ﻩﻩTr[j] = FourierDataR[i*nCols + j];Ti[j] =FourierDataI[i*nCols + j];}ﻩFFTandIFFT(Tr,Ti,nCols,1);ﻩﻩfor (j=0;j<nCols;j++){ﻩﻩFourierDataR[i*nCols + j] = Tr[j];FourierDataI[i*nCols + j] = Ti[j];ﻩﻩ}ﻩ}delete Tr;delete Ti;ﻩTr = new float[nRows];Ti = new float[nRows];for(j=0;j<nCols;j++){//每列进行傅立叶变换for (i=0;i<nRows;i++){ﻩTr[i]= FourierDataR[i*nCols + j];Ti[i] = FourierDataI[i*nCols + j];}FFTandIFFT(Tr,Ti,nRows,1);for (i=0;i<nRows;i++){FourierDataR[i*nCols + j] = Tr[i];FourierDataI[i*nCols + j] = Ti[i];ﻩ}ﻩ}for (i=0;i<nRows;i++){for(j=0;j<nCols;j++){ﻩﻩtemp = sqrt(FourierDataR [i*nCols+j]*FourierDataR [i*nCols+j]+FourierDataI [i*nCols+j]*FourierDataI[i*nCols+j] );ﻩtemp /= 100;ﻩﻩif(temp > 255.0)ﻩﻩﻩtemp = 255.0;ii = nRows - 1-(i<nRows/2?i+nRows/2:i-nRows/2); ﻩjj = (j<nCols/2)?(j+nCols/2):(j-nCols/2);//将变换后现实的原点调整在中心位置pResultData[3*ii*nCols+3*jj] = (int) temp;pResultData[3*ii*nCols+3*jj+1] = (int) temp;pResultData[3*ii*nCols+3*jj+2] =(int) temp;ﻩ}//更新显示UpdateAllViews(NULL);ﻩdelete FourierDataR;delete FourierDataI;ﻩFourierDataI = NULL;FourierDataR= NULL;return;ﻩ}void CImageProcessingDoc::OnSaltPepperNoice(){// TODO: Add your command handler code here// TODO: Add your command handler code hereint x;inty;ﻩSalt_Pepper_Noise(mSourceData,nCols,nRows);for(y=0; y < nRows; y++){for(x = 0; x < nCols; x++){pSourceData[3*y*nCols+3*x] = (unsigned char)mSourceData[y*nCols+x];pSourceData[3*y*nCols+3*x+1] = (unsigned char) mSou rceData[y*nCols+x];pSourceData[3*y*nCols+3*x+2] = (unsigned char) mSourceData[y*nCols+x];ﻩ}UpdateAllViews(NULL);ﻩ}void CImageProcessingDoc::OnRandomNoise(){// TODO: Addyour commandhandler code hereint x;int y;Random_Noise(mSourceData,nRows,nCols);for(y = 0; y <nRows; y++){for(x = 0; x < nCols; x++){pSourceData[3*y*nCols+3*x] = (unsigned char) mSourceData[y*nCols+x];pSourceData[3*y*nCols+3*x+1] = (unsigned char) mS ourceData[y*nCols+x];pSourceData[3*y*nCols+3*x+2] = (unsigned char) mSourceData[y*nCols+x];ﻩ}UpdateAllViews(NULL);}void CImageProcessingDoc::Salt_Pepper_Noise(unsignedchar*mdata, int nHeight, int nWidth) {unsigned char*ﻩlpSrc;ﻩ//循环变量long i;long j;ﻩ//生成伪随机种子ﻩsrand((unsigned)time(NULL));ﻩ//在图像中加噪for (j = 0;j < nHeight ;j++){for(i= 0;i< nWidth ;i++){ﻩﻩif(rand()>31500) {ﻩﻩ// 指向源图像倒数第j行,第i个象素的指针ﻩlpSrc =(unsigned char *)&mdata[j*nWidth + i];ﻩ//图像中当前点置为黑ﻩﻩ*lpSrc=0;ﻩ}ﻩ}}ﻩ// 返回ﻩreturn ;}voidCImageProcessingDoc::Random_Noise(unsigned char *mdata, i nt nHeight, int nWidth) {// 指向源图像的指针ﻩunsigned char* lpSrc;ﻩ//循环变量ﻩlong i;ﻩlong j;ﻩ//像素值unsigned char pixel;//噪声BYTE NoisePoint;ﻩ//生成伪随机种子srand((unsigned)time(NULL));ﻩ//在图像中加噪for (j = 0;j < nHeight ;j++){ﻩﻩfor(i = 0;i < nWidth ;i++){NoisePoint=rand()/1024;ﻩﻩ// 指向源图像倒数第j行,第i个象素的指针ﻩﻩlpSrc = (unsigned char *)&mdata[nWidth * j + i];ﻩﻩﻩ//取得像素值pixel= (unsignedchar)*lpSrc;ﻩ*lpSrc = (unsigned char)(pixel*224/256 + NoisePoint);ﻩ}}//返回ﻩreturn ;}void CImageProcessingDoc::MedianFiltering(unsigned char *sourcedata, unsigned char *resultdata,int nHeight, int nWidth, int nR){ int i,j,m,n,r;ﻩ unsigned tmp;unsigned char* mdata = new unsigned char[(2*nR+1)*(2*nR+1)]; ﻩ for (i=0;i<nRows;i++)ﻩ for (j=0;j<nCols;j++){ﻩif((i<nR) || (i>nHeight-nR-1)|| (j<nR) || (j>nWidth-nR-1))resultdata[i*nWidth+j] = 0;else {for(m=-nR;m<=nR;m++)for(n=-nR;n<=nR;n++)ﻩ mdata[(m+nR)*(2*nR+1)+n+nR] =sourcedata[(i+m)*nWidth+(j +n)];//排序ﻩﻩfor(m=0;m<(2*nR+1)*(2*nR+1)-2;m++){r = 1;ﻩﻩ for (n=m+1;n<(2*nR+1)*(2*nR+1);n++){ﻩﻩ if (mdata[n]<mdata[n+1]){tmp = mdata[n];mdata[n]=mdata[n+1];md ata[n+1]=tmp;r=0;ﻩﻩﻩ}ﻩﻩﻩ }ﻩﻩif (r)ﻩﻩﻩbreak;ﻩﻩﻩ}ﻩ mResultData[i*nWidth+j] = mdata[nR*(2*nR+1)+nR];}}}void CImageProcessingDoc::OnMedianFiltering(){// TODO: Add your command handler code hereint x;int y;ﻩMedianFiltering(mSourceData,mResultData,nRows,nCols,1);ﻩfor(y=0; y <nRows; y++){for(x =0;x < nCols; x++){pResultData[3*y*nCols+3*x] = (unsigned char) mResul tData[y*nCols+x];pResultData[3*y*nCols+3*x+1] = (unsigned char) mResultData[y*nCols+x];pResultData[3*y*nCols+3*x+2] = (unsigned char)mResultData[y*nCols+x];}UpdateAllViews(NULL);ﻩ}void CImageProcessingDoc::OnDct() {// TODO: Add your commandhandler code hereﻩ}void CImageProcessingDoc::OnFwt() {// TODO: Add your commandhandler code here}void CImageProcessingDoc::OnDht() {// TODO: Add your command handler code here}void CImageProcessingDoc::OnWaveletTransform() {// TODO: Add your command handler code here}void CImageProcessingDoc::OnGreyAdjustifcation() {// TODO: Add yourcommand handler code here}void CImageProcessingDoc::OnGreyLinearAdjustifcation(){// TODO: Add your command handler code hereﻩint x;ﻩint y;ﻩint tmp;CGreyRatio mdlg;ﻩmdlg.DoModal();for(y=0;y<nRows;y++)ﻩfor(x=0;x<nCols;x++){ﻩtmp =(int)(mdlg.m_GreyRatio*mSourceData[y*nCols+x]);ﻩtmp = tmp>255?255:tmp;ﻩﻩpResultData[3*y*nCols+3*x] = tmp;pResultData[3*y*nCols+3*x+1] = tmp;ﻩpResultData[3*y*nCols+3*x+2] = tmp;ﻩ}UpdateAllViews(NULL);ﻩ}void CImageProcessingDoc::OnGreySeglinearAdjustifcation(){ // TODO: Add your command handler code here}void CImageProcessingDoc::On2dgrad() {// TODO: Add your commandhandlercode hereint x;ﻩint y;int dx;ﻩintdy;ﻩint tmp;for(y=0;y<nRows-1;y++){ﻩfor(x=0;x<nCols-1;x++){ﻩdx = mSourceData[y*nCols+x]- mSourceData[y*nCols+x+1];ﻩdy = mSourceData[y*nCols+x] - mSourceData[(y+1)*nCols+x]; ﻩ tmp = (int) sqrt(dx*dx+dy*dy);ﻩﻩtmp = tmp>255?255:tmp;pResultData[3*y*nCols+3*x] = tmp;pResultData[3*y*nCols+3*x+1] = tmp;ﻩpResultData[3*y*nCols+3*x+2] = tmp;ﻩﻩ}UpdateAllViews(NULL);ﻩ}void CImageProcessingDoc::OnRobert() {//TODO:Add your command handler code hereint x;ﻩint y;ﻩint dx;int dy;inttmp;for(y=0;y<nRows-1;y++){for(x=0;x<nCols-1;x++){dx = mSourceData[y*nCols+x]-mSourceData[(y+1)*nCols+x+1];ﻩdy =mSourceData[y*nCols+x+1] -mSourceData[(y+1)*nCols+x];tmp = (int) sqrt(dx*dx+dy*dy);ﻩﻩtmp = tmp>255?255:tmp;ﻩpResultData[3*y*nCols+3*x] = tmp;ﻩpResultData[3*y*nCols+3*x+1] = tmp;pResultData[3*y*nCols+3*x+2] = tmp;}UpdateAllViews(NULL);}void CImageProcessingDoc::DCTandIDCT(float*Ff, int N, bool bDctIDct){ﻩfloat *mR;ﻩ float *mI;int i;float Ff0 = 0;ﻩ mR = new float[N*2];mI = new float[N*2];ﻩ if(bDctIDct){ﻩ for(i=0;i<2*N;i++){ﻩif(i<N)mR[i] = Ff[i];ﻩ else{ﻩﻩ mR[i] = 0;ﻩmI[i] = 0;ﻩﻩ}for(i=0;i<N;i++){Ff0 += Ff[i];Ff0 = Ff0/sqrt(N);ﻩ FFTandIFFT(mR,mI,2*N,true)Ff[0] =Ff0;for(i=0;i<N;i++){ﻩFf[i] = (mR[i]*cos(i*PI/(2*N)) + mI[i]*sin(i*PI/(2*N))) *sqrt(2.0/N);}ﻩ else{ﻩ for(i=0;i<2*N;i++){ﻩﻩ if(i<N){ﻩﻩ mR[i]= Ff[i]*cos(i*PI/(2*N));ﻩ mI[i] = Ff[i]*sin(i*PI/(2*N));ﻩ }ﻩ else{ﻩ mR[i] = 0;ﻩﻩmI[i]= 0;ﻩﻩ }}for(i=0;i<N;i++){ﻩFf0 += Ff[i];Ff0 =Ff0/sqrt(N);ﻩFFTandIFFT(mR,mI,2*N,false);ﻩfor(i=0;i<N;i++){ﻩﻩFf[i] = 1/sqrt(N) - sqrt(2.0/N) + sqrt(2.0/N)*mR[i]; ﻩ }return;}六、实验数据七、思考及体会在设计算法编制程序的时候,我们充分考虑到程序运行的时间复杂度和空间复杂度问题,在解决问题的前提下,使算法尽量简单,使程序运行占有的空间尽量的小,这样来减少不必要的时问浪费和空间浪费,从而太大的提高程序执行的效率。