您的位置:首页 > 其它

双边滤波

2015-05-19 22:15 696 查看
双边滤波是一种可以保边去噪的滤波器。之所以可以达到这样的效果,是因为该滤波器是由两个函数构成,一个函数是由几何空间距离决定滤波器系数,另外一个由像素差决定滤波器系数。

在前面几种讲述的滤波方法中,像素点的灰度值均是由该点邻域内其他点的灰度值决定的,比如高斯滤波和均值滤波都可看作是加权平均,中值滤波取的是邻域灰度中值。双边滤波则不但考虑邻域范围内点的灰度值,同样考虑这些点距离中心点的几何距离,这样可以得到滤波后的点的灰度值表达公式为:



其中k为归一化系数,其表达式为:



h和x分别为滤波后和滤波前对应点的灰度值;

c表示中心点与其邻域内点的空间相似度;

s表示中心点与其邻域内点的灰度相似度。

在实现过程中,c和s函数均可用高斯函数实现,即其定义如下:



可根据以上原理实现双边滤波如下。

Void BilateralFilter(CvMat *pGrayMat, CvMat *pFilterMat, int nWidth, int nHeight, double dSigma1, double dSigma2, int nWindows)

{

////////////////////////参数说明///////////////////////////////////

//pGrayMat:待处理图像数组

//pFilterMat:保存高斯滤波结果

//nWidth:图像宽度

//nHeight:图像高度

//dSigma1、dSigma2:分别为几何与灰度相关高斯函数的方差

double* dDistance = new double[nWindows*nWindows]; //计算距离中间点的几何距离

double* dGrayDiff = new double[nWindows*nWindows]; //定义中心点到当前点的灰度差

for(int i=0; i<nWindows*nWindows; i++)

{

int nNumX = i/nWindows;

int nNumY = i%nWindows;

dDistance[i] = ((nWindows-1)/2-nNumX)*((nWindows-1)/2-nNumX)+((nWindows-1)/2-nNumY)*((nWindows-1)/2-nNumY);

dDistance[i] = exp(-0.5*dDistance[i]/dSigma1/dSigma1); //C参数

}

//以下求解灰度值的差

for(i=0; i<nHeight; i++)

{

for(int j=0; j<nWidth; j++)

{

double dGray = cvmGet(pGrayMat, i, j); //当前点的灰度值

double dData = 0.0;

double dTotal = 0.0; //用于进行归一化

for(int m=0; m<nWindows*nWindows; m++)

{

int nNumX = m/nWindows; //行索引

int nNumY = m%nWindows; //列索引

int nX = i-(nWindows-1)/2+nNumX;

int nY = j-(nWindows-1)/2+nNumY;

if( (nY>=0) && (nY<nWidth) && (nX>=0) && (nX<nHeight))

{

double dGray1 = cvmGet(pGrayMat, nX, nY);

dGrayDiff[m] = fabs(dGray-dGray1);

dGrayDiff[m] = exp(-0.5*dGrayDiff[m]*dGrayDiff[m]/dSigma2/dSigma2); //S参数

if(m!=4)

{

dData += dGray1 * dGrayDiff[m] * dDistance[m]; //C和S参数综合

dTotal += dGrayDiff[m]*dDistance[m]; //加权系数求和,进行归一化

}

}

}

dData /=dTotal;

cvmSet(pFilterMat, i, j, dData);

}

}

delete[]dDistance;

delete[]dGrayDiff;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: