CVPR2019 Oral 论文《Side Window Filtering》C++代码实现

算法原理

可以看这篇文章:
https://zhuanlan.zhihu.com/p/58326095

简单介绍

这篇文章提出了一种新的方法用于滤波保留边缘和角点,原理在上面的文章可以找到,同时也能找到论文原文和一份github的代码,这种方法可以配合现有的任何滤波方法使用,让这些滤波方法都强制保留边缘。只需要将对应的滤波的核的系数换成对应的滤波方法的核即可。这里我实现了均值滤波的Side Window Filtering,代码奉献一下。

实现的细节

作者的matlab代码:https://github.com/YuanhaoGong/SideWindowFilter

CVPR2019 Oral 论文《Side Window Filtering》C++代码实现_第1张图片

CVPR2019 Oral 论文《Side Window Filtering》C++代码实现_第2张图片

代码

//针对灰度图的均值滤波+CVPR 2019的SideWindowFilter
//其他种类的滤波直接换核即可

int cnt[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
vector  filter[8];

void InitFilter(int radius) {
	int n = radius * 2 + 1;
	for (int i = 0; i < 8; i++) {
		cnt[i] = 0;
		filter[i].clear();
	}
	for (int i = 0; i < 8; i++) {
		for (int x = 0; x < n; x++) {
			for (int y = 0; y < n; y++) {
				if (i == 0 && x <= radius && y <= radius) {
					filter[i].push_back(1);
				}
				else if (i == 1 && x <= radius && y >= radius) {
					filter[i].push_back(1);
				}
				else if (i == 2 && x >= radius && y <= radius) {
					filter[i].push_back(1);
				}
				else if (i == 3 && x >= radius && y >= radius) {
					filter[i].push_back(1);
				}
				else if (i == 4 && x <= radius) {
					filter[i].push_back(1);
				}
				else if (i == 5 && x >= radius) {
					filter[i].push_back(1);
				}
				else if (i == 6 && y >= radius) {
					filter[i].push_back(1);
				}
				else if (i == 7 && y <= radius) {
					filter[i].push_back(1);
				}
				else {
					filter[i].push_back(0);
				}
			}
		}
	}
	for (int i = 0; i < 8; i++) {
		int sum = 0;
		for (int j = 0; j < filter[i].size(); j++) sum += filter[i][j] == 1;
		cnt[i] = sum;
	}
}

Mat SideWindowFilter(Mat src, int radius = 1) {
	int row = src.rows;
	int col = src.cols;
	int channels = src.channels();
	InitFilter(radius);
	for (int i = 0; i < 8; i++) {
		printf("%d ", cnt[i]);
	}
	printf("\n");
	if (channels == 1) {
		Mat dst(row, col, CV_8UC1);
		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				if (i < radius || i + radius >= row || j < radius || j + radius >= col) {
					dst.at(i, j) = src.at(i, j);
					continue;
				}
				int minn = 256;
				int pos = 0;
				for (int k = 0; k < 8; k++) {
					int val = 0;
					int id = 0;
					for (int x = -radius; x <= radius; x++) {
						for (int y = -radius; y <= radius; y++) {
							//if (x == 0 && y == 0) continue;
							val += src.at(i + x, j + y) * filter[k][id++];
						}
					}
					val /= cnt[k];
					if (abs(val - src.at(i, j)) < minn) {
						minn = abs(val - src.at(i, j));
						pos = k;
					}
				}
				int val = 0;
				int id = 0;
				for (int x = -radius; x <= radius; x++) {
					for (int y = -radius; y <= radius; y++) {
						//if (x == 0 && y == 0) continue;
						val += src.at(i + x, j + y) * filter[pos][id++];
					}
				}
				dst.at(i, j) = val / cnt[pos];
			}
		}
		return dst;
	}
	Mat dst(row, col, CV_8UC3);
	for (int c = 0; c < 3; c++) {
		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				if (i < radius || i + radius >= row || j < radius || j + radius >= col) {
					dst.at(i, j)[c] = src.at(i, j)[c];
					continue;
				}
				int minn = 256;
				int pos = 0;
				for (int k = 0; k < 8; k++) {
					int val = 0;
					int id = 0;
					for (int x = -radius; x <= radius; x++) {
						for (int y = -radius; y <= radius; y++) {
							//if (x == 0 && y == 0) continue;
							val += src.at(i + x, j + y)[c] * filter[k][id++];
						}
					}
					val /= cnt[k];
					if (abs(val - src.at(i, j)[c]) < minn) {
						minn = abs(val - src.at(i, j)[c]);
						pos = k;
					}
				}
				int val = 0;
				int id = 0;
				for (int x = -radius; x <= radius; x++) {
					for (int y = -radius; y <= radius; y++) {
						//if (x == 0 && y == 0) continue;
						val += src.at(i + x, j + y)[c] * filter[pos][id++];
					}
				}
				dst.at(i, j)[c] = val / cnt[pos];
			}
		}
	}
	return dst;
}

效果

原图
CVPR2019 Oral 论文《Side Window Filtering》C++代码实现_第3张图片
均值滤波20次后的结果
CVPR2019 Oral 论文《Side Window Filtering》C++代码实现_第4张图片
使用论文算法对均值滤波做强制保边结果
CVPR2019 Oral 论文《Side Window Filtering》C++代码实现_第5张图片

结论

可以看到经过20次滤波之后,正常的图像的一些边缘,角点被模糊了。但经过论文算法做强制保留之后的边缘和角点没被模糊,这是边缘保留的一大突破性进展啊,不由得为作者的智慧点赞!

你可能感兴趣的:(数字图像处理论文和算法复现)