双边滤波
原文地址:双边滤波
文中出现的2范数:

文中代码
//------------------------------------------------------------- //作者:不用先生,2018.11.26 //自实现的图像双边滤波算法 //bilateral.cpp //------------------------------------------------------------- #include "opencv2/core/core.hpp" #include "opencv2/opencv.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include <iostream> #include <cmath> using namespace std; using namespace cv; //-------------------------------------------------------------- //函数名:my_Bilateral //函数功能:自己编写的可用于灰度图及彩色图的双边滤波函数; //参数:Mat &scr:输入图像,为单通道灰度图或三通道彩色图; //参数:Mat &dst:输出图像,尺寸与通道数与输入图像吻合; //参数:int d:滤波器大小,应该保证为奇数; //参数:double sigmaColor:颜色域/像素值域方差,sigmaColor越大,平滑效果越好,对边缘的保护越弱; //参数:double sigmaSpace:空间域方差,sigmaSpace越大,结果越平滑; //-------------------------------------------------------------- bool my_Bilateral(Mat &scr, Mat &dst, int d, double sigmaColor, double sigmaSpace) { if (!scr.data) { cerr << "输入图像错误,请检查" << endl;; return false; } if (d % 2 == 0) { cerr << "输入窗口大小应该为奇数,请修改"<<endl; return false; } dst = scr.clone(); int row = dst.rows; //获取图像大小; int col = dst.cols; int copyBorderSize =floor(0.5+ d / 2); Mat copyBorder_dst; copyMakeBorder(dst, copyBorder_dst, copyBorderSize, copyBorderSize, copyBorderSize, copyBorderSize, BORDER_REFLECT); int channels = dst.channels(); if (channels == 1) //如果是灰度图像 { for (int i = 0; i < row; i++) //对每一个点进行处理 { for (int j = 0; j < col; j++) { double weightSum = 0; double filterValue = 0; for (int row_d = -(d / 2); row_d <= (d / 2); row_d++) //以图像中的一点为中心,d为边长的方形区域内进行计算 { for (int col_d = -(d / 2); col_d <= (d / 2); col_d++) { double distance_Square = row_d*row_d + col_d*col_d;//row_d和col_d就是离中心点的距离 double value_Square = pow((scr.at<uchar>(i, j) - copyBorder_dst.at<uchar>(i + (d / 2) + row_d, j + (d / 2) + col_d)), 2); double weight = exp(-1 * (distance_Square / (2 * sigmaSpace*sigmaSpace) + value_Square / (2 * sigmaColor*sigmaColor))); weightSum += weight; //求滤波窗口内的权重和,用于归一化; filterValue += (weight*copyBorder_dst.at<uchar>(i + (d / 2) + row_d, j + (d / 2) + col_d)); } } dst.at<uchar>(i, j) = filterValue / weightSum; } } return true; } else if (channels == 3) //如果是RGB图像 { for (int c = 0; c < channels; c++) //逐通道进行处理 { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { double weightSum = 0; double filterValue = 0; for (int row_d = -(d / 2); row_d <= (d / 2); row_d++) { for (int col_d = -(d / 2); col_d <= (d / 2); col_d++) { double distance_Square = row_d*row_d + col_d*col_d; double value_Square = pow((scr.at<Vec3b>(i, j)[c] - copyBorder_dst.at<Vec3b>(i + (d / 2) + row_d, j + (d / 2) + col_d)[c]), 2); double weight = exp(-1 * (distance_Square / (2 * sigmaSpace*sigmaSpace) + value_Square / (2 * sigmaColor*sigmaColor))); weightSum += weight; filterValue += (weight*copyBorder_dst.at<Vec3b>(i + (d / 2) + row_d, j + (d / 2) + col_d)[c]); } } dst.at<Vec3b>(i, j)[c] = filterValue / weightSum; } } } return true; } else { cerr << "图像通道数有误,请确定"; return false; } } //---------------- //主函数 //---------------- void main() { Mat scr = imread("03.jpg", IMREAD_UNCHANGED); //以默认的方式读入图像 if (!scr.data) //判断图像是否被正确读取; { return; } int half_Window_Size = 10; //窗口半宽大小 int window_Size = 2 * half_Window_Size + 1; //窗口大小,应该为奇数; double sigmaColor = 10; //像素值域的方差 double sigmaSpace = 10; //空间域的方差 //使用自实现的双边滤波对结果进行处理 Mat my_dst = scr.clone(); if (!my_Bilateral(scr, my_dst, window_Size, sigmaColor, sigmaSpace)) { cerr << "自编写的双边滤波再计算过程中出差,请查验" << endl; } //用OpenCV自带的双边滤波函数进行处理 Mat auto_dst = scr.clone(); bilateralFilter(scr, auto_dst, window_Size, sigmaColor, sigmaSpace); //用高斯函数记性处理 Mat gau_dst = scr.clone(); Size gauSize(window_Size, window_Size); GaussianBlur(scr, gau_dst, gauSize, sigmaSpace); imwrite("temp1.jpg", my_dst); imwrite("temp2.jpg", auto_dst); imwrite("temp3.jpg", gau_dst); system("pause"); return; }

浙公网安备 33010602011771号