用双边滤波图像平滑

来源:互联网 发布:淘宝搜索指数查询 编辑:程序博客网 时间:2024/06/05 18:56
算法

双边滤波(Bilateral filter)是非线性滤波,是一种可以保边去噪的滤波器。之所以可以达到此去噪效果,是因为滤波器是由两个函数构成。一个函数是由几何空间距离决定滤波器系数。另一个由像素差值决定滤波器系数。
双边滤波器中,输出像素的值依赖于邻域像素的值的加权组合,

权重系数w(i,j,k,l)取决于定义域核

和值域核

的乘积

同时考虑了空间域与值域的差别,而Gaussian Filter和α均值滤波分别只考虑了空间域和值域差别。


函数

void bilateralFilter(InputArray src, OutputArraydst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT)  

第一个参数,InputArray类型的src,输入图像,即源图像,需要为8位或者浮点型单通道、三通道的图像。
第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。
第三个参数,int类型的d,表示在过滤过程中每个像素邻域的直径。如果这个值我们设其为非正数,那么OpenCV会从第五个参数sigmaSpace来计算出它来。
第四个参数,double类型的sigmaColor,颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
第五个参数,double类型的sigmaSpace坐标空间中滤波器的sigma值,坐标空间的标注方差。他的数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。当d>0,d指定了邻域大小且与sigmaSpace无关。否则,d正比于sigmaSpace。
第六个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。


源码
亲测,这个耗时很久。对整张图片做平滑之前还是要一些处理。加掩膜?用开闭运算?

#include "opencv2/highgui/highgui.hpp"#include <opencv2/opencv.hpp>#include "opencv2/imgproc/imgproc.hpp"#include <iostream>using namespace std;using namespace cv;#define WINDOW_NAME "Contrast"const int g_nMaxA = 100;int sigmaColor;int sigmaSpace;Mat g_srcImage1(Scalar(0,0,0));Mat g_srcImage2(Scalar(0,0,0));Mat g_dstImage(Scalar(0,0,0));//定义像素值系数的控制条void on_TrackbarColor(int, void*){    //让两张图线性融合(并不是要这个功能啊!)    //addWeighted(g_srcImage1, g_dAvalue, g_srcImage2, g_dBvalue, 0.0, g_dstImage);    /*    第一个参数,InputArray类型的src,输入图像,即源图像,需要为8位或者浮点型单通道、三通道的图像。    第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。    第三个参数,int类型的d,表示在过滤过程中每个像素邻域的直径。如果这个值我们设其为非正数,那么OpenCV会从第五个参数sigmaSpace来计算出它来。    第四个参数,double类型的sigmaColor,颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。    第五个参数,double类型的sigmaSpace坐标空间中滤波器的sigma值,坐标空间的标注方差。他的数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。    当d>0,d指定了邻域大小且与sigmaSpace无关。否则,d正比于sigmaSpace。    第六个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。     */    bilateralFilter(g_srcImage1, g_dstImage, -1, sigmaColor, sigmaSpace, BORDER_DEFAULT);    imshow(WINDOW_NAME, g_dstImage);    waitKey(1);}//定义空间位置系数的控制条void on_TrackbarSpace(int, void*){    //让两张图线性融合(并不是要这个功能啊!)    //addWeighted(g_srcImage1, g_dAvalue, g_srcImage2, g_dBvalue, 0.0, g_dstImage);    /*    第一个参数,InputArray类型的src,输入图像,即源图像,需要为8位或者浮点型单通道、三通道的图像。    第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。    第三个参数,int类型的d,表示在过滤过程中每个像素邻域的直径。如果这个值我们设其为非正数,那么OpenCV会从第五个参数sigmaSpace来计算出它来。    第四个参数,double类型的sigmaColor,颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。    第五个参数,double类型的sigmaSpace坐标空间中滤波器的sigma值,坐标空间的标注方差。他的数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。    当d>0,d指定了邻域大小且与sigmaSpace无关。否则,d正比于sigmaSpace。    第六个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。     */    bilateralFilter(g_srcImage1, g_dstImage, -1, sigmaSpace, sigmaSpace, BORDER_DEFAULT);    imshow(WINDOW_NAME, g_dstImage);    waitKey(1);}int main(int argc, char** argv){    g_srcImage1 = imread("newme.jpeg");//984 × 738    //g_srcImage2 = imread("../view.jpeg");//1200 x 800    //Rect rect(int(g_srcImage2.cols-g_srcImage1.cols)/2, 0, g_srcImage1.cols, g_srcImage1.rows);    //g_srcImage2 = g_srcImage2(rect);    if(!g_srcImage1.data){        cout<<"read error"<<endl;    }    sigmaColor = 4;    sigmaSpace = 4;    namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE);    char TrackbarNameColor[50];    sprintf(TrackbarNameColor, "of Color Value: %d", sigmaColor);    //建立响应    createTrackbar(TrackbarNameColor, WINDOW_NAME, &sigmaColor, g_nMaxA, on_TrackbarColor);    on_TrackbarColor(sigmaColor, 0);    char TrackbarNameSpace[50];    sprintf(TrackbarNameSpace, "of Space value: %d", sigmaSpace);    createTrackbar(TrackbarNameSpace, WINDOW_NAME, &sigmaSpace, g_nMaxA, on_TrackbarSpace);    on_TrackbarSpace(sigmaSpace, 0);    waitKey(0);    return 0;}