引導濾波
引導濾波是由何凱明等人與2010年提出,它本質上具有O(N)複雜度,相對於雙邊濾波有更好的邊緣保持特性,且不會出現梯度反轉現象。在不同引導圖像的引導下,可廣泛應用於降噪、去霧、高動態範圍壓縮等。
該方法基於局部線性模型:
代碼實現
0、僞代碼
1、MATLAB代碼
見參考資料【2】
2、C++實現
template<class T, class K>
void CImageObj::BoxFilter(K** src, T** dst, int r)
{
int w = 2 * r + 1;
int pixCount = w * w;
int nx = m_width;
int ny = m_height;
int i, j, m, n;
for (i = 0; i < ny; ++i)
{
for (j = 0; j < nx; ++j)
{
int k = 0;
double sum = 0.0;
for (m = i - r; m <= i + r; ++m)
{
for (n = j - r; n <= j + r; ++n)
{
if (m < 0 || m >= ny) { k++; continue; }
if (n < 0 || n >= nx) { k++; continue; }
sum += src[m][n];
}
} // 一次窗口濾波
dst[i][j] = sum / (pixCount - k);
}
}
}
void CImageObj::GIF(uchar** guidenceImg, int radius, double eps)
{
if (guidenceImg == nullptr || *guidenceImg == nullptr)
return;
int cx = m_width;
int cy = m_height;
int wndsize = 2 * radius + 1;
int pixcount = wndsize * wndsize;
double** a = NewDoubleMatrix(cx, cy);
double** b = NewDoubleMatrix(cx, cy);
double** mean_a = NewDoubleMatrix(cx, cy);
double** mean_b = NewDoubleMatrix(cx, cy);
int i, j, m, n;
for (i = 0; i < cy; ++i)
for (j = 0; j < cx; ++j)
{
int k = 0;
double sum_I = 0.0;
double sum_p = 0.0;
for (m = i - radius; m <= i + radius; ++m)
for (n = j - radius; n <= j + radius; ++n)
{
if (m < 0 || m >= cy) { k++; continue; }
if (n < 0 || n >= cx) { k++; continue; }
sum_I += guidenceImg[m][n] / 255.0;
sum_p += m_imgData[m][n] / 255.0;
}
double mean_I = sum_I / (pixcount - k);
double mean_p = sum_p / (pixcount - k);
k = 0;
double sum_Ip = 0.0;
double sum_var_I = 0.0;
for (m = i - radius; m <= i + radius; ++m)
for (n = j - radius; n <= j + radius; ++n)
{
if (m < 0 || m >= cy) { k++; continue; }
if (n < 0 || n >= cx) { k++; continue; }
sum_Ip += (m_imgData[m][n] / 255.0) * (guidenceImg[m][n] / 255.0);
sum_var_I += (guidenceImg[m][n] / 255.0 - mean_I) * (guidenceImg[m][n] / 255.0 - mean_I);
}
a[i][j] = (sum_Ip / (pixcount - k) - mean_I * mean_p) / (sum_var_I / (pixcount - k) + eps);
b[i][j] = mean_p - a[i][j] * mean_I;
}
BoxFilter(a, mean_a, radius);
BoxFilter(b, mean_b, radius);
for (i = 0; i < cy; ++i)
for (j = 0; j < cx; ++j)
{
double tmp = 255 * (mean_a[i][j] * guidenceImg[i][j] / 255.0 + mean_b[i][j]);
tmp = tmp > 255.0 ? 255.0 : tmp;
tmp = tmp < 0.0 ? 0.0 : tmp;
m_imgData[i][j] = (uchar)tmp;
}
UpdateImage();
DeleteDoubleMatrix(a, cx, cy);
DeleteDoubleMatrix(b, cx, cy);
DeleteDoubleMatrix(mean_a, cx, cy);
DeleteDoubleMatrix(mean_b, cx, cy);
}
參考資料
[1] Guided Image Filtering, by Kaiming He, Jian Sun, and Xiaoou Tang, in TPAMI 2013.