Several image filtering based on opencv

1. Introduction

    Box filtering, mean filtering, Gaussian filtering, median filtering, bilateral filtering, guided filtering.

    boxFilter()

    blur()

    GaussianBlur()

    medianBlur()

    bilateralFilter()

    1. Bilateral filtering - non-linear filter, maintaining edges and reducing noise smoothly.

   The weighted average method is adopted, and the weighted average of the brightness values ​​of surrounding pixels is used to represent the intensity of a certain pixel.

   The weight of bilateral filtering takes into account not only the Euclidean distance of the pixels, but also the radiation differences in the pixel range.

  The kernel function of bilateral filtering is the comprehensive result of the spatial domain kernel and the pixel range kernel:

  In the flat area of ​​the image , the pixel value changes very little, and the spatial domain weight plays a major role, which is equivalent to Gaussian blur;

  In the edge area of ​​the image , the pixel values ​​change greatly, and the weight of the pixel range domain becomes larger, thereby maintaining the edge information.

  2. Guidance filtering - explicitly uses the guidance image to calculate the output image.

  Compared with bilateral filtering, guided filtering works better near the boundary and has a linear time speed advantage of O(N).

  Guided filtering can maintain gradients, while bilateral filtering will cause gradient flipping.

 

2. Code

#include <opencv2/core/core.hpp>                      
#include <opencv2/highgui/highgui.hpp>          
#include <opencv2/imgproc/imgproc.hpp>      
#include <iostream> 

using namespace std;
using namespace cv;

#define WINDOWNAME "【滤波处理结果窗口】"  

//---------------【全局变量声明部分】-------------------------  
Mat g_srcIamge, g_dstImage1, g_dstImage2, g_dstImage3, g_dstImage4, g_dstImage5, g_dstImage6;
int g_nBoxFilterValue = 1;       //盒式滤波内核值  
int g_nMeanBlurValue = 1;        //均值滤波内核值  
int g_nGaussianBlurValue = 1;    //高斯滤波内核值  
int g_nMedianBlurValue = 1;      //中值滤波内核值  
int g_nBilateralFilterValue = 1; //双边滤波内核值  
int g_nGuidedFilterValue = 1;    //导向滤波内核值  
const int g_nMaxVal = 20;        //预设滑动条最大值 

//--------------【全局函数声明部分】-------------------------   
static void on_BoxFilter(int, void*);       //盒式滤波器  
static void on_MeanBlur(int, void*);        //均值滤波器  
static void on_GaussianBlur(int, void*);    //高斯滤波器  
static void on_MedianBlur(int, void*);      //中值滤波器  
static void on_BilateralFilter(int, void*); //双边滤波器  
static void on_GuidedFilter(int, void*);    //导向滤波器  
void guidedFilter(Mat& srcMat, Mat& guidedMat, Mat& dstImage, int radius, double eps); //导向滤波器  

//----------------------------【主函数】---------------------------  
int main()
{
    //------------【1】读取源图像并检查图像是否读取成功------------    
    g_srcIamge = imread("D:\\opencv4_1_2\\opencv\\sources\\samples\\data\\lena.jpg");
    if (!g_srcIamge.data)
    {
        cout << "读取图片错误,请重新输入正确路径!\n";
        system("pause");
        return -1;
    }
    namedWindow("【源图像】", 1);     //创建窗口  
    imshow("【源图像】", g_srcIamge); //显示窗口  
    
    //------------【2】在WINDOWNAME窗口上分别创建滤波6个滑动条------------         
    namedWindow(WINDOWNAME); //创建窗口    
    createTrackbar("方框滤波", WINDOWNAME, &g_nBoxFilterValue, g_nMaxVal, on_BoxFilter); //创建方框滤波轨迹条  
    on_BoxFilter(g_nBoxFilterValue, 0);
    createTrackbar("均值滤波", WINDOWNAME, &g_nMeanBlurValue, g_nMaxVal, on_MeanBlur); //创建均值滤波轨迹条  
    on_MeanBlur(g_nMeanBlurValue, 0);
    createTrackbar("高斯滤波", WINDOWNAME, &g_nGaussianBlurValue, g_nMaxVal, on_GaussianBlur); //创建高斯滤波轨迹条  
    on_GaussianBlur(g_nGaussianBlurValue, 0);
    createTrackbar("中值滤波", WINDOWNAME, &g_nMedianBlurValue, g_nMaxVal, on_MedianBlur); //创建中值滤波轨迹条  
    on_MedianBlur(g_nMedianBlurValue, 0);
    createTrackbar("双边滤波", WINDOWNAME, &g_nBilateralFilterValue, g_nMaxVal, on_BilateralFilter); //创建双边滤波轨迹条  
    on_BilateralFilter(g_nBilateralFilterValue, 0);
    createTrackbar("导向滤波", WINDOWNAME, &g_nGuidedFilterValue, g_nMaxVal, on_GuidedFilter); //创建导向滤波轨迹条  
    on_GuidedFilter(g_nGuidedFilterValue, 0);

    //------------【3】退出程序------------    
    cout << "\t按下'q'键,退出程序~!\n" << endl;
    while (char(waitKey(1)) != 'q') {}
    return 0;
}

