1.什么是中值滤波?
中值滤波法是一种非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值。理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声点。方法是用某种结构的二维滑动模板,将板内像素按照像素值的大小进行排序,生成单调上升(或下降)的为二维数据序列。但在条纹中心分析方法中作用不大。
2.中值滤波的应用
中值滤波法对消除椒盐噪声非常有效,在光学测量条纹图象的相位分析处理方法中有特殊作用,但在条纹中心分析方法中作用不大.
中值滤波在图像处理中,常用于保护边缘信息,是经典的平滑噪声的方法。
3.基于opencv的中值滤波代码实现
//中值滤波的实现
#include "highgui.h"
#include "cv.h"
//函数声明
void RGB_Gray_Typical(IplImage *tempFrame, IplImage *grayImage);
void MedianFliter(IplImage *grayImage,IplImage *FliterImage);
unsigned char GetMedianNum(IplImage *grayImage, int FilterLen);
int main()
{
//确定要读入的AVI视频
CvCapture *capture = cvCreateFileCapture("E:\\新建文件夹\\行车视频.avi");
//将视频文件的下一帧加载到内存
IplImage *tempFrame= cvQueryFrame(capture);
IplImage *grayImage,*FliterImage;
//创建头并分配数据,取与这一帧图大小一样的尺寸,数据类型为无符号8位整型,单通道
grayImage = cvCreateImage(cvSize(tempFrame->width, tempFrame->height),8,1);
FliterImage=cvCreateImage(cvSize(tempFrame->width,tempFrame->height),8,1);
while (IplImage *tempFrame = cvQueryFrame(capture))
{
cvShowImage("原始视频",tempFrame); //播放原视频
RGB_Gray_Typical(tempFrame, grayImage);//得到灰度图
cvShowImage("灰度视频",grayImage);
MedianFliter(grayImage,FliterImage);
//cvShowImage("中值滤波视频",FliterImage);
char c = cvWaitKey(33);
if (c == 27)
{
return 0;
}
cvWaitKey(10);
}
cvReleaseCapture(&capture);
cvReleaseImage(&grayImage);
cvReleaseImage(&FliterImage);
cvDestroyWindow("原始视频");
cvDestroyWindow("灰度视频");
cvDestroyWindow("中值滤波视频");
}
void RGB_Gray_Typical(IplImage *tempFrame, IplImage *grayImage)
{
for(int j=0; j<tempFrame->height; j++)
for(int i=0; i<tempFrame->width; i++)
{
//int liv_size = j * img->width + i;//测试循环多少次
uchar *data=( uchar *)(tempFrame->imageData );
int step=tempFrame->widthStep;
//得到某个像素点bgr三个通道的像素值
double B = (double)data[j*step + i*3+0]; //B分量
double G= (double)data[j*step + i*3 + 1]; //G分量
double R = (double)data[j*step + i*3 + 2]; //R分量
//用灰度公式,计算出这个像素点转换后的灰度值GRAY
double GRAY = (double)(0.299 * R+ 0.587 * G + 0.114 * B+0.5);
//把GRAY的值赋给它对应的内存单元
long int index= j*tempFrame->width + i;
grayImage->imageData[index] = GRAY;
//cout<<"liv_size = "<<liv_size<<endl;
}
}
void MedianFliter(IplImage *grayImage,IplImage *FliterImage)
{
uchar *data0=(uchar*)(grayImage->imageData );
unsigned char bArray[10];//如果是9的话,就会出现堆栈溢出的警告,设计时,把空间设大一点
unsigned char *m_lpBufmed;
m_lpBufmed=new unsigned char[grayImage->height * grayImage->width];
for(int j1=1; j1<grayImage->height-1; j1++)
{
for(int i1=1; i1<grayImage->width-1; i1++)
{
bArray[0]=data0[(j1-1)*grayImage->width + i1-1];
bArray[1]=data0[(j1-1)*grayImage->width + i1];
bArray[2]=data0[(j1-1)*grayImage->width + i1+1];
bArray[3]=data0[j1*grayImage->width + i1-1];
bArray[4]=data0[j1*grayImage->width + i1];
bArray[5]=data0[j1*grayImage->width + i1+1];
bArray[6]=data0[(j1+1)*grayImage->width + i1-1];
bArray[7]=data0[(j1+1)*grayImage->width + i1];
bArray[8]=data0[(j1+1)*grayImage->width + i1+1];
// 用冒泡法对数组进行排序
for(int j=1;j<=8;j++)
{
for(int i=2;i1<=9-i;i++)
{
if (bArray[i] > bArray[i+1])
{
// 互换
unsigned char bTemp = bArray[i];
bArray[i] = bArray[i+1];
bArray[i+1] =bTemp;
}
}
}
//排序后,中间那个数,中值也就是bArray[4],把这个值赋给m_lpBufmed中的相应的点
m_lpBufmed[j1*grayImage->width + i1] = bArray[4];
}
}
FliterImage->imageData = (char *)m_lpBufmed;
cvShowImage("中值滤波视频",FliterImage);
delete m_lpBufmed;
}