双边滤波器在实践中的应用还是挺广范的,效果也不错,本文主要是实现双边滤波器功能,中间处理不借助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;
}
写在最后,这段代码大约是花费了三到四个上午的时间,个人的编程水平有限,也是作为练手直接上的,后面还会继续更~