一、原理
cvSmooth(m_iplImg, dstImg, CV_BILATERAL, 2 * r + 1, 0, sigma_r, sigma_d);
void CImageObj::Bilateral_Filter(int r, double sigma_d, double sigma_r)
{
int i, j, m, n, k;
int nx = m_width, ny = m_height;
int w_filter = 2 * r + 1; // 濾波器邊長
double gaussian_d_coeff = -0.5 / (sigma_d * sigma_d);
double gaussian_r_coeff = -0.5 / (sigma_r * sigma_r);
double** d_metrix = NewDoubleMatrix(w_filter, w_filter); // spatial weight
double r_metrix[256]; // similarity weight
// copy the original image
double* img_tmp = new double[m_nChannels * nx * ny];
for (i = 0; i < ny; i++)
for (j = 0; j < nx; j++)
for (k = 0; k < m_nChannels; k++)
{
img_tmp[i * m_nChannels * nx + m_nChannels * j + k] = m_imgData[i * m_nChannels * nx + m_nChannels * j + k];
}
// compute spatial weight
for (i = -r; i <= r; i++)
for (j = -r; j <= r; j++)
{
int x = j + r;
int y = i + r;
d_metrix[y][x] = exp((i * i + j * j) * gaussian_d_coeff);
}
// compute similarity weight
for (i = 0; i < 256; i++)
{
r_metrix[i] = exp(i * i * gaussian_r_coeff);
}
// bilateral filter
for (i = 0; i < ny; i++)
for (j = 0; j < nx; j++)
{
for (k = 0; k < m_nChannels; k++)
{
double weight_sum, pixcel_sum;
weight_sum = pixcel_sum = 0.0;
for (m = -r; m <= r; m++)
for (n = -r; n <= r; n++)
{
if (m*m + n*n > r*r) continue;
int x_tmp = j + n;
int y_tmp = i + m;
x_tmp = x_tmp < 0 ? 0 : x_tmp;
x_tmp = x_tmp > nx - 1 ? nx - 1 : x_tmp; // 邊界處理,replicate
y_tmp = y_tmp < 0 ? 0 : y_tmp;
y_tmp = y_tmp > ny - 1 ? ny - 1 : y_tmp;
int pixcel_dif = (int)abs(img_tmp[y_tmp * m_nChannels * nx + m_nChannels * x_tmp + k] - img_tmp[i * m_nChannels * nx + m_nChannels * j + k]);
double weight_tmp = d_metrix[m + r][n + r] * r_metrix[pixcel_dif]; // 複合權重
pixcel_sum += img_tmp[y_tmp * m_nChannels * nx + m_nChannels * x_tmp + k] * weight_tmp;
weight_sum += weight_tmp;
}
pixcel_sum = pixcel_sum / weight_sum;
m_imgData[i * m_nChannels * nx + m_nChannels * j + k] = (uchar)pixcel_sum;
} // 一個通道
} // END ALL LOOP
UpdateImage();
DeleteDoubleMatrix(d_metrix, w_filter, w_filter);
delete[] img_tmp;
}