C代码实战-双边滤波器20201019

双边滤波器在实践中的应用还是挺广范的,效果也不错,本文主要是实现双边滤波器功能,中间处理不借助opencv的相关库函数,整体写下来,觉得收获还是挺大的,所以将源码也放上来,代码已经做了详细的注释,供大家交流参考。

#include<iostream>
#include<math.h>

#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>

using namespace std;
using namespace cv;

void bilateral_filter_ys(unsigned int* src, unsigned int* dst, int ksize, int channels, int cols, int rows, double space_sigma, double color_sigma)
{
	//1. 定义空间模板和颜色模板的系数和滤波半径
	double space_coeff = -0.5 / (space_sigma * space_sigma);
	double color_coeff = -0.5 / (color_sigma * color_sigma);
	int radius = ksize / 2;

	// 2. 定义颜色差异的Map和距离Map,并给出临时变量
		
	double color_weight[256 * 3] = { 0 };//变量定义有变量
	double space_weight[25] = { 0 };

	//3.生成颜色差异MAP
	for (int i = 0; i < channels * 256; i++)
	{
		color_weight[i] = exp(i * i * color_coeff);
	}

	//4.定义窗口滤波指针
	int loc = 0;

	//5.生成距离差异MAP
	for (int i = -radius; i < radius; i++)
	{
		for (int j = -radius; j < radius; j++)
		{
			double distance = -sqrt(i * i + j * j);
			space_weight[loc] = exp(distance * distance * space_coeff);
			loc++;
		}
	}

	//6.开始滤波,channel=3的情况
	for (int i = radius; i < rows - radius; i++)
	{
		for (int j = radius; j < cols - radius; j++)
		{
			double sumb = 0, sumg = 0, sumr = 0, wsum = 0;
			int b0 = src[(i * cols + j) * 3 + 0];
			int g0 = src[(i * cols + j) * 3 + 1];
			int r0 = src[(i * cols + j) * 3 + 2];

			for (int p = i - radius; p <= i + radius; p++)
			{
				for (int q = j - radius; q <= j + radius; q++)
				{
					int b = src[(p * cols + q) * 3 + 0];
					int g = src[(p * cols + q) * 3 + 1];
					int r = src[(p * cols + q) * 3 + 2];
					double space_w = space_weight[(p + radius - i) * ksize + (q + radius - j)];
					double color_w = color_weight[abs(b - b0) + abs(g - g0) + abs(r - r0)];
					double weight = space_w * color_w;

					sumb += b * weight;
					sumg += g * weight;
					sumr += r * weight;
					wsum += weight;

				}
			}

			wsum = 1.0f / wsum;
			dst[(i * cols + j) * 3 + 0] = round(sumb * wsum);
			dst[(i * cols + j) * 3 + 1] = round(sumg * wsum);
			dst[(i * cols + j) * 3 + 2] = round(sumr * wsum);
		}
	}
}

int main()
{
	//read img and parameters
	Mat image_src = imread("111.jpg", 1);
	int cols = image_src.cols;
	int rows = image_src.rows;
	int channels = image_src.channels();

	//define matrix space memory
	unsigned int* image_src_rgb = (unsigned int*)malloc(rows * cols * sizeof(unsigned int) * 3);
	unsigned int* image_dst_rgb = (unsigned int*)malloc(rows * cols * sizeof(unsigned int) * 3);


	//value exchange
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			image_src_rgb[(i * cols + j) * 3 + 0] = image_src.at<Vec3b>(i, j)[2];
			image_src_rgb[(i * cols + j) * 3 + 1] = image_src.at<Vec3b>(i, j)[1];
			image_src_rgb[(i * cols + j) * 3 + 2] = image_src.at<Vec3b>(i, j)[0];
		}
	}

	//filtering
	bilateral_filter_ys(image_src_rgb, image_dst_rgb, 5, channels, cols, rows, 100, 50);

	//matrix 2 Mat
	Mat image_dst(image_src.size(), image_src.type());
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			image_dst.at<Vec3b>(i, j)[2] = image_dst_rgb[(i * cols + j) * 3 + 0];
			image_dst.at<Vec3b>(i, j)[1] = image_dst_rgb[(i * cols + j) * 3 + 1];
			image_dst.at<Vec3b>(i, j)[0] = image_dst_rgb[(i * cols + j) * 3 + 2];
		}
	}

	//imshow
	imshow("image_src", image_src);
	imshow("image_dst", image_dst);

	//imwrite
	imwrite("image_src.bmp", image_src);
	imwrite("image_dst.bmp", image_dst);

	waitKey();
	return 0;

}

写在最后,这段代码大约是花费了三到四个上午的时间,个人的编程水平有限,也是作为练手直接上的,后面还会继续更~

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值