中值滤波器设计及椒盐噪声滤除.docx
《中值滤波器设计及椒盐噪声滤除.docx》由会员分享,可在线阅读,更多相关《中值滤波器设计及椒盐噪声滤除.docx(24页珍藏版)》请在冰豆网上搜索。
中值滤波器设计及椒盐噪声滤除
题目四:
中值滤波器设计及椒盐噪声滤除
一、实验背景
在数字图像的生成与采集过程中,由于受工作环境,器件等性能的影响,使得一幅未经处理的原始图像,都存在着一定的噪声干扰。
这种噪声具有以下性质:
1、图像上的噪声出现处呈现不规则分布;
2、噪声的大小也是不规则的。
这些噪声恶化了图像质量,使图像模糊甚至淹没目标特征,给后续的处理分析带来了困难。
因此需要对图像应该进行滤除噪声处理。
二、实验目的
1.通过利用c程序实现数字信号处理的相关功能,巩固对信号处理原理知识的理解,培养快速解决实际问题的能力提高实际编程和处理数据的综合能力,初步培养在解决信号处理实际应用问题中所应具备的基本素质和要求。
2.培养独立思考的能力与研发能力,通过设计实现不同的信号处理问题,初步掌握在给定条件和功能的情况下,实现合理设计算法结构的能力。
3.提高资料查询和整理的能力。
能够在短时间内找到适合自己的方法。
并在文献整理的过程中学会科技文献的写作,提高语言表达能力。
三、实验内容
1.理解什么是椒盐噪声,中值滤波的原理及其特性。
2.设计一种中值滤波,对椒噪声滤波有效,并分析滤波器的适用范围。
3、(扩展训练)对设计的滤波器针对椒、盐噪声滤除分别进行测试,并进行性能比较分析,并讨论椒、盐噪声频度(噪声数目占图像实际像素的百分比)对滤波器实际效果的影响。
四、实验原理
1.椒盐噪声
椒盐噪声又称脉冲噪声,是由图像传感器,传输信道,解码处理等产生的黑白相间的亮暗点噪声。
椒盐噪声往往由图像切割引起。
椒盐噪声的PDF是:
如果b>a,灰度值b在图像中将显示为一个亮点,a的值将显示为一个暗点。
若或为零,则脉冲噪声称为单级脉冲。
如果和均不为零,尤其是他们近似相等时,脉冲噪声值将类似于随机分布在图像上的胡椒和盐粉微粒。
形象的说,椒噪声在图像上是类似于黑胡椒颗粒的小点,而盐噪声在图像上是类似于白色盐粒的小点。
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)中值滤波特性
中值滤波是图像处理中的一个常用步骤,它对于斑点噪声和椒盐噪声来说尤其有用。
中值滤波方法以牺牲图像清晰度为代价消除图像中的椒盐噪声。
中值滤波不能保证把噪声去除,只能在有限的范围内减弱噪声对图像的影响。
同时,中值滤波不能多次使用,因为这样会使图像各个像素间趋于相同,整个图像就会变得越来越模糊。
另外,通过查阅资料发现,中值滤波器的效果不仅仅和观察窗的大小有关,还和观察窗的形状有关。
五、实验步骤
1、根据题目要求,先画出程序的流程图。
2、源程序:
(1)基础训练部分:
#include
#include
unsignedchar*pBmpBuf=NULL;//读入图像数据的指针
unsignedchar*pBmpBuf2=NULL;//读入图像数据的指针
intbmpWidth;//图像宽度
intbmpHeight;//图像高度
RGBQUAD*pColorTable;//颜色表指针
intbiBitCount;//图像类型,每像素的位数
//读程序可读取8,24位图,本实验是对8位灰度图进行操作,满足要求
boolreadBmp(char*bmpName,intImageWidth,intImageHeight)
{
inti,j;//行列数
BYTE**B;//分别对应图像的RGB,本实验中RGB相等,故意义不大
BYTE**R;
BYTE**G;
FILE*fp=fopen(bmpName,"rb");//打开文件
if(fp==0)return0;
fseek(fp,sizeof(BITMAPFILEHEADER),0);//找出头文件
BITMAPINFOHEADERhead;
fread(&head,sizeof(BITMAPINFOHEADER),1,fp);
ImageWidth=head.biWidth;//图像宽度赋值
ImageHeight=head.biHeight;//图像高度赋值
bmpWidth=ImageWidth;
bmpHeight=ImageHeight;
biBitCount=head.biBitCount;
intlineByte=(bmpWidth*biBitCount/8+3)/4*4;//一行中信息点字节
if(biBitCount==8)
{
pColorTable=newRGBQUAD[256];
fread(pColorTable,sizeof(RGBQUAD),256,fp);
}
pBmpBuf=newunsignedchar[lineByte*bmpHeight];
fread(pBmpBuf,1,lineByte*bmpHeight,fp);
//开空间
B=NULL;
B=(BYTE**)malloc(sizeof(BYTE*)*bmpHeight);
for(i=0;iB[i]=(BYTE*)malloc(sizeof(BYTE)*bmpWidth);
if(B==NULL)
{
printf("failtomallocB\n");
exit(0);
}
G=NULL;
G=(BYTE**)malloc(sizeof(BYTE*)*bmpHeight);
for(i=0;iG[i]=(BYTE*)malloc(sizeof(BYTE)*bmpWidth);
if(G==NULL)
{
printf("failtomallocG\n");
exit(0);
}
R=NULL;
R=(BYTE**)malloc(sizeof(BYTE*)*bmpHeight);
for(i=0;iR[i]=(BYTE*)malloc(sizeof(BYTE)*bmpWidth);
if(R==NULL)
{
printf("failtomallocR\n");
exit(0);
}
//读图像的RGB
if(biBitCount==8)
{
for(i=0;i{
for(j=0;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]);
}
}
}
elseif(biBitCount==24)
{
for(i=0;i{
for(j=0;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;ifree(B[i]);
free(B);
B=NULL;
for(i=0;ifree(G[i]);
free(G);
G=NULL;
for(i=0;ifree(R[i]);
free(R);
R=NULL;
return1;
}
boolwriteBmp(char*bmpName,intImageWidth,intImageHeight)
{
unsignedchar*imgBuf=pBmpBuf2;
if(!
imgBuf)
return0;
intcolorTablesize=0;
if(biBitCount==8)
colorTablesize=1024;
intlineByte=(ImageWidth*biBitCount/8+3)/4*4;
FILE*fp=fopen(bmpName,"wb");
if(fp==0)return0;
BITMAPFILEHEADERfileHead;
fileHead.bfType=0x4D42;
fileHead.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTablesize+lineByte*ImageHeight;
fileHead.bfReserved1=0;
fileHead.bfReserved2=0;
fileHead.bfOffBits=54+colorTablesize;
fwrite(&fileHead,sizeof(BITMAPFILEHEADER),1,fp);
BITMAPINFOHEADERhead;
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);
return1;
}
voidMed()
{inti,j,a,b;
BYTEp[9],s;
intlineByte=(bmpWidth+3)/4*4;//计算一行中储存信息的字节数
pBmpBuf2=newunsignedchar[lineByte*bmpHeight];
memcpy(pBmpBuf2,pBmpBuf,lineByte*bmpHeight);//将原图复制
//观察窗取3*3的矩形窗
for(i=1;i{for(j=3;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];//取中值
}
}
}
voidmain()
{
charreadPath[]="输入图像.bmp";
readBmp(readPath,bmpWidth,bmpHeight);
printf("width=%d,height=%d,biBitCount=%d\n",bmpWidth,bmpHeight,biBitCount);
Med();
charwritePath[]="输出图像.bmp";
writeBmp(writePath,bmpWidth,bmpHeight);
delete[]pBmpBuf;
delete[]pBmpBuf2;
if(biBitCount==8)
delete[]pColorTable;
}
(2)扩展训练部分
#include
#include
unsignedchar*pBmpBuf=NULL;//读入图像数据的指针
unsignedchar*pBmpBuf2=NULL;//读入图像数据的指针2
unsignedchar*pBmpBuf3=NULL;//读入图像数据的指针3
intbmpWidth;
intbmpHeight;
RGBQUAD*pColorTable;//颜色表指针
intbiBitCount;//图像类型,每像素的位数
boolreadBmp(char*bmpName,intImageWidth,intImageHeight)
{
inti,j;
BYTE**B;
BYTE**R;
BYTE**G;
FILE*fp=fopen(bmpName,"rb");
if(fp==0)return0;
fseek(fp,sizeof(BITMAPFILEHEADER),0);
BITMAPINFOHEADERhead;
fread(&head,sizeof(BITMAPINFOHEADER),1,fp);
ImageWidth=head.biWidth;
ImageHeight=head.biHeight;
bmpWidth=ImageWidth;
bmpHeight=ImageHeight;
biBitCount=head.biBitCount;
intlineByte=(bmpWidth*biBitCount/8+3)/4*4;
if(biBitCount==8)
{
pColorTable=newRGBQUAD[256];
fread(pColorTable,sizeof(RGBQUAD),256,fp);
}
pBmpBuf=newunsignedchar[lineByte*bmpHeight];
fread(pBmpBuf,1,lineByte*bmpHeight,fp);
//开空间
B=NULL;
B=(BYTE**)malloc(sizeof(BYTE*)*bmpHeight);
for(i=0;iB[i]=(BYTE*)malloc(sizeof(BYTE)*bmpWidth);
if(B==NULL)
{
printf("failtomallocB\n");
exit(0);
}
G=NULL;
G=(BYTE**)malloc(sizeof(BYTE*)*bmpHeight);
for(i=0;iG[i]=(BYTE*)malloc(sizeof(BYTE)*bmpWidth);
if(G==NULL)
{
printf("failtomallocG\n");
exit(0);
}
R=NULL;
R=(BYTE**)malloc(sizeof(BYTE*)*bmpHeight);
for(i=0;iR[i]=(BYTE*)malloc(sizeof(BYTE)*bmpWidth);
if(R==NULL)
{
printf("failtomallocR\n");
exit(0);
}
//读图像的RGB
if(biBitCount==8)
{
for(i=0;i{
for(j=0;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]);
}
}
}
elseif(biBitCount==24)
{
for(i=0;i{
for(j=0;j{
//printf("(B=%d,G=%d,R=%d)\n",*(pBmpBuf+i*lineByte+j*3+0),*(pBmpBuf+i*lineByte+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;ifree(B[i]);
free(B);
B=NULL;
for(i=0;ifree(G[i]);
free(G);
G=NULL;
for(i=0;ifree(R[i]);
free(R);
R=NULL;
return1;
}
boolwriteBmp(char*bmpName,intImageWidth,intImageHeight)
{
unsignedchar*imgBuf=pBmpBuf2;
if(!
imgBuf)
return0;
intcolorTablesize=0;
if(biBitCount==8)
colorTablesize=1024;
intlineByte=(ImageWidth*biBitCount/8+3)/4*4;
FILE*fp=fopen(bmpName,"wb");
if(fp==0)return0;
BITMAPFILEHEADERfileHead;
fileHead.bfType=0x4D42;
fileHead.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTablesize+lineByte*ImageHeight;
fileHead.bfReserved1=0;
fileHead.bfReserved2=0;
fileHead.bfOffBits=54+colorTablesize;
fwrite(&fileHead,sizeof(BITMAPFILEHEADER),1,fp);
BITMAPINFOHEADERhead;
head.biBitCount=biBitCount;
head.biClrImportant=0;
head.biClrUsed=0;
head.biCompression=0;
head.biHeight=ImageHeight