中值滤波器设计及椒盐噪声滤除文档格式.docx
《中值滤波器设计及椒盐噪声滤除文档格式.docx》由会员分享,可在线阅读,更多相关《中值滤波器设计及椒盐噪声滤除文档格式.docx(35页珍藏版)》请在冰点文库上搜索。
如果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<
windows.h>
stdio.h>
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;
i<
bmpHeight;
i++)
B[i]=(BYTE*)malloc(sizeof(BYTE)*bmpWidth);
if(B==NULL)
printf("
failtomallocB\n"
exit(0);
G=NULL;
G=(BYTE**)malloc(sizeof(BYTE*)*bmpHeight);
G[i]=(BYTE*)malloc(sizeof(BYTE)*bmpWidth);
if(G==NULL)
failtomallocG\n"
R=NULL;
R=(BYTE**)malloc(sizeof(BYTE*)*bmpHeight);
R[i]=(BYTE*)malloc(sizeof(BYTE)*bmpWidth);
if(R==NULL)
failtomallocR\n"
//读图像的RGB
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]);
}
}
elseif(biBitCount==24)
bmpHeight/100;
bmpWidth/100;
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);
fclose(fp);
//释放空间
++i)
free(B[i]);
free(B);
free(G[i]);
free(G);
free(R[i]);
free(R);
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;
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);
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(pColorTable,sizeof(RGBQUAD),256,fp);
fwrite(imgBuf,ImageHeight*lineByte,1,fp);
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;
bmpHeight-2;
i++)//边缘不进行处理
{for(j=3;
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];
//取中值
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;
delete[]pColorTable;
(2)扩展训练部分
//读入图像数据的指针2
unsignedchar*pBmpBuf3=NULL;
//读入图像数据的指针3
//printf("
*(pBmpBuf+i*lineByte+j),*(pBmpBuf+i*lineByte+j),*(pBmpBuf+i*lineByte+j));
*(pBmpBuf+i*lineByte+j*3+0),*(pBmpBuf+i*lineByte+j*3+1),*(pBmpBuf+i*lineByte+j*3+2));
head.biHeight=Ima