//----------------------【on_BoxFilter()函数】------------------------  
static void on_BoxFilter(int, void*)
{
    boxFilter(g_srcIamge, g_dstImage1, -1, Size(g_nBoxFilterValue * 2 + 1, g_nBoxFilterValue * 2 + 1));
    cout << "\n当前为【盒式滤波】处理效果,其内核大小为:" << g_nBoxFilterValue * 2 + 1 << endl;
    imshow(WINDOWNAME, g_dstImage1);
}

//----------------------【on_MeanBlur()函数】------------------------  
static void on_MeanBlur(int, void*)
{
    blur(g_srcIamge, g_dstImage2, Size(g_nMeanBlurValue * 2 + 1, g_nMeanBlurValue * 2 + 1), Point(-1, -1));
    cout << "\n当前为【均值滤波】处理效果,其内核大小为:" << g_nMeanBlurValue * 2 + 1 << endl;
    imshow(WINDOWNAME, g_dstImage2);
}

//----------------------【on_GaussianBlur()函数】------------------------  
static void on_GaussianBlur(int, void*)
{
    GaussianBlur(g_srcIamge, g_dstImage3, Size(g_nGaussianBlurValue * 2 + 1, g_nGaussianBlurValue * 2 + 1), 0, 0);
    cout << "\n当前为【高斯滤波】处理效果,其内核大小为:" << g_nGaussianBlurValue * 2 + 1 << endl;
    imshow(WINDOWNAME, g_dstImage3);
}

//----------------------【on_MedianBlur()函数】------------------------  
static void on_MedianBlur(int, void*)
{
    medianBlur(g_srcIamge, g_dstImage4, g_nMedianBlurValue * 2 + 1);
    cout << "\n当前为【中值滤波】处理效果,其内核大小为:" << g_nMedianBlurValue * 2 + 1 << endl;
    imshow(WINDOWNAME, g_dstImage4);
}

//----------------------【on_BilateralFilter()函数】------------------------  
static void on_BilateralFilter(int, void*)
{
    bilateralFilter(g_srcIamge, g_dstImage5, g_nBilateralFilterValue, g_nBilateralFilterValue * 2, g_nBilateralFilterValue / 2);
    cout << "\n当前为【双边滤波】处理效果,其内核大小为:" << g_nBilateralFilterValue << endl;
    imshow(WINDOWNAME, g_dstImage5);
}

//----------------------【on_GuidedFilter()函数】------------------------  
static void on_GuidedFilter(int, void*)
{
    vector<Mat> vSrcImage, vResultImage;
    //【1】对源图像进行通道分离,并对每个分通道进行导向滤波操作  
    split(g_srcIamge, vSrcImage);
    for (int i = 0; i < 3; i++)
    {
        Mat tempImage;
        vSrcImage[i].convertTo(tempImage, CV_64FC1, 1.0 / 255.0); //将分通道转换成浮点型数据  
        Mat cloneImage = tempImage.clone(); //将tempImage复制一份到cloneImage  
        Mat resultImage;
        guidedFilter(tempImage, cloneImage, resultImage, g_nGuidedFilterValue * 2 + 1, 0.01); //对分通道分别进行导向滤波  
        vResultImage.push_back(resultImage); //将分通道导向滤波后的结果存放到vResultImage中  
    }
    //【2】将分通道导向滤波后结果合并  
    merge(vResultImage, g_dstImage6);
    cout << "\n当前处理为【导向滤波】,其内核大小为:" << g_nGuidedFilterValue * 2 + 1 << endl;
    imshow(WINDOWNAME, g_dstImage6);
}

//-------------------【实现导向滤波器函数部分】-------------------------  
void guidedFilter(Mat& srcMat, Mat& guidedMat, Mat& dstImage, int radius, double eps)
{
    //------------【0】转换源图像信息,将输入扩展为64位浮点型,以便以后做乘法------------  
    srcMat.convertTo(srcMat, CV_64FC1);
    guidedMat.convertTo(guidedMat, CV_64FC1);
    //--------------【1】各种均值计算----------------------------------  
    Mat mean_p, mean_I, mean_Ip, mean_II;
    boxFilter(srcMat, mean_p, CV_64FC1, Size(radius, radius)); //生成待滤波图像均值mean_p   
    boxFilter(guidedMat, mean_I, CV_64FC1, Size(radius, radius)); //生成导向图像均值mean_I     
    boxFilter(srcMat.mul(guidedMat), mean_Ip, CV_64FC1, Size(radius, radius)); //生成互相关均值mean_Ip  
    boxFilter(guidedMat.mul(guidedMat), mean_II, CV_64FC1, Size(radius, radius)); //生成导向图像自相关均值mean_II  
    //--------------【2】计算相关系数,计算Ip的协方差cov和I的方差var------------------  
    Mat cov_Ip = mean_Ip - mean_I.mul(mean_p);
    Mat var_I = mean_II - mean_I.mul(mean_I);
    //---------------【3】计算参数系数a、b-------------------  
    Mat a = cov_Ip / (var_I + eps);
    Mat b = mean_p - a.mul(mean_I);
    //--------------【4】计算系数a、b的均值-----------------  
    Mat mean_a, mean_b;
    boxFilter(a, mean_a, CV_64FC1, Size(radius, radius));
    boxFilter(b, mean_b, CV_64FC1, Size(radius, radius));
    //---------------【5】生成输出矩阵------------------  
    dstImage = mean_a.mul(srcMat) + mean_b;
}

3. Display

Guess you like

Origin blog.csdn.net/Goodness2020/article/details/132029714