快速中值滤波及c语言实现
C语言滤波算法实现
C语言滤波算法实现滤波算法是信号处理领域中一种常见的技术,用于去除信号中的噪声或不需要的部分,以提取出我们感兴趣的特征。
在C语言中,实现滤波算法可以有效地处理信号,提高信号质量和可靠性。
本文将介绍C语言中一些常见的滤波算法及其实现方法。
一、均值滤波算法均值滤波算法是一种简单而常用的滤波算法,它通过计算信号中一定窗口内像素值的平均值,替代该窗口内的每个像素值,从而达到去除噪声的目的。
下面是C语言中实现均值滤波算法的示例代码:```c#include <stdio.h>#define SIZE 5void meanFilter(int data[], int length) {int result[length];int sum = 0;for (int i = 0; i < length; i++) {sum = 0;for (int j = i - SIZE / 2; j <= i + SIZE / 2; j++) {if (j >= 0 && j < length) {sum += data[j];}}result[i] = sum / SIZE;}for (int i = 0; i < length; i++) {printf("%d ", result[i]);}}int main() {int data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};int length = sizeof(data) / sizeof(data[0]);meanFilter(data, length);return 0;}```在上述代码中,我们定义了一个`meanFilter`函数来实现均值滤波。
该函数接受一个整型数组`data`和数组长度`length`作为参数。
在函数内部,我们使用一个大小为5的滑动窗口,对每个像素进行均值计算,并将结果存储在一个新的数组`result`中。
快速中值滤波算法
南昌大学实验报告学生姓名:洪僡婕学号: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_FILEstatic 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-time construction code heremImageFile = NULL;bFileIsLoad = 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: add reinitialization code here// (SDI documents will reuse this document)return TRUE;}///////////////////////////////////////////////////////////////////////////// // CImageProcessingDoc serializationvoid CImageProcessingDoc::Serialize(CArchive& ar) {if (ar.IsStoring()) {// TODO: add storing code here}else{// TODO: add loading 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(LPCTSTR lpszPathName) { 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*sizeof(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);return FALSE;}if (fread(mSourceData,sizeof(unsigned char),nRows*nCols,mImageFile) != (unsigned)nCols*nRows) {free(mSourceData);fclose(mImageFile);mImageFile = NULL;bFileIsLoad = false;return FALSE;}for(y = 0; y < nRows; y++){for(x = 0; x < nCols; x++){pSourceData[3*y*nCols+3*x] = mSourceData[y*nCols+x];pSourceData[3*y*nCols+3*x+1] = mSourceData[y*nCols+x];pSourceData[3*y*nCols+3*x+2] = mSourceData[y*nCols+x];}bFileIsLoad = TRUE;return TRUE;}void CImageProcessingDoc::OnHistogramAdjustifcation(){// TODO: Add your command handler code hereint 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*nCols+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,逻辑变量,非零做正变换,零做反变换void CImageProcessingDoc::FFTandIFFT(float *Tr, float *Ti, int N, bool FFTorIFFT) {int r; //迭代次数int l,j,k;//循环变量int p; //用于蝶形计算加权系数的指数int B; //对偶结点距离float X,Y,XX,YY;float w;float cosw,sinw;if (!FFTorIFFT) { //如果做傅立叶逆变换,则必须对数列除以Nfor(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;int y;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) mSourceData[y*nCols+x];pSourceData[3*y*nCols+3*x+2] = (unsigned char) mSourceData[y*nCols+x];}UpdateAllViews(NULL);}void CImageProcessingDoc::OnRandomNoise(){// TODO: Add your command handler 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)mSourceData[y*nCols+x];pSourceData[3*y*nCols+3*x+2] = (unsigned char)mSourceData[y*nCols+x];}UpdateAllViews(NULL);}void CImageProcessingDoc::Salt_Pepper_Noise(unsigned char *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 ;}void CImageProcessingDoc::Random_Noise(unsigned char *mdata, int 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 = (unsigned char)*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];mdata[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) mResultData[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 command handler code here}void CImageProcessingDoc::OnFwt() {// TODO: Add your command handler 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 your command handler code here}void CImageProcessingDoc::OnGreyLinearAdjustifcation() {// TODO: Add your command handler code hereint 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 command handler code hereint x;int y;int dx;int dy;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;int tmp;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;}六、实验数据七、思考及体会在设计算法编制程序的时候,我们充分考虑到程序运行的时间复杂度和空间复杂度问题,在解决问题的前提下,使算法尽量简单,使程序运行占有的空间尽量的小,这样来减少不必要的时问浪费和空间浪费,从而太大的提高程序执行的效率。
图像处理之中值滤波介绍及C实现
图像处理之中值滤波介绍及C实现1 中值滤波概述 滤波是基于排序统计理论的⼀种能有效抑制噪声的⾮线性信号平滑处理技术,它将每⼀点的设置为该点某邻域窗⼝内的所有像素点灰度值的。
中值滤波的基本原理是把数字图像或数字序列中⼀点的值⽤该点的⼀个邻域中各点值的中值代替,让周围的值接近的真实值,从⽽消除孤⽴的噪声点。
⽅法是⽤某种结构的⼆维滑动模板,将板内按照像素值的⼤⼩进⾏排序,⽣成单调上升(或下降)的为⼆维数据序列。
⼆维滤波输出为g(x,y)=med{f(x-k,y-l),(k,l∈W)} ,其中,f(x,y),g(x,y)分别为原始图像和处理后图像。
W为⼆维模板,通常为3*3,5*5区域,也可以是不同的的形状,如线状,圆形,⼗字形,圆环形等。
2 中值滤波算法原理 中值滤波数学实现:对⼀个数字信号序列xj(-∞<j<∞)进⾏滤波处理时,⾸先要定义⼀个长度为奇数的L长窗⼝,L=2N+1,N为正整数。
设在某⼀个时刻,窗⼝内的信号样本为x(i-N),…,x(i),…,x(i+N),其中x(i)为位于窗⼝中⼼的信号样本值。
对这L个信号样本值按从⼩到⼤的顺序排列后,其中值,在i处的样值,便定义为中值滤波的输出值。
在实际应⽤中,随着所选⽤窗⼝长度的增加,滤波的计算量将会迅速增加。
因此,寻求中值滤波的快速算法,是中值滤波理论的⼀个重要研究内容。
中值滤波的快速算法,⼀般采⽤下述三种⽅式:①直⽅图数据修正法;②样本值⼆进制表⽰逻辑判断法;③数字和模拟的选择⽹络法。
对中值滤波的理论研究,还集中于统计特性分析和根序列的描述⽅⾯。
当⼀个信号序列经⼀特定窗⼝长度的中值滤波反复处理后,它会收敛于某⼀个不再变化的序列,这个序列称为中值滤波的根序列。
根序列是描述中值滤波特性的⼀个重要概念。
通过对根序列结构的研究,可以确定原信号序列中,哪些成分可以经中值滤波后保留下来,哪些成分将被抑制。
这对确定中值滤波器的窗⼝长度,提供了重要依据。
C语言十大滤波算法
C语言十大滤波算法C语言是一种广泛应用于嵌入式系统、图形界面、游戏开发等领域的编程语言。
在信号处理和图像处理等领域,滤波算法是一种重要的处理方式。
滤波算法可以对信号进行去噪、平滑、边缘检测等操作,从而提高信号的质量和准确度。
在C语言中,有许多优秀的滤波算法被广泛应用。
下面将介绍C语言中的十大滤波算法,并讨论它们的原理和应用领域。
1.均值滤波算法:均值滤波是一种简单有效的滤波算法,通过计算像素周围若干个邻域像素的平均值作为滤波结果。
均值滤波适用于去除高频噪声,但会造成图像细节的模糊。
2.中值滤波算法:中值滤波算法通过计算像素周围若干个邻域像素的中值作为滤波结果。
中值滤波可以有效去除椒盐噪声,但不能处理高斯噪声。
3.高斯滤波算法:高斯滤波算法利用高斯函数对图像进行滤波,以平滑图像并去除噪声。
高斯滤波在保持图像边缘信息的同时,能够有效降低噪声。
4.自适应中值滤波算法:自适应中值滤波算法根据像素邻域内像素的不同情况选择中值滤波器的大小,对不同噪声情况进行适应性处理。
5.双边滤波算法:双边滤波算法是一种非线性滤波算法,通过同时考虑空间信息和灰度差异信息,可在去噪的同时保持图像的边缘信息。
6.快速傅里叶变换(FFT)滤波算法:FFT滤波是一种频域滤波算法,通过将信号从时域转换到频域,对频谱进行滤波后再进行逆变换,能够有效去除周期性噪声。
7.小波变换滤波算法:小波变换是一种时频联合分析方法,将信号分解为不同频率的子带,通过阈值处理可以实现去噪。
8.自适应滤波算法:自适应滤波算法根据图像中的纹理复杂度自动选择合适的滤波器,能够在保持图像细节的同时去除噪声。
9.协同滤波算法:协同滤波算法是一种基于用户行为数据的推荐算法,通过分析用户的历史数据和相似用户群体的数据,对用户进行个性化推荐。
10.卡尔曼滤波算法:卡尔曼滤波算法是一种利用动态模型对状态进行推断的滤波算法,适用于系统状态估计、信号恢复等应用。
以上是C语言中的十大滤波算法,它们在不同领域的应用有所差异,但都能够有效地处理信号和数据,提高数据质量和准确度。
十一种滤波方法及C语言程序
一.十一种通用滤波算法(转)1、限幅滤波法(又称程序判断滤波法)A、方法:根据经验判断,确定两次采样允许的最大偏差值(设为A)每次检测到新值时判断:如果本次值与上次值之差<=A,则本次值有效如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值B、优点:能有效克服因偶然因素引起的脉冲干扰C、缺点无法抑制那种周期性的干扰平滑度差2、中位值滤波法A、方法:连续采样N次(N取奇数)把N次采样值按大小排列取中间值为本次有效值B、优点:能有效克服因偶然因素引起的波动干扰对温度、液位的变化缓慢的被测参数有良好的滤波效果C、缺点:对流量、速度等快速变化的参数不宜3、算术平均滤波法A、方法:连续取N个采样值进行算术平均运算N值较大时:信号平滑度较高,但灵敏度较低N值较小时:信号平滑度较低,但灵敏度较高N值的选取:一般流量,N=12;压力:N=4B、优点:适用于对一般具有随机干扰的信号进行滤波这样信号的特点是有一个平均值,信号在某一数值范围附近上下波动C、缺点:对于测量速度较慢或要求数据计算速度较快的实时控制不适用比较浪费RAM4、递推平均滤波法(又称滑动平均滤波法)A、方法:把连续取N个采样值看成一个队列队列的长度固定为N每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据.(先进先出原则) 把队列中的N个数据进行算术平均运算,就可获得新的滤波结果N值的选取:流量,N=12;压力:N=4;液面,N=4~12;温度,N=1~4 B、优点:对周期性干扰有良好的抑制作用,平滑度高适用于高频振荡的系统C、缺点:灵敏度低对偶然出现的脉冲性干扰的抑制作用较差不易消除由于脉冲干扰所引起的采样值偏差不适用于脉冲干扰比较严重的场合比较浪费RAM5、中位值平均滤波法(又称防脉冲干扰平均滤波法)A、方法:相当于“中位值滤波法”+“算术平均滤波法”连续采样N个数据,去掉一个最大值和一个最小值然后计算N-2个数据的算术平均值N值的选取:3~14B、优点:融合了两种滤波法的优点对于偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差C、缺点:测量速度较慢,和算术平均滤波法一样比较浪费RAM6、限幅平均滤波法A、方法:相当于“限幅滤波法”+“递推平均滤波法”每次采样到的新数据先进行限幅处理,再送入队列进行递推平均滤波处理B、优点:融合了两种滤波法的优点对于偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差C、缺点:比较浪费RAM7、一阶滞后滤波法A、方法:取a=0~1本次滤波结果=(1-a)*本次采样值+a*上次滤波结果B、优点:对周期性干扰具有良好的抑制作用适用于波动频率较高的场合C、缺点:相位滞后,灵敏度低滞后程度取决于a值大小不能消除滤波频率高于采样频率的1/2的干扰信号8、加权递推平均滤波法A、方法:是对递推平均滤波法的改进,即不同时刻的数据加以不同的权通常是,越接近现时刻的数据,权取得越大。
关于中值滤波算法,以及C语言实现
关于中值滤波算法,以及C语言实现中值滤波是一种非线性的图像平滑方法,与均值滤波器以及其他线性滤波器相比,它能够很好地滤除脉冲噪声,同时又能够保护目标图像边缘。
它是一种邻域运算,类似于卷积,但计算的不是加权求和,而是把邻域中的像素按灰度级进行排序,然后选择该组的中间值作为输出像素值,中值滤波可定义为:式中:g(x,y)和f(x-i,y-i)分别为输出和输入像素灰度值,W为模板窗口。
窗W可以取线状、方形、十字形、圆形、菱形等。
中值滤波实现过程如上图所示。
标准的中值滤波器都是由一个奇数大小尺寸的滑动窗组成,通常为3x3窗或5x5窗等。
以3x3窗为例,该窗沿着图像数据的行方向逐像素滑动,在每一次滑动期间内,方形窗中的所有像素按照灰度值被排序,这组数据中的中值作为输出,替代原来窗函数的中心位置像素的灰度值。
均值滤波和中值滤波的内容非常基础,均值滤波相当于低通滤波,有将图像模糊化的趋势,对椒盐噪声基本无能为力。
中值滤波的优点是可以很好的过滤掉椒盐噪声,缺点是易造成图像的不连续性。
在下面的代码中,中值滤波主要通过冒泡算法来实现。
含有椒盐噪声的中值滤波的效果如下,可以看到,几乎完全去除了椒盐噪声。
均值滤波的效果如下,可以看出,椒盐噪声被处理成了小的气泡,同时图像变模糊:1、什么是中值滤波?中值滤波是对一个滑动窗口内的诸像素灰度值排序,用其中值代替窗口中心象素的原来灰度值,它是一种非线性的图像平滑法,它对脉冲干扰级椒盐噪声的抑制效果好,在抑制随机噪声的同时能有效保护边缘少受模糊。
中值滤波可以过滤尖峰脉冲。
目的在于我们对于滤波后的数据更感兴趣。
滤波后的数据保留的原图像的变化趋势,同时去除了尖峰脉冲对分析造成的影响。
以一维信号的中值滤波举例。
对灰度序列80、120、90、200、100、110、70,如果按大小顺序排列,其结果为70、80、90、10O、110、120、200,其中间位置上的灰度值为10O,则该灰度序列的中值即为100。
10种简单的数字滤波算法(C++源程序)
10种简单的数字滤波算法(C++源程序)以下是10种简单的数字滤波算法C++实现示例:1. 均值滤波均值滤波是数字滤波算法的一种常见形式,它可以通过计算一定范围内像素值的平均值来平滑图像。
其C++实现如下:#include <iostream>#include <opencv2/opencv.hpp>using namespace std;using namespace cv;// Function to implement mean filtervoid meanBlur(Mat& img, Mat& result, int k_size){int img_rows = img.rows;int img_cols = img.cols;// Create a same sized blank imageresult.create(img_rows, img_cols, img.type());for(int r=0; r<img_rows; r++){for(int c=0; c<img_cols; c++){// Define the window of radius k_sizeint r_min = max(0, r-k_size/2);int r_max = min(img_rows-1, r+k_size/2);int c_min = max(0, c-k_size/2);int c_max = min(img_cols-1, c+k_size/2);// Calculate the mean valueint sum = 0;int count = 0;for (int i=r_min; i<=r_max; i++){for (int j=c_min; j<=c_max; j++){sum += img.at<uchar>(i,j);count++;}}result.at<uchar>(r,c) = (uchar) (sum/count);}}}int main(int argc, char** argv){// Load the imageMat img = imread("image.jpg", 0);// Check if image is loaded properlyif(!img.data){cout << "Failed to load image" << endl;return -1;}// Define the kernel sizeint k_size = 3;// Apply mean filterMat result;meanBlur(img, result, k_size);// Display the resultnamedWindow("Original Image", WINDOW_NORMAL);namedWindow("Mean Filtered Image", WINDOW_NORMAL);imshow("Original Image", img);imshow("Mean Filtered Image", result);waitKey(0);return 0;}在上述代码中,`meanBlur()` 函数接收一个输入图像`img` 和一个输出图像`result`,以及一个整数参数`k_size`,该参数指定滤波器的大小,即窗口的半径。
十一种滤波方法及C语言程序
一.十一种通用滤波算法(转)1、限幅滤波法(又称程序判断滤波法)A、方法:根据经验判断,确定两次采样允许的最大偏差值(设为A)每次检测到新值时判断:如果本次值与上次值之差<=A,则本次值有效如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值B、优点:能有效克服因偶然因素引起的脉冲干扰C、缺点无法抑制那种周期性的干扰平滑度差2、中位值滤波法A、方法:连续采样N次(N取奇数)把N次采样值按大小排列取中间值为本次有效值B、优点:能有效克服因偶然因素引起的波动干扰对温度、液位的变化缓慢的被测参数有良好的滤波效果C、缺点:对流量、速度等快速变化的参数不宜3、算术平均滤波法A、方法:连续取N个采样值进行算术平均运算N值较大时:信号平滑度较高,但灵敏度较低N值较小时:信号平滑度较低,但灵敏度较高N值的选取:一般流量,N=12;压力:N=4B、优点:适用于对一般具有随机干扰的信号进行滤波这样信号的特点是有一个平均值,信号在某一数值范围附近上下波动C、缺点:对于测量速度较慢或要求数据计算速度较快的实时控制不适用比较浪费RAM4、递推平均滤波法(又称滑动平均滤波法)A、方法:把连续取N个采样值看成一个队列队列的长度固定为N每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据.(先进先出原则) 把队列中的N个数据进行算术平均运算,就可获得新的滤波结果N值的选取:流量,N=12;压力:N=4;液面,N=4~12;温度,N=1~4 B、优点:对周期性干扰有良好的抑制作用,平滑度高适用于高频振荡的系统C、缺点:灵敏度低对偶然出现的脉冲性干扰的抑制作用较差不易消除由于脉冲干扰所引起的采样值偏差不适用于脉冲干扰比较严重的场合比较浪费RAM5、中位值平均滤波法(又称防脉冲干扰平均滤波法)A、方法:相当于“中位值滤波法”+“算术平均滤波法”连续采样N个数据,去掉一个最大值和一个最小值然后计算N-2个数据的算术平均值N值的选取:3~14B、优点:融合了两种滤波法的优点对于偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差C、缺点:测量速度较慢,和算术平均滤波法一样比较浪费RAM6、限幅平均滤波法A、方法:相当于“限幅滤波法”+“递推平均滤波法”每次采样到的新数据先进行限幅处理,再送入队列进行递推平均滤波处理B、优点:融合了两种滤波法的优点对于偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差C、缺点:比较浪费RAM7、一阶滞后滤波法A、方法:取a=0~1本次滤波结果=(1-a)*本次采样值+a*上次滤波结果B、优点:对周期性干扰具有良好的抑制作用适用于波动频率较高的场合C、缺点:相位滞后,灵敏度低滞后程度取决于a值大小不能消除滤波频率高于采样频率的1/2的干扰信号8、加权递推平均滤波法A、方法:是对递推平均滤波法的改进,即不同时刻的数据加以不同的权通常是,越接近现时刻的数据,权取得越大。
十一种滤波方法及C语言程序
一. 十一种通用滤波算法(转)1、限幅滤波法(又称程序判断滤波法)A、方法:根据经验判断,确定两次采样允许的最大偏差值(设为A)每次检测到新值时判断:如果本次值与上次值之差<=A, 则本次值有效如果本次值与上次值之差>A, 则本次值无效, 放弃本次值, 用上次值代替本次值B、优点:能有效克服因偶然因素引起的脉冲干扰C缺点无法抑制那种周期性的干扰平滑度差2、中位值滤波法A、方法:连续采样N次(N取奇数)把N 次采样值按大小排列取中间值为本次有效值B、优点:能有效克服因偶然因素引起的波动干扰对温度、液位的变化缓慢的被测参数有良好的滤波效果C缺点:对流量、速度等快速变化的参数不宜3、算术平均滤波法A、方法:连续取N 个采样值进行算术平均运算N 值较大时:信号平滑度较高,但灵敏度较低N 值较小时:信号平滑度较低,但灵敏度较高N值的选取:一般流量,N=12;压力:N=4B、优点:适用于对一般具有随机干扰的信号进行滤波这样信号的特点是有一个平均值,信号在某一数值范围附近上下波动C缺点:对于测量速度较慢或要求数据计算速度较快的实时控制不适用比较浪费RAM4、递推平均滤波法(又称滑动平均滤波法)A、方法:把连续取N个采样值看成一个队列队列的长度固定为N 每次采样到一个新数据放入队尾, 并扔掉原来队首的一次数据.(先进先出原则)把队列中的N个数据进行算术平均运算,就可获得新的滤波结果N值的选取:流量,N=12;压力:N=4;液面,N=4〜12;温度,N=1〜4 B、优点:对周期性干扰有良好的抑制作用,平滑度高适用于高频振荡的系统C缺点:灵敏度低对偶然出现的脉冲性干扰的抑制作用较差不易消除由于脉冲干扰所引起的采样值偏差不适用于脉冲干扰比较严重的场合比较浪费RAM5、中位值平均滤波法(又称防脉冲干扰平均滤波法)A、方法:相当于“中位值滤波法” +“算术平均滤波法”连续采样N个数据,去掉一个最大值和一个最小值然后计算N-2 个数据的算术平均值N 值的选取:3〜14B、优点:融合了两种滤波法的优点对于偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差C缺点:测量速度较慢,和算术平均滤波法一样比较浪费RAM6、限幅平均滤波法A、方法:相当于“限幅滤波法” +“递推平均滤波法” 每次采样到的新数据先进行限幅处理,再送入队列进行递推平均滤波处理B、优点:融合了两种滤波法的优点对于偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差C缺点:比较浪费RAM7、一阶滞后滤波法A、方法:取a=0〜1本次滤波结果=(1-a)*本次采样值+a*上次滤波结果B、优点:对周期性干扰具有良好的抑制作用适用于波动频率较高的场合C缺点:相位滞后,灵敏度低滞后程度取决于 a 值大小不能消除滤波频率高于采样频率的1/2 的干扰信号8、加权递推平均滤波法A、方法:是对递推平均滤波法的改进,即不同时刻的数据加以不同的权通常是,越接近现时刻的数据,权取得越大。
3X3中值滤波代码
3X3中值滤波代码在MFC框架下,实现3x3中值滤波的C语言代码如下:首先,在MFC的头文件中,定义一个用于处理图像的类`CImageProcessor`,并添加以下成员变量和函数:```cppclass CImageProcessorpublic://构造函数CImageProcessor(;//析构函数~CImageProcessor(;//中值滤波函数void MedianFilter(BYTE* pSrcImageData, BYTE* pDstImageData, int width, int height);//获取3x3矩阵中的中值BYTE GetMedianValue(BYTE* pSrcData);private://边界处理函数,处理灰度图像的边界像素int MirrorBoundary(int index, int length);```然后,在MFC的源文件中,实现上述定义的函数如下:```cppCImageProcessor::CImageProcessorCImageProcessor::~CImageProcessorvoid CImageProcessor::MedianFilter(BYTE* pSrcImageData, BYTE* pDstImageData, int width, int height)BYTE* pSrc = new BYTE[width * height];BYTE* pDst = new BYTE[width * height];memcpy(pSrc, pSrcImageData, width * height);//遍历图像for (int i = 1; i < height - 1; i++)for (int j = 1; j < width - 1; j++)BYTE* pSrcPixel = pSrc + (i * width + j);BYTE* pDstPixel = pDst + (i * width + j);//获取3x3矩阵中的中值*pDstPixel = GetMedianValue(pSrcPixel);}memcpy(pDstImageData, pDst, width * height);delete[] pSrc;delete[] pDst;BYTE CImageProcessor::GetMedianValue(BYTE* pSrcData) //将3x3矩阵中的像素值存入数组BYTE values[9] = { 0 };values[0] = *(pSrcData - width - 1);values[1] = *(pSrcData - width);values[2] = *(pSrcData - width + 1);values[3] = *(pSrcData - 1);values[4] = *pSrcData;values[5] = *(pSrcData + 1);values[6] = *(pSrcData + width - 1);values[7] = *(pSrcData + width);values[8] = *(pSrcData + width + 1);//使用冒泡排序法排序for (int i = 0; i < 9 - 1; i++)for (int j = 0; j < 9 - i - 1; j++)if (values[j] > values[j + 1])BYTE temp = values[j];values[j] = values[j + 1];values[j + 1] = temp;}}}//返回中值return values[4];int CImageProcessor::MirrorBoundary(int index, int length)if (index < 0)return -index;if (index >= length)return 2 * length - index - 1;return index;```以上是一个基本的3x3中值滤波计算的代码示例。
用C语言实现数字滤波
标题:用C语言实现数字滤波2008-05-09 16:17:33在工业过程控制系统中,由于被控对象的环境比较恶劣,干扰源比较多,仪器、仪表采集的信息常会受到干扰,所以在模拟系统中,为了消除干扰,常采用RC滤波电路,而在由工业控制计算机组成的自动检测系统中,为了提高采样的可靠性,减少虚假信息的影响,常常采用数字滤波的方法。
数字滤波的方法有很多种,可以根据不同的测量参数进行选择。
下面给出几种常用的数字滤波方法的C语言函数,这些函数有一定的通用性,用Turbo C 2.0编制而成,在研华IPC-610/386机上均编译通过,适用于PC机及其兼容机。
1. 程序判数滤波采样的信号,如因常受到随机干扰传感器不稳定而引起严重失真时,可以采用此方法。
方法是:根据生产经验确定两交采样允许的最大偏差△×,若先后两次采样的信号相减数值大于△×,表明输入的是干扰信号,应该去掉;用上次采样值作为本次采样值,若小于、等于△×表明没有受到干扰,本次采样值效。
该方法适用于慢变化的物理参数的采样,如温度、物理位置等测量系统。
程序判断滤波的C程序函数如下:float program_detect_filter(float old_new_value[], float X){float sample_value;if (fabs(old_new_value[1]_old_new_value[0])>X)sample_value=old_new_value[0];elsesample_value=old_new_value[1];retrun(sample_value);}函数调用需一个一维的两个元素的数组(old_new_value[2],用于存放上次采样值(old_new_v alue[0],)和本次采样值(old_new_value[1],),函数中sample_value表示有效采样值,X表示根据根据经验确定的两次采样允许的最大偏差△×。
中值滤波c语言
中值滤波c语言中值滤波是数字图像处理中常用的滤波方法之一,可以有效地消除图像中的噪声。
中值滤波的原理是将相邻像素的灰度值进行排序,然后取中间的值作为当前像素的灰度值,从而达到平滑图像的目的。
本文将介绍如何使用C语言实现中值滤波。
一、中值滤波的原理中值滤波是一种基于排序的滤波方法,其基本思想是对于图像中的每一个像素点,选择一定大小的邻域,将该邻域内的像素值按照大小排序,然后将中间的那个像素值作为该像素的输出值。
中值滤波的核心在于对像素值进行排序,因此其计算量较大,但能有效地去除图像的噪声。
1. 定义邻域大小中值滤波的邻域大小可以根据实际情况进行选择,通常建议选择3x3、5x5或7x7的大小。
在实现中值滤波时,需要先定义邻域的大小,然后将其用数组进行表示。
#define N 3 // 邻域大小int kernel[N*N]; // 定义邻域数组2. 将像素值存入邻域数组对于图像中的每一个像素点,需要将其邻域内的像素灰度值存入邻域数组中,这里默认将以该像素为中心的邻域内的所有像素值存入邻域数组中。
for(int i=-N/2;i<=N/2;i++){ // 遍历邻域for(int j=-N/2;j<=N/2;j++){kernel[(i+N/2)*N+j+N/2] = img[(row+i)*ncol+col+j]; // 存入邻域数组}}3. 对邻域数组进行排序将邻域数组进行快速排序,将中间的值作为当前像素的输出值。
这里使用了快速排序算法,其时间复杂度为O(nlogn)。
void quicksort(int arr[],int left,int right){ // 快速排序if(left >= right) return;int j = partition(arr,left,right);quicksort(arr,left,j-1);quicksort(arr,j+1,right);}int partition(int arr[],int left,int right){int pivot = arr[left];int i = left,j = right+1;while(true){while(arr[++i] < pivot){ if(i == right) break; } while(arr[--j] > pivot){ if(j == left) break; } if(i >= j) break;swap(arr,i,j);}swap(arr,left,j);return j;}quicksort(kernel,0,N*N-1); // 对邻域数组进行排序4. 取中间值作为当前像素的输出值将排好序的邻域数组中间的值作为当前像素的输出值。
openCV中值滤波和均值滤波的代码实现
openCV中值滤波和均值滤波的代码实现⽬录⼀.均值滤波⼆.中值滤波在开始我们今天的博客之前,我们需要先了解⼀下什么是滤波:⾸先我们看⼀下图像滤波的概念。
图像滤波,即在尽量保留图像细节特征的条件下对⽬标图像的噪声进⾏抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。
下图左边是原图右边是噪声图:消除图像中的噪声成分叫作图像的平滑化或滤波操作。
信号或图像的能量⼤部分集中在幅度谱的低频和中频段是很常见的,⽽在较⾼频段,感兴趣的信息经常被噪声淹没。
因此⼀个能降低⾼频成分幅度的滤波器就能够减弱噪声的影响。
图像滤波的⽬的有两个:⼀是抽出对象的特征作为图像识别的特征模式;另⼀个是为适应图像处理的要求,消除图像数字化时所混⼊的噪声。
⽽对滤波处理的要求也有两条:⼀是不能损坏图像的轮廓及边缘等重要信息;⼆是使图像清晰视觉效果好。
平滑滤波是低频增强的空间域滤波技术。
它的⽬的有两类:⼀类是模糊;另⼀类是消除噪⾳。
空间域的平滑滤波⼀般采⽤简单平均法进⾏,就是求邻近像元点的平均亮度值。
邻域的⼤⼩与平滑的效果直接相关,邻域越⼤平滑的效果越好,但邻域过⼤,平滑会使边缘信息损失的越⼤,从⽽使输出的图像变得模糊,因此需合理选择邻域的⼤⼩。
关于滤波器,⼀种形象的⽐喻法是:我们可以把滤波器想象成⼀个包含加权系数的窗⼝,当使⽤这个滤波器平滑处理图像时,就把这个窗⼝放到图像之上,透过这个窗⼝来看我们得到的图像。
举⼀个滤波在我们⽣活中的应⽤:美颜的磨⽪功能。
如果将我们脸上坑坑洼洼⽐作是噪声的话,那么滤波算法就是来取出这些噪声,使我们⾃拍的⽪肤看起来很光滑。
这篇博⽂会介绍中值滤波以及均值滤波两种算法⼀.均值滤波图⽚中⼀个⽅块区域(⼀般为3*3)内,中⼼点的像素为全部点像素值的平均值。
均值滤波就是对于整张图⽚进⾏以上操作。
我们可以看下图的矩阵进⾏理解缺陷:均值滤波本⾝存在着固有的缺陷,即它不能很好地保护图像细节,在图像去噪的同时也破坏了图像的细节部分,从⽽使图像变得模糊,不能很好地去除噪声点。
快速加权中值滤波代码
快速加权中值滤波代码快速加权中值滤波是一种常用的图像处理算法,它可以有效去除图像中的噪点,提高图像的质量。
下面是快速加权中值滤波的代码。
代码实现:```c++void FastWeightedMedianFilter(Mat input, Mat output, int window_size, int filter_size, double sigma){Mat temp_input, temp_output;int half_size = filter_size / 2;int step = input.channels();int index = 0;double *temp_array = newdouble[filter_size*filter_size*input.channels()];cv::copyMakeBorder(input, temp_input, half_size, half_size, half_size, half_size, cv::BORDER_REPLICATE);for (int y = half_size; y < input.rows + half_size; y++) {for (int x = half_size; x < input.cols + half_size; x++) {index = 0;for (int i = (-half_size); i <= half_size; i++) {for (int j = (-half_size); j <= half_size; j++) {int index_temp = (y + i)*temp_input.step + (x + j)*step;temp_array[index++] = ((double*)(temp_input.data + index_temp))[0];}}sort(temp_array, temp_array + filter_size*filter_size);double median = 0, total_weight = 0;int half_index = filter_size / 2;for (int i = 0; i < filter_size; i++) {double weight = exp((-pow((temp_array[half_index] - temp_array[i]), 2)) / (2 * pow(sigma, 2)));median += weight*temp_array[i];total_weight += weight;}int index_output = (y - half_size)*output.step + (x - half_size)*step;for (int i = 0; i < input.channels(); i++) {((uchar*)(output.data + index_output))[i] = median / total_weight;}}}delete[] temp_array;}```代码说明:该代码实现了一种快速加权中值滤波的算法,其中:- input:输入图像;- output:输出图像;- window_size:窗口大小,即图像上选取的窗口的大小;- filter_size:滤波器大小,即对窗口内的像素进行排序的大小;- sigma:高斯函数的标准差。
中值滤波C语言优化
中值滤波C语⾔优化中值滤波C语⾔优化图像平滑是图像预处理的基本操作,本⽂⾸先⽤不同的⽅法对⼀张图⽚做预处理⽐较它们效果的不同,然后针对中值滤波,实现了⼀种快速实现.(其实是copy的opencv实现,呵呵).因为opencv的实现⽅法感觉太好了,今天就特别写下来.既有备忘的作⽤,同时如果谁看到这篇⽂章,也可以借鉴下opencv的实现.1 原始图像2 均值滤波图像3 中值滤波图像4 双边滤波图像5⾼斯滤波图像上图的代码void CDialogTest2013Dlg::OnBnClickedMfcbutton1(){char file[10]="e:\\1.jpg";IplImage *src = cvLoadImage(file,0);CvSize picSize;picSize.width = src->width;picSize.height = src->height;IplImage *dst_midian= cvCreateImage(picSize,8,1);IplImage *dst_blur = cvCreateImage(picSize,8,1);IplImage *dst_gaussian = cvCreateImage(picSize,8,1);IplImage *dst_bilateral = cvCreateImage(picSize,8,1);cvSmooth(src, dst_midian, CV_MEDIAN,3,3);cvSmooth(src, dst_blur, CV_BLUR,3,3);cvSmooth(src, dst_gaussian, CV_GAUSSIAN,3,3);cvSmooth(src, dst_bilateral, CV_BILATERAL,3,3);}均值滤波原理:把⼀个点周围点求均值,这个均值给这个点.中值滤波原理:把⼀个点周围的点排序,把中位数给这个点.⾼斯滤波原理:均值滤波对⼀个点周围点求和是每个点的权重都是1,⾼斯滤波的权重不是1了,是⼀个类似⾼斯分布的权重分布,距离⽬标点近的地⽅权重⾼点,距离⽬标点远的地⽅,权重低些.中值滤波的opencv实现template<class Op, class VecOp>staticvoidmedianBlur_SortNet(const Mat& _src, Mat& _dst,int m ){typedef typename Op::value_type T;typedef typename Op::arg_type WT;typedef typename VecOp::arg_type VT;const T* src =(const T*)_src.data;T* dst =(T*)_dst.data;int sstep =(int)(_src.step/sizeof(T));int dstep =(int)(_dst.step/sizeof(T));Size size = _dst.size();int i, j, k, cn = _src.channels();Op op;VecOp vop;VecOp vop;volatile bool useSIMD = checkHardwareSupport(CV_CPU_SSE2);if( m ==3){if( size.width ==1|| size.height ==1){int len = size.width + size.height -1;int sdelta = size.height ==1? cn : sstep;int sdelta0 = size.height ==1?0: sstep - cn;int ddelta = size.height ==1? cn : dstep;for( i =0; i < len; i++, src += sdelta0, dst += ddelta )for( j =0; j < cn; j++, src++){WT p0 = src[i >0?-sdelta :0];WT p1 = src[0];WT p2 = src[i < len -1? sdelta :0];op(p0, p1); op(p1, p2); op(p0, p1);dst[j]=(T)p1;}return;}size.width *= cn;for( i =0; i < size.height; i++, dst += dstep ){const T* row0 = src + std::max(i -1,0)*sstep;const T* row1 = src + i*sstep;const T* row2 = src + std::min(i +1, size.height-1)*sstep;int limit = useSIMD ? cn : size.width;for(j =0;;){for(; j < limit; j++){int j0 = j >= cn ? j - cn : j;int j2 = j < size.width - cn ? j + cn : j;WT p0 = row0[j0], p1 = row0[j], p2 = row0[j2];WT p3 = row1[j0], p4 = row1[j], p5 = row1[j2];WT p6 = row2[j0], p7 = row2[j], p8 = row2[j2];op(p1, p2); op(p4, p5); op(p7, p8); op(p0, p1);//op(p1, p2) 交换p1和p2两个数 op(p3, p4); op(p6, p7); op(p1, p2); op(p4, p5);op(p7, p8); op(p0, p3); op(p5, p8); op(p4, p7);op(p3, p6); op(p1, p4); op(p2, p5); op(p4, p7);op(p4, p2); op(p6, p4); op(p4, p2);dst[j]=(T)p4;}if( limit == size.width )break;for(; j <= size.width - VecOp::SIZE - cn; j += VecOp::SIZE ){VT p0 = vop.load(row0+j-cn), p1 = vop.load(row0+j), p2 = vop.load(row0+j+cn); VT p3 = vop.load(row1+j-cn), p4 = vop.load(row1+j), p5 = vop.load(row1+j+cn); VT p6 = vop.load(row2+j-cn), p7 = vop.load(row2+j), p8 = vop.load(row2+j+cn);vop(p1, p2); vop(p4, p5); vop(p7, p8); vop(p0, p1);vop(p3, p4); vop(p6, p7); vop(p1, p2); vop(p4, p5);vop(p7, p8); vop(p0, p3); vop(p5, p8); vop(p4, p7);vop(p3, p6); vop(p1, p4); vop(p2, p5); vop(p4, p7);vop(p4, p2); vop(p6, p4); vop(p4, p2);vop.store(dst+j, p4);}limit = size.width;}}}}}。
中位数滤波算法 c语言
中位数滤波算法 c语言中位数滤波算法是一种常用的信号处理算法,在数字信号处理和图像处理领域广泛应用。
该算法的目的是通过对一组数据进行排序,并选择其中的中位数作为滤波后的结果,以消除数据中的异常值或噪声,从而得到更加平滑的信号。
在实际应用中,我们经常会遇到信号中存在不稳定的噪声或异常值,这些噪声或异常值可能会影响到我们对信号的分析和处理。
中位数滤波算法通过选择一组数据中的中位数作为滤波后的结果,可以有效地消除这些噪声或异常值。
中位数是一组数据中的中间值,即将数据按照大小排序后,处于中间位置的数。
在一组数据中,有一半的数据比中位数大,有一半的数据比中位数小。
因此,中位数具有很好的抗干扰能力,能够有效地消除噪声或异常值的影响。
中位数滤波算法的实现过程如下:1. 将待滤波的数据存储在一个数组中。
2. 对数组进行排序,从小到大或从大到小。
3. 如果数组的长度为奇数,选择中间位置的数作为中位数;如果数组的长度为偶数,选择中间两个数的平均值作为中位数。
4. 将中位数作为滤波后的结果输出。
中位数滤波算法的优点是简单、易于实现,并且能够有效地消除噪声或异常值。
然而,该算法也存在一些缺点。
首先,该算法只能处理一维数据,对于二维或多维数据需要进行适当的扩展。
其次,中位数滤波算法对于突变信号的处理效果不好,可能会引入额外的误差。
此外,该算法的计算复杂度较高,特别是在处理大规模数据时,可能会消耗较长的时间。
为了改进中位数滤波算法的性能,可以采用一些优化策略。
例如,可以使用快速排序等高效的排序算法来对数据进行排序,以减少计算时间。
此外,还可以结合其他滤波算法,如均值滤波或高斯滤波,来进一步提高滤波效果。
中位数滤波算法是一种常用的信号处理算法,能够有效地消除噪声或异常值,得到更加平滑的信号。
在实际应用中,我们可以根据具体的需求和信号特点选择合适的滤波算法,并进行适当的优化,以获得更好的滤波效果。
快速中值滤波 c代码
快速中值滤波 c代码快速中值滤波是一种非线性信号处理技术,通常用于消除图像或信号中的噪声。
以下是一个简单的快速中值滤波器的C代码实现。
这个实现使用了简单的排序算法,因此对于大数据集可能不是最优的,但对于小到中等大小的数据集,它的性能应该是可以接受的。
c#include <stdio.h>#include <stdlib.h>// 函数声明void findMedian(int arr[], int n, int *median);// 函数定义void findMedian(int arr[], int n, int *median) {// 冒泡排序,对于小的数据集可以直接使用简单的排序算法for(int i = 0; i < n; i++) {for(int j = 0; j < n - i - 1; j++) {if(arr[j] > arr[j+1]) {int temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}*median = arr[n/2]; // 计算中值}// 主函数int main() {int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; // 输入数组int n = sizeof(arr) / sizeof(arr[0]); // 数组长度int median; // 中值findMedian(arr, n, &median); // 找到中值printf("The median of the array is: %d\n", median); // 输出中值return 0;}以上代码实现了一个简单版本的快速中值滤波器。
请注意,在实际使用中,可能需要根据应用的具体需求对代码进行相应的修改和优化。
用C语言在微机上实现中值滤波及其快速算法
用C语言在微机上实现中值滤波及其快速算法
熊金泉;李鉴庆
【期刊名称】《江西教育学院学报》
【年(卷),期】1999(020)006
【摘要】本文讨论了用C语言在微机上实现中值滤波及快速算法,在程序设计的过程中充分考虑到程序运行的时间复杂度和空间复杂度的问题,解决了由于图象太大而内存不够的问题,运用对程序运行时的方法,得出在PENTIUM-S100MHz 上中值滤波的一般算法运行4.23秒,而快速算法运行2.58秒。
【总页数】4页(P13-16)
【作者】熊金泉;李鉴庆
【作者单位】无
【正文语种】中文
【中图分类】TN713
【相关文献】
1.快速中值滤波算法的改进及其FPGA实现 [J], 李国燕;侯向丹;顾军华;陆益财;范培培
2.快速中值滤波算法研究及其FPGA硬件实现 [J], 韩团军
3.基于System Generator的快速中值滤波算法设计与实现 [J], 代书博;徐伟;朴永杰;陈彦彤
4.基于FPGA快速中值滤波算法的硬件实现 [J], 赵亮;刘鹏;王晓曼;刘美
5.基于FPGA的快速中值滤波算法实现 [J], 赵凤怡
因版权原因,仅展示原文概要,查看原文内容请购买。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
快速中值滤波及c语言实现学生姓名:刘勇学号:6100410218 专业班级:数媒101【摘要】本文讨论了用c语言在微机上实现中值滤波及快速算法,在程序设计的过程中充分考虑到程序运行的时间复杂度和空间复杂度的问题.解决了由于图像太大而内存不够的问题,运用对程序运行时的方法,得出在PENTIUM-S100MHz上中值滤渡的一般算法运行4.23秒.而快速算法运行2 58秒。
【关键词】c语言;中值滤波;快速算法1 引言中值滤波是涂基发明的一种非线性信号处理技术,对抑制图像的噪声非常有效,在二维形式下,中值滤渡器是一个古有奇数个像素的滑动窗口,窗口正中的象素的灰度值用窗口内各个象素的中值代替窗口的中值为窗口中象素按大小顺序排列后处于中间位置的象素;本文讨论中值滤的一般算法并比较其运算速度。
2 用C语言实现算法的若干问题在设计算法编制程序的时候,我们充分考虑到程序运行的时间复杂度和空间复杂度问题,在解决问题的前提下,使算法尽量简单,使程序运行占有的空间尽量的小,这样来减少不必要的时问浪费和空间浪费,从而太大的提高程序执行的效率。
首先考虑到的内存问题。
由于在本文算法中用的图像是512+512 8bit,这就存在一个内存不够大一整幅图像不能一次性调入的问题。
为了解受此问题,可以只开辟一个3"512的缓冲区n,将原图像采用分批调入缓冲区,使内存不够的问题得到了圆满的解决。
另外为了对中值滤波的快速算法和普通算法进行精确的比较,采用对程序运行计时的方法,并精确计算每个算法运行的时间,使得出的结论更可靠。
3 中值滤波算法的C语言程序实现本算法采用对开辟的3*512的缓冲区从左到右依次形成一个3*3的窗口.然后将此3*3的窗口放人一个一维数组中,调用求中值子函数.通过排序得出中值,当此中值不等于窗口中间位置的象素时.用此中值来代替窗VI中间位置的象素灰度值.若此缓冲区处理完毕后,将缓冲区的第一行存入新建的文件中,将第二、第三行分别向上移动一行,若存人新建的文件中的行数小于或等于511(即这样处理的行数小于或等于511),则从原文件中调入一行作为缓冲区第三行,按上述方法进行直到处理的总行数等于511为止,最后,将缓冲区的第二、三行存人新建的文件,程序流程框图如图14 中值滤波快速算法的C语言程序实现本算法充分利用了上一次处理的结果.采用迭代,逐次逼近的方法得到本次的中值,在一行处理完毕后转人下一行也采用走S型的方法.这样除第一个窗口采用了一伏排序得到中值外,其它的窗口都利用上伏的窗口的象素删除无用的3个象素后再加人新的3个象素,利用迭代的方法得到本次窗口的中值.这样太大地提高了程序执行的效率。
4.1算法的解释首先是开辟一个3*512的缓冲区a,在初始化缓冲区时考虑到时间复杂度的问题,所以只初始化了第二、三行,而对第一行只初始化了前三个象素,这样便在缓冲区中可以得到一个3*3的窗口,对此窗口进行排序求中值后得出第一个窗口的中间象素的值.将文件指针定位在2*512处。
然后开始循环,当处理的行数小于或等于511时,将缓冲区a中的第二、三行分别向上移动一行变为第一、二行,从文件中读人512个字节作为缓冲区的第三行,并用行数模2的方法设置方向标志k.当k为0时,从左向右移动窗口.当k为1时.从右向左移动窗口.而每一窗口都利用上次的窗口的像素删除无用的3个象素后再加入新的3个象素.利用迭代的方法从上次的中值得到本次的中值。
当处理完一行后将缓冲区的第一行存入新建的文件中,最后将缓冲区的第二、三行存入文件中。
4.2 算法代码// 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_FILEstatic 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-time construction code heremImageFile = NULL;bFileIsLoad = 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: add reinitialization code here// (SDI documents will reuse this document)return TRUE;}///////////////////////////////////////////////////////////////////// ////////// CImageProcessingDoc serializationvoidCImageProcessingDoc::Serialize(CArchive&ar){if (ar.IsStoring()){// TODO: add storing code here}else{// TODO: add loading code here}}///////////////////////////////////////////////////////////////////// ////////// CImageProcessingDoc diagnostics#ifdef _DEBUGvoidCImageProcessingDoc::AssertValid() const{CDocument::AssertValid();}voidCImageProcessingDoc::Dump(CDumpContext& dc) const{CDocument::Dump(dc);}#endif //_DEBUG///////////////////////////////////////////////////////////////////// ////////// CImageProcessingDoc commandsBOOL CImageProcessingDoc::OnOpenDocument(LPCTSTR lpszPathName) {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*sizeof(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(unsigned char))))return FALSE;if (mImageFile){fclose(mImageFile);mImageFile = NULL;}if (!(mImageFile = fopen(lpszPathName,"rb"))){free(mSourceData);return FALSE;}if (fread(mSourceData,sizeof(unsignedchar),nRows*nCols,mImageFile) != (unsigned)nCols*nRows) {free(mSourceData);fclose(mImageFile);mImageFile = NULL;bFileIsLoad = false;return FALSE;}for(y = 0; y <nRows; y++)for(x = 0; x <nCols; x++){pSourceData[3*y*nCols+3*x] = mSourceData[y*nCols+x]; pSourceData[3*y*nCols+3*x+1] = mSourceData[y*nCols+x]; pSourceData[3*y*nCols+3*x+2] = mSourceData[y*nCols+x];}bFileIsLoad = TRUE;return TRUE;}voidCImageProcessingDoc::OnHistogramAdjustifcation(){// TODO: Add your command handler code hereintx,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*nCols+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, boolFFTorIFFT){int r; //迭代次数intl,j,k;//循环变量int p; //用于蝶形计算加权系数的指数int B; //对偶结点距离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;inti;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;}}}}voidCImageProcessingDoc::OnFft(){// TODO: Add your command handler code hereinti,j;intii,jj;float temp;float *Tr;float *Ti;Tr = new float[nCols];Ti = new float[nCols];if ( FourierDataR){deleteFourierDataR;FourierDataR = NULL;}if ( FourierDataI){deleteFourierDataI;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];}}deleteTr;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);deleteFourierDataR;deleteFourierDataI;FourierDataI = NULL;FourierDataR = NULL;return;}voidCImageProcessingDoc::OnSaltPepperNoice(){// TODO: Add your command handler code here // TODO: Add your command handler code here int x;int y;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) mSourceData[y*nCols+x];pSourceData[3*y*nCols+3*x+2] = (unsigned char) mSourceData[y*nCols+x];}UpdateAllViews(NULL);}voidCImageProcessingDoc::OnRandomNoise(){// TODO: Add your command handler 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) mSourceData[y*nCols+x];pSourceData[3*y*nCols+3*x+2] = (unsigned char) mSourceData[y*nCols+x];}UpdateAllViews(NULL);}voidCImageProcessingDoc::Salt_Pepper_Noise(unsigned char *mdata, intnHeight, intnWidth){unsigned char* lpSrc;//循环变量longi;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, intnHeight, intnWidth){// 指向源图像的指针unsigned char* lpSrc;//循环变量longi;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 = (unsigned char)*lpSrc;*lpSrc = (unsigned char)(pixel*224/256 + NoisePoint);}}// 返回return ;}voidCImageProcessingDoc::MedianFiltering(unsigned char *sourcedata, unsigned char *resultdata,intnHeight, intnWidth, intnR){inti,j,m,n,r;unsignedtmp;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];mdata[n+1] =tmp;r=0;}}if (r)break;}mResultData[i*nWidth+j] = mdata[nR*(2*nR+1)+nR];}}}voidCImageProcessingDoc::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) mResultData[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);}voidCImageProcessingDoc::OnDct(){// TODO: Add your command handler code here}voidCImageProcessingDoc::OnFwt(){// TODO: Add your command handler code here}voidCImageProcessingDoc::OnDht(){// TODO: Add your command handler code here}voidCImageProcessingDoc::OnWaveletTransform(){// TODO: Add your command handler code here}voidCImageProcessingDoc::OnGreyAdjustifcation(){// TODO: Add your command handler code here}voidCImageProcessingDoc::OnGreyLinearAdjustifcation(){// TODO: Add your command handler code hereint x;int y;inttmp;CGreyRatiomdlg;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);}voidCImageProcessingDoc::OnGreySeglinearAdjustifcation() {// TODO: Add your command handler code here}voidCImageProcessingDoc::On2dgrad(){// TODO: Add your command handler code hereint x;int y;int dx;intdy;inttmp;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);}voidCImageProcessingDoc::OnRobert(){// TODO: Add your command handler code hereint x;int y;int dx;intdy;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);}voidCImageProcessingDoc::DCTandIDCT(float *Ff, int N, boolbDctIDct) {float *mR;float *mI;inti;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];elsemR[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;}结果截图;5 结论本文充分考虑到程序运行的时间复杂度和空间复杂度问题。