引導濾波(guided image filtering)原理及C++實現

引導濾波

引導濾波是由何凱明等人與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.



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章