图形学-降噪技术-2维中值滤波

导读:
  在图像采集过程中,由于电子设备的不稳定性(比如毛刺电压,电磁干扰等)会对获取的图像产生一些影响,这种影响叫噪声,降噪技术就是图像处理中消除这种噪声影响的技术。二维中值滤波就是其中一种方法。
  中值滤波是一种局部图像平滑技术,属于非线性滤波,他可以是1维的也可以是2维的,因为图像是2维象素矩阵,所以这里使用2维中值滤波。
  2维中值滤波算法是:
  对于一幅图像的象素矩阵,取以目标象素为中心的一个子矩阵窗口,这个窗口可以是3*3 ,5*5 等根据需要选取,对窗口内的象素灰度排序,取中间一个值作为目标象素的新灰度值。
  窗口示例如
  ooo
  oxo
  ooo
  上面x为目标象素,和周围o组成3*3矩阵Array,然后对这9个元素的灰度进行排序,以排序后的中间元素Array[4]为x的新灰度值,如此就完成对象素x的中值滤波,再迭代对其他需要的象素进行滤波即可。
  下面根据这个理论用BCB6实现中值滤波算法
  //--------------------------------BCB6程序
  #include
  #pragma hdrstop
  #include
  #include "Unit1.h"
  #include"File1.h"
  #pragma pack(1)
  /*
  程序:图形学-中值滤波
  作者:sboom(Lingch)
  日期:12月26日
  */
  //BMP文件头
  struct BITMAPFILEHEADER_
  {
  short type;
  int bfSize;
  short re1,re2;
  int Offbits;
  };
  //BMP信息头
  struct BITMAPINFO_
  {
  long size;
  long width,height;
  short planes,bitCount;
  long comp,sizeImg;
  long xpels,ypels;
  long used,important;
  };
  //BMP彩色表项
  struct COLOR_
  {
  char blue,green,red;
  };
  //------将BMP彩色表的数据校正到BCB TColor的数据。
  TColor* SwitchColor(unsigned char r,unsigned char g,unsigned char b)
  {
  TColor *re=new TColor;
  *re=(r | g<<8 | b<<16 );
  *re=*re &0x00ffffff;
  return re;
  }
  void xxx()
  {
  FILE *f=fopen("f://7.bmp","rb");
  if(f==NULL) /*判断文件是否打开成功*/
  {
  ShowMessage("File open error");
  return;
  }
  fseek(f,0,0);//移动到开头
  //----------读BMP文件头
  BITMAPFILEHEADER_ *bmph=new BITMAPFILEHEADER_();
  if(fread((char*)bmph,sizeof(BITMAPFILEHEADER_),1,f)==NULL)
  {
  ShowMessage("File read error");
  return;
  }
  //-----------读BMP信息头
  BITMAPINFO_ *bmpi=new BITMAPINFO_();
  if(fread((char*)bmpi,sizeof(BITMAPINFO_),1,f)==NULL)
  {
  ShowMessage("File read error2");
  return;
  }
  fseek(f,bmph->Offbits,0);
  //----------显示一些信息
  Form1->Edit1->Text=IntToStr(bmph->bfSize);
  Form1->Edit2->Text=IntToStr(bmpi->width);
  Form1->Edit3->Text=IntToStr(bmpi->height);
  Form1->Edit4->Text=IntToStr(bmpi->comp);
  Form1->Edit5->Text=IntToStr(bmpi->used);
  int i,j,k,l,wc,pos;
  long N=bmph->bfSize- bmph->Offbits;//象素总数
  COLOR_ *image=new COLOR_[N]; //位图矩阵
  COLOR_ *newimage=new COLOR_[N];//滤波后的位图矩阵
  fread(image,N*3,1,f);//读入位图矩阵
  //---------先COPY不处理的原图像第一行,因为第一行无法取窗口
  memcpy((void*)newimage,(void*)image,(bmpi->width+1)*3);
  //--!!!!!!!!!!!!!!下面开始窗口为3×3中值滤波!!!!!!!!!!!!!!!!
  int ns=bmpi->width+1; //开始处理的起点
  int ne=N-bmpi->width-2; //开始处理的终点
  unsigned char *psr=new unsigned char[9]; //红色窗口
  unsigned char *psg=new unsigned char[9]; //绿色窗口
  unsigned char *psb=new unsigned char[9]; //蓝色窗口
  unsigned char temp;
  COLOR_ cc;
  for(i=ns;i<=ne;i++)
  {
  //---------红色窗口
  //---3*3窗口矩阵第一行
  psr[0]=image[i-bmpi->width+1].red ;
  psr[1]=image[i-bmpi->width+1].red;
  psr[2]=image[i-bmpi->width+1].red;
  //---3*3窗口矩阵第二行
  psr[3]=image[i-1].red;
  psr[4]=image[i].red;
  psr[5]=image[i+1].red;
  //---3*3窗口矩阵第三行
  psr[6]=image[i+bmpi->width-1].red;
  psr[7]=image[i+bmpi->width].red;
  psr[8]=image[i+bmpi->width+1].red;
  //---------绿色窗口
  //---3*3窗口矩阵第一行
  psg[0]=image[i-bmpi->width+1].green ;
  psg[1]=image[i-bmpi->width+1].green;
  psg[2]=image[i-bmpi->width+1].green;
  //---3*3窗口矩阵第二行
  psg[3]=image[i-1].green;
  psg[4]=image[i].green;
  psg[5]=image[i+1].green;
  //---3*3窗口矩阵第三行
  psg[6]=image[i+bmpi->width-1].green;
  psg[7]=image[i+bmpi->width].green;
  psg[8]=image[i+bmpi->width+1].green;
  //---------蓝色窗口
  //---3*3窗口矩阵第一行
  psb[0]=image[i-bmpi->width+1].blue ;
  psb[1]=image[i-bmpi->width+1].blue;
  psb[2]=image[i-bmpi->width+1].blue;
  //---3*3窗口矩阵第二行
  psb[3]=image[i-1].blue;
  psb[4]=image[i].blue;
  psb[5]=image[i+1].blue;
  //---3*3窗口矩阵第三行
  psb[6]=image[i+bmpi->width-1].blue;
  psb[7]=image[i+bmpi->width].blue;
  psb[8]=image[i+bmpi->width+1].blue;
  //--------选择排序
  for(j=0;j<9;j++)
  {
  //-----------红色排序
  pos=j;
  for(k=j;k<9;k++)
  {
  if(psr[k]
  pos=k;
  }
  temp=psr[j];
  psr[j]=psr[pos];
  psr[pos]=temp;
  //--------------绿色排序
  pos=j;
  for(k=j;k<9;k++)
  {
  if(psg[k]
  pos=k;
  }
  temp=psg[j];
  psg[j]=psg[pos];
  psg[pos]=temp;
  //--------------蓝色排序
  pos=j;
  for(k=j;k<9;k++)
  {
  if(psb[k]
  pos=k;
  }
  temp=psb[j];
  psb[j]=psb[pos];
  psb[pos]=temp;
  }
  //------取中值
  newimage[i].red=psr[4];
  newimage[i].green=psg[4];
  newimage[i].blue=psb[4];
  }
  //!!!!!!!!!!!滤波完毕,COPY无法滤波的最后一行,因为最后一行无法取窗口!!!!!!!
  memcpy((void*)&image[ne+1],(void*)&image[ne+1],(bmpi->width+1)*3);
  //------显示图形
  COLOR_ color;
  TColor *tc;
  if(bmpi->width%4==0)//-----------因为BMP图像4字节对齐
  wc=bmpi->width/4*4;
  else
  wc=(bmpi->width/4+1)*4;
  pos=0;
  for( i=0;i height;i++)
  {
  for(j=0;j
  {
  //-----原始图形
  color=image[pos];
  tc=SwitchColor(color.red,color.green,color.blue);
  Form1->Canvas->Pixels[10+j][600-i]=*tc;
  //------新图形
  color=newimage[pos];
  tc=SwitchColor(color.red,color.green,color.blue);
  Form1->Canvas->Pixels[400+j][600-i]=*tc;
  pos++;
  }
  }
  fclose(f);
  }
  //-------------------------------------------------------------------------
  经过实际运行证实,中值滤波能有效去除图像中的噪声点,特别是在一片连续变化缓和的区域中(比如人的衣服,皮肤),几乎100%去除灰度突变点(可以认为是噪声点),也因为如此,中值滤波不适合用在一些细节多,如细节点,细节线多的图像中,因为细节点有可能被当成噪声点去除。
  中值滤波的窗口还可以有多种形状,上面程序选择的是矩形(容易计算),其实窗口还可以是菱形,圆形,十字形等等,不同的窗口形状有不同的滤波效果,对有缓慢且有较长轮廓线的物体适合用矩形或者原型窗口,对于有尖顶角物体的图像适合采用十字形窗口。
  中值滤波可以进行线性组合,不同窗口形状的滤波器可以线性组合
  g(x,y)=E{k=1,n}ak*medk(f(x,y)) 编辑关系,左式E{k=1,n}表示下标k从1到n连加符号,ak是各滤波器权值系数,med是滤波器函数。其实就是象素灰度通过所有滤波器再相加,各滤波器权值ak的和应该=1。
  中值滤波同时伴随着模糊化效果。

本文转自
http://3pcode.com/code/2006/09/80704.htm
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值