今天用C++实现了中值滤波,opencv中用的cvSmooth,平滑方法选CV_MEDIAN即为中值滤波,下面是自己用代码实现的中值滤波。
中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波的基本原理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的
像素值接近的真实值,从而消除孤立的噪声点。方法是用某种结构的二维滑动模板,将板内
像素按照像素值的大小进行排序,生成单调上升(或下降)的为二维数据序列。二维
中值滤波输出为g(x,y)=med{f(x-k,y-l),(k,l∈W)} ,其中,f(x,y),g(x,y)分别为原始图像和处理后图像。W为二维模板,通常为3*3,5*5区域,也可以是不同的的形状,如线状,圆形,十字形,圆环形等。
区域越大滤波效果越好,本人在此选用的是5X5的掩模,代码如下。
inline unsigned char GetMedianValue(int * bArray, int iFilterLen)
{
int i,j;
unsigned char tempV;
// 用冒泡法对数组进行排序
for (j = 0; j < iFilterLen - 1; j ++)
{
for (i = 0; i < iFilterLen - j - 1; i ++)
{
if (bArray[i] > bArray[i + 1])
{
// 互换
tempV = bArray[i];
bArray[i] = bArray[i + 1];
bArray[i + 1] = tempV;
}
}
}
// 计算中值
if ((iFilterLen & 1) > 0)
{
// 数组有奇数个元素,返回中间一个元素
tempV = bArray[(iFilterLen + 1) / 2];
}
else
{
// 数组有偶数个元素,返回中间两个元素平均值
tempV = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2;
}
return tempV;
};
{
int i,j;
unsigned char tempV;
// 用冒泡法对数组进行排序
for (j = 0; j < iFilterLen - 1; j ++)
{
for (i = 0; i < iFilterLen - j - 1; i ++)
{
if (bArray[i] > bArray[i + 1])
{
// 互换
tempV = bArray[i];
bArray[i] = bArray[i + 1];
bArray[i + 1] = tempV;
}
}
}
// 计算中值
if ((iFilterLen & 1) > 0)
{
// 数组有奇数个元素,返回中间一个元素
tempV = bArray[(iFilterLen + 1) / 2];
}
else
{
// 数组有偶数个元素,返回中间两个元素平均值
tempV = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2;
}
return tempV;
};
int picProcessBasics::IMGMedianFilter(IplImage* pImg,IplImage* pDestImg,int maskSize)
{
int FilterW=0;
int FilterH=0;
int FilterCenterX=0;
int FilterCenterY=0;
int aValue[64]={0};//滤波掩模
{
int FilterW=0;
int FilterH=0;
int FilterCenterX=0;
int FilterCenterY=0;
int aValue[64]={0};//滤波掩模
FilterW=maskSize;
FilterH=maskSize;
FilterCenterX=maskSize/2;
FilterCenterY=maskSize/2;
cvCopy(pImg,pDestImg,0);
for(int i = FilterCenterY; i < pImg->height-FilterH+FilterCenterY+1; i++){
for(int j = FilterCenterX; j < pImg->width-FilterW+FilterCenterX+1; j++){
// 读取滤波器数组
for (int k = 0; k < FilterH; k++)
{
for (int l = 0; l < FilterW; l++)
{
// 指向DIB第i - iFilterMY + k行,第j - iFilterMX + l个象素的指针
aValue[k * FilterW + l] = pImg->imageData[pImg->widthStep * (i - FilterCenterY + k) + (j - FilterCenterX + l) ];
}
}
for(int j = FilterCenterX; j < pImg->width-FilterW+FilterCenterX+1; j++){
// 读取滤波器数组
for (int k = 0; k < FilterH; k++)
{
for (int l = 0; l < FilterW; l++)
{
// 指向DIB第i - iFilterMY + k行,第j - iFilterMX + l个象素的指针
aValue[k * FilterW + l] = pImg->imageData[pImg->widthStep * (i - FilterCenterY + k) + (j - FilterCenterX + l) ];
}
}
pDestImg->imageData[pDestImg->widthStep * i + j ]= GetMedianValue(aValue, FilterH * FilterW) ;
}
}
}
}
return 0;
}
}
处理前图像:
处理后图像: