当前位置:文档之家› 中值滤波器设计及椒盐噪声滤除

中值滤波器设计及椒盐噪声滤除

题目四:中值滤波器设计及椒盐噪声滤除一、实验背景在数字图像的生成与采集过程中,由于受工作环境,器件等性能的影响,使得一幅未经处理的原始图像,都存在着一定的噪声干扰。

这种噪声具有以下性质:1、图像上的噪声出现处呈现不规则分布;2、噪声的大小也是不规则的。

这些噪声恶化了图像质量,使图像模糊甚至淹没目标特征,给后续的处理分析带来了困难。

因此需要对图像应该进行滤除噪声处理。

二、 实验目的1. 通过利用c 程序实现数字信号处理的相关功能,巩固对信号处理原理知识的理解,培养快速解决实际问题的能力提高实际编程和处理数据的综合能力,初步培养在解决信号处理实际应用问题中所应具备的基本素质和要求。

2. 培养独立思考的能力与研发能力,通过设计实现不同的信号处理问题,初步掌握在给定条件和功能的情况下,实现合理设计算法结构的能力。

3. 提高资料查询和整理的能力。

能够在短时间内找到适合自己的方法。

并在文献整理的过程中学会科技文献的写作,提高语言表达能力。

三、 实验内容1. 理解什么是椒盐噪声,中值滤波的原理及其特性。

2. 设计一种中值滤波,对椒噪声滤波有效,并分析滤波器的适用范围。

3、(扩展训练)对设计的滤波器针对椒、盐噪声滤除分别进行测试,并进行性能比较分析,并讨论椒、盐噪声频度(噪声数目占图像实际像素的百分比)对滤波器实际效果的影响。

四、实验原理1.椒盐噪声椒盐噪声又称脉冲噪声,是由图像传感器,传输信道,解码处理等产生的黑白相间的亮暗点噪声。

椒盐噪声往往由图像切割引起。

椒盐噪声的PDF 是:如果b>a ,灰度值b 在图像中将显示为一个亮点,a 的值将显示为一个暗点。

若或 为零,则脉冲噪声称为单级脉冲。

如果 和 均不为零,尤其是他们近似相等时,脉冲噪声值将类似于随机分布在图像上的胡椒和盐粉微粒。

()⎪⎩⎪⎨⎧===其他0b z P a z P z p b aa Pb P a P b P形象的说,椒噪声在图像上是类似于黑胡椒颗粒的小点,而盐噪声在图像上是类似于白色盐粒的小点。

2、 平滑化去噪声思想如何从一副有噪声的图像中把噪声去除呢?此时,因有随机噪声而把像素的真值隐藏起来,而不被知晓,可表现为图像变暗而不清楚。

我们的目的是要把干扰的噪声除去,得到视觉清晰的图像。

如右图,噪声的浓度与其周围像素的浓度间,存在着很大的浓度差,使人觉得很刺眼, 利用噪声的这种性质除去噪声的方法,一般称为平滑化(smoothing )。

3、中值滤波的原理及特性:中值滤波在图像处理中,常用于用来保护边缘信息,是一种经典的平滑噪声的方法。

(1)中值滤波原理中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波的基本原理是把数字图像或数字序列中一点的值用该点的一个拎域中各点值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声点。

方法是去某种结构的二维滑动模板,将板内像素按照像素值的大小进行排序,生成单调上升(或下降)的为二维数据序列。

二维中值滤波输出为g (x,y )=med{f(x-k,y-l),(k,l ∈W)} ,其中,f(x,y),g(x,y)分别为原始图像和处理后图像。

W 为二维模板,通常为2*2,3*3区域,也可以是不同的的形状,如线状,圆形,十字形,圆环形等。

(2)中值滤波器:中值滤波器:用该像素相邻像素的灰度中值来代替该像素的值 :实现方法:a. 通过从图像中的某个采样窗口取出奇数个数据进行排序,位于采样窗中间的中值作为输出;b. 丢弃最早的值,用排序后的中值取代要处理的数据即可。

(3)中值滤波特性)},({),(ˆ),(t s g median y x fxyS t s ∈=中值滤波是图像处理中的一个常用步骤,它对于斑点噪声和椒盐噪声来说尤其有用。

中值滤波方法以牺牲图像清晰度为代价消除图像中的椒盐噪声。

中值滤波不能保证把噪声去除,只能在有限的范围内减弱噪声对图像的影响。

同时,中值滤波不能多次使用,因为这样会使图像各个像素间趋于相同,整个图像就会变得越来越模糊。

另外,通过查阅资料发现,中值滤波器的效果不仅仅和观察窗的大小有关,还和观察窗的形状有关。

五、实验步骤1、根据题目要求,先画出程序的流程图。

结束结束2、源程序:(1)基础训练部分:#include <windows.h>#include <stdio.h>unsigned char*pBmpBuf=NULL;//读入图像数据的指针unsigned char*pBmpBuf2=NULL;//读入图像数据的指针int bmpWidth; //图像宽度int bmpHeight; //图像高度RGBQUAD *pColorTable;//颜色表指针int biBitCount; //图像类型,每像素的位数//读程序可读取8,24位图,本实验是对8位灰度图进行操作,满足要求bool readBmp(char *bmpName,int ImageWidth,int ImageHeight){int i,j; //行列数BYTE **B; //分别对应图像的RGB,本实验中RGB相等,故意义不大BYTE **R;BYTE **G;FILE *fp=fopen(bmpName,"rb"); //打开文件if(fp==0) return 0;fseek(fp,sizeof(BITMAPFILEHEADER),0); //找出头文件BITMAPINFOHEADER head;fread(&head,sizeof(BITMAPINFOHEADER),1,fp);ImageWidth=head.biWidth; //图像宽度赋值ImageHeight=head.biHeight; //图像高度赋值bmpWidth=ImageWidth;bmpHeight=ImageHeight;biBitCount=head.biBitCount;int lineByte=(bmpWidth*biBitCount/8+3)/4*4; //一行中信息点字节if (biBitCount==8){pColorTable=new RGBQUAD[256];fread(pColorTable,sizeof(RGBQUAD),256,fp);}pBmpBuf=new unsigned char[lineByte*bmpHeight];fread(pBmpBuf,1,lineByte*bmpHeight,fp);//开空间B=NULL;B=(BYTE**)malloc(sizeof(BYTE*)*bmpHeight);for(i=0; i<bmpHeight; i++)B[i] = (BYTE*)malloc(sizeof(BYTE)*bmpWidth);if(B==NULL){printf("fail to malloc B\n");exit(0);}G=NULL;G=(BYTE**)malloc(sizeof(BYTE*)*bmpHeight);for(i=0; i<bmpHeight; i++)G[i] = (BYTE*)malloc(sizeof(BYTE)*bmpWidth);if(G==NULL){printf("fail to malloc G\n");exit(0);}R=NULL;R=(BYTE**)malloc(sizeof(BYTE*)*bmpHeight);for(i=0; i<bmpHeight; i++)R[i] = (BYTE*)malloc(sizeof(BYTE)*bmpWidth);if(R==NULL){printf("fail to malloc R\n");exit(0);}//读图像的RGBif (biBitCount==8){for(i=0;i<bmpHeight/50;i++){for(j=0;j<bmpWidth/50;j++){B[i][j]=*(pBmpBuf+i*lineByte+j);G[i][j]=*(pBmpBuf+i*lineByte+j);R[i][j]=*(pBmpBuf+i*lineByte+j);printf("(B=%d,G=%d,R=%d)\n",B[i][j],G[i][j],R[i][j]);}}}else if (biBitCount==24){for(i=0;i<bmpHeight/100;i++){for(j=0;j<bmpWidth/100;j++){B[i][j]=*(pBmpBuf+i*lineByte+j*3+0);G[i][j]=*(pBmpBuf+i*lineByte+j*3+1);R[i][j]=*(pBmpBuf+i*lineByte+j*3+2);printf("(B=%d,G=%d,R=%d)\n",B[i][j],G[i][j],R[i][j]);}}}fclose(fp);//释放空间for(i=0; i<bmpHeight; ++i)free(B[i]);free(B);B=NULL;for(i=0; i<bmpHeight; ++i)free(G[i]);free(G);G=NULL;for(i=0; i<bmpHeight; ++i)free(R[i]);free(R);R=NULL;return 1;}bool writeBmp(char *bmpName, int ImageWidth,int ImageHeight){unsigned char *imgBuf=pBmpBuf2;if(!imgBuf)return 0;int colorTablesize=0;if(biBitCount==8)colorTablesize=1024;int lineByte=(ImageWidth*biBitCount/8+3)/4*4;FILE *fp=fopen(bmpName,"wb");if (fp==0) return 0;BITMAPFILEHEADER fileHead;fileHead.bfType=0x4D42;fileHead.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTab lesize+lineByte*ImageHeight;fileHead.bfReserved1=0;fileHead.bfReserved2=0;fileHead.bfOffBits=54+colorTablesize;fwrite(&fileHead,sizeof(BITMAPFILEHEADER),1,fp);BITMAPINFOHEADER head;head.biBitCount=biBitCount;head.biClrImportant=0;head.biClrUsed=0;head.biCompression=0;head.biHeight=ImageHeight;head.biPlanes=1;head.biSize=40;head.biSizeImage=lineByte*ImageHeight;head.biWidth=ImageWidth;head.biXPelsPerMeter=0;head.biYPelsPerMeter=0;fwrite(&head,sizeof(BITMAPINFOHEADER),1,fp);if (biBitCount==8)fwrite(pColorTable,sizeof(RGBQUAD),256,fp);fwrite(imgBuf,ImageHeight*lineByte,1,fp);fclose(fp);return 1;}void Med(){int i,j,a,b;BYTE p[9],s;int lineByte=(bmpWidth +3)/4*4; //计算一行中储存信息的字节数pBmpBuf2=new unsigned char[lineByte*bmpHeight];memcpy(pBmpBuf2,pBmpBuf,lineByte*bmpHeight); //将原图复制//观察窗取3*3的矩形窗for(i=1;i<bmpHeight-2;i++) //边缘不进行处理{for(j=3;j<bmpWidth*3-3;j=j+3) //每一个像素点由RGB三个字节组成,故一个单元为三字节,相对应改变就需要将列数值j设为每三字节取一次//取原图像中该点周围的一个矩形部分{p[0]=*(pBmpBuf+(i-1)*lineByte+j-3);p[1]=*(pBmpBuf+(i-1)*lineByte+j);p[2]=*(pBmpBuf+(i-1)*lineByte+j+3);p[3]=*(pBmpBuf+i*lineByte+j-3);p[4]=*(pBmpBuf+i*lineByte+j);p[5]=*(pBmpBuf+i*lineByte+j+3);p[6]=*(pBmpBuf+(i+1)*lineByte+j-3);p[7]=*(pBmpBuf+(i+1)*lineByte+j);p[8]=*(pBmpBuf+(i+1)*lineByte+j+3);//排序for(a=0;a<5;a++){for(b=a+1;b<9;b++){if (p[a]>p[b]){s=p[a];p[a]=p[b];p[b]=s;}}}*(pBmpBuf2+i*lineByte+j)=p[4]; //取中值}}}void main(){char readPath[]="输入图像.bmp";readBmp(readPath,bmpWidth,bmpHeight);printf("width=%d,height=%d,biBitCount=%d\n",bmpWidth,bmpHeight,biBitCount) ;Med();char writePath[]="输出图像.bmp";writeBmp(writePath,bmpWidth,bmpHeight);delete []pBmpBuf;delete []pBmpBuf2;if(biBitCount==8)delete[] pColorTable;}(2)扩展训练部分#include <windows.h>#include <stdio.h>unsigned char*pBmpBuf=NULL;//读入图像数据的指针unsigned char*pBmpBuf2=NULL;//读入图像数据的指针2unsigned char*pBmpBuf3=NULL;//读入图像数据的指针3int bmpWidth;int bmpHeight;RGBQUAD *pColorTable;//颜色表指针int biBitCount; //图像类型,每像素的位数bool readBmp(char *bmpName,int ImageWidth,int ImageHeight){int i,j;BYTE **B;BYTE **R;BYTE **G;FILE *fp=fopen(bmpName,"rb");if(fp==0) return 0;fseek(fp,sizeof(BITMAPFILEHEADER),0);BITMAPINFOHEADER head;fread(&head,sizeof(BITMAPINFOHEADER),1,fp);ImageWidth=head.biWidth;ImageHeight=head.biHeight;bmpWidth=ImageWidth;bmpHeight=ImageHeight;biBitCount=head.biBitCount;int lineByte=(bmpWidth*biBitCount/8+3)/4*4;if (biBitCount==8){pColorTable=new RGBQUAD[256];fread(pColorTable,sizeof(RGBQUAD),256,fp);}pBmpBuf=new unsigned char[lineByte*bmpHeight];fread(pBmpBuf,1,lineByte*bmpHeight,fp);//开空间B=NULL;B=(BYTE**)malloc(sizeof(BYTE*)*bmpHeight);for(i=0; i<bmpHeight; i++)B[i] = (BYTE*)malloc(sizeof(BYTE)*bmpWidth);if(B==NULL){printf("fail to malloc B\n");exit(0);}G=NULL;G=(BYTE**)malloc(sizeof(BYTE*)*bmpHeight);for(i=0; i<bmpHeight; i++)G[i] = (BYTE*)malloc(sizeof(BYTE)*bmpWidth);if(G==NULL){printf("fail to malloc G\n");exit(0);}R=NULL;R=(BYTE**)malloc(sizeof(BYTE*)*bmpHeight);for(i=0; i<bmpHeight; i++)R[i] = (BYTE*)malloc(sizeof(BYTE)*bmpWidth);if(R==NULL){printf("fail to malloc R\n");exit(0);}//读图像的RGBif (biBitCount==8){for(i=0;i<bmpHeight/50;i++){for(j=0;j<bmpWidth/50;j++){//printf("(B=%d,G=%d,R=%d)\n",*(pBmpBuf+i*lineByte+j),*(pBmpBuf+i*lineByte +j),*(pBmpBuf+i*lineByte+j));B[i][j]=*(pBmpBuf+i*lineByte+j);G[i][j]=*(pBmpBuf+i*lineByte+j);R[i][j]=*(pBmpBuf+i*lineByte+j);printf("(B=%d,G=%d,R=%d)\n",B[i][j],G[i][j],R[i][j]);}}}else if (biBitCount==24){for(i=0;i<bmpHeight/100;i++){for(j=0;j<bmpWidth/100;j++){//printf("(B=%d,G=%d,R=%d)\n",*(pBmpBuf+i*lineByte+j*3+0),*(pBmpBuf+i*line Byte+j*3+1),*(pBmpBuf+i*lineByte+j*3+2));B[i][j]=*(pBmpBuf+i*lineByte+j*3+0);G[i][j]=*(pBmpBuf+i*lineByte+j*3+1);R[i][j]=*(pBmpBuf+i*lineByte+j*3+2);printf("(B=%d,G=%d,R=%d)\n",B[i][j],G[i][j],R[i][j]);}}}fclose(fp);//释放空间for(i=0; i<bmpHeight; ++i)free(B[i]);free(B);B=NULL;for(i=0; i<bmpHeight; ++i)free(G[i]);free(G);G=NULL;for(i=0; i<bmpHeight; ++i)free(R[i]);free(R);R=NULL;return 1;}bool writeBmp(char *bmpName, int ImageWidth,int ImageHeight){unsigned char *imgBuf=pBmpBuf2;if(!imgBuf)return 0;int colorTablesize=0;if(biBitCount==8)colorTablesize=1024;int lineByte=(ImageWidth*biBitCount/8+3)/4*4;FILE *fp=fopen(bmpName,"wb");if (fp==0) return 0;BITMAPFILEHEADER fileHead;fileHead.bfType=0x4D42;fileHead.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTab lesize+lineByte*ImageHeight;fileHead.bfReserved1=0;fileHead.bfReserved2=0;fileHead.bfOffBits=54+colorTablesize;fwrite(&fileHead,sizeof(BITMAPFILEHEADER),1,fp);BITMAPINFOHEADER head;head.biBitCount=biBitCount;head.biClrImportant=0;head.biClrUsed=0;head.biCompression=0;head.biHeight=ImageHeight;head.biPlanes=1;head.biSizeImage=lineByte*ImageHeight;head.biWidth=ImageWidth;head.biXPelsPerMeter=0;head.biYPelsPerMeter=0;fwrite(&head,sizeof(BITMAPINFOHEADER),1,fp);if (biBitCount==8)fwrite(pColorTable,sizeof(RGBQUAD),256,fp);fwrite(imgBuf,ImageHeight*lineByte,1,fp);fclose(fp);return 1;}bool writeBmp2(char *bmpName, int ImageWidth,int ImageHeight){unsigned char *imgBuf=pBmpBuf3;if(!imgBuf)return 0;int colorTablesize=0;if(biBitCount==8)colorTablesize=1024;int lineByte=(ImageWidth*biBitCount/8+3)/4*4;FILE *fp=fopen(bmpName,"wb");if (fp==0) return 0;BITMAPFILEHEADER fileHead;fileHead.bfType=0x4D42;fileHead.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTab lesize+lineByte*ImageHeight;fileHead.bfReserved1=0;fileHead.bfReserved2=0;fileHead.bfOffBits=54+colorTablesize;fwrite(&fileHead,sizeof(BITMAPFILEHEADER),1,fp);BITMAPINFOHEADER head;head.biBitCount=biBitCount;head.biClrImportant=0;head.biClrUsed=0;head.biCompression=0;head.biHeight=ImageHeight;head.biPlanes=1;head.biSize=40;head.biSizeImage=lineByte*ImageHeight;head.biWidth=ImageWidth;head.biXPelsPerMeter=0;head.biYPelsPerMeter=0;fwrite(&head,sizeof(BITMAPINFOHEADER),1,fp);if (biBitCount==8)fwrite(imgBuf,ImageHeight*lineByte,1,fp);fclose(fp);return 1;}void Med(){int i,j,x,y;BYTE p[5],s;int lineByte=(bmpWidth+3)/4*4;pBmpBuf2= new unsigned char[lineByte*bmpHeight];memcpy(pBmpBuf2,pBmpBuf,lineByte*bmpHeight);for(i=1;i<bmpHeight-2;i++){for(j=3;j<bmpWidth*3-3;j=j+3){p[0]=*(pBmpBuf+(i-1)*lineByte+j);p[1]=*(pBmpBuf+i*lineByte+j-3);p[2]=*(pBmpBuf+i*lineByte+j);p[3]=*(pBmpBuf+i*lineByte+j+3);p[4]=*(pBmpBuf+(i+1)*lineByte+j);for(x=0;x<3;x++){for(y=x+1;y<5;y++){if (p[y]>p[x]){s=p[y];p[y]=p[x];p[x]=s;}}}*(pBmpBuf2+i*lineByte+j)=p[2];}}//左下角为黑色/* int i,j;int lineByte=(bmpWidth*biBitCount/8+3)/4*4;for(i=0;i<bmpHeight/2;i++){for(j=0;j<bmpWidth/2;j++){*(pBmpBuf+i*lineByte+j)=0;}// int x,y;// BYTE p[9],s;// BYTE *lpTemp=new BYTE[bmpWidth*bmpHeight]; 中值滤波// int i,j;/* for(y=1;y<bmpHeight-1;y++){for(x=3;x<bmpWidth*3-3;x++){p[0]=lpBits[x-3+(y-1)*bmpWidth];p[1]=lpBits[x+(y-1)*bmpWidth];p[2]=lpBits[x+3+(y-1)*bmpWidth];p[3]=lpBits[x-3+y*bmpWidth];p[4]=lpBits[x+y*bmpWidth];p[5]=lpBits[x+3+y*bmpWidth];p[6]=lpBits[x-3+(y+1)*bmpWidth];p[7]=lpBits[x+(y+1)*bmpWidth];p[8]=lpBits[x+3+(y+1)*bmpWidth];for(j=0;j<5;j++){for(i=j+1;i<9;i++){if (p[j]>p[i]){s=p[j];p[j]=p[i];p[i]=s;}}}lpTemp[x+y*bmpWidth]=p[4];}}lpBits=lpTemp;*/}void Med2(){int i,j,x,y;BYTE p[9],s;int lineByte=(bmpWidth+3)/4*4;pBmpBuf3= new unsigned char[lineByte*bmpHeight];memcpy(pBmpBuf3,pBmpBuf,lineByte*bmpHeight);for(i=2;i<bmpHeight-2;i++){for(j=6;j<bmpWidth*3-6;j=j+3)p[0]=*(pBmpBuf+(i-2)*lineByte+j);p[1]=*(pBmpBuf+(i-1)*lineByte+j);p[2]=*(pBmpBuf+i*lineByte+j-6);p[3]=*(pBmpBuf+i*lineByte+j-3);p[4]=*(pBmpBuf+i*lineByte+j);p[5]=*(pBmpBuf+i*lineByte+j+3);p[6]=*(pBmpBuf+i*lineByte+j+6);p[7]=*(pBmpBuf+(i+1)*lineByte+j);p[8]=*(pBmpBuf+(i+2)*lineByte+j);for(x=0;x<5;x++){for(y=x+1;y<9;y++){if (p[y]>p[x]){s=p[y];p[y]=p[x];p[x]=s;}}}*(pBmpBuf3+i*lineByte+j)=p[4];}}}void main(){char readPath[]="输入图像.bmp";readBmp(readPath,bmpWidth,bmpHeight);printf("width=%d,height=%d,biBitCount=%d\n",bmpWidth,bmpHeight,biBitCount) ;Med();Med2();char writePath[]="输出图像1.bmp";writeBmp(writePath,bmpWidth,bmpHeight);char writePath2[]="输出图像2.bmp";writeBmp2(writePath2,bmpWidth,bmpHeight);delete []pBmpBuf;delete []pBmpBuf2;delete []pBmpBuf3;if(biBitCount==8)delete[] pColorTable;}六、实验效果及分析1、基础训练部分输入图像输出图像5次中值滤波后输出图像原图像根据实验结果可以看出,中值滤波法能将图片中的椒盐噪声很好地滤除掉,但与原图像清晰度为代价消除图像中的椒盐噪声。

相关主题