OpenCv阈值化与常用滤波算法

阈值化

简易阈值化函数说明

选定一个阈值,可以对原图像各个像素点与阈值相比较,作出判断。

   double threshold( InputArray src, OutputArray dst,
                     double thresh,  //阈值
                     double maxval,  //目标最大像素设置值
                     int type  //阈值化输出模式
                     );

     参数src:
    1.   常为灰度图.使用cvtColor(src,gray,CV_RGB2GRAY);可转换为灰度图
    2.   如果为三通道图片,需要先分通道再处理。使用
            a.  vector<Mat> mv;  
            b.  split(src,mv); //mv[0]为b通道 mv[1]为g mv[2]为r通道
            c.  r.create(src.size(),CV_8UC1);
            d.  mv[2].copyTo(r); //即可获得r通道


     参数thresh:
            依据实际情况设定,也可以使用bar随机设定。

     参数maxval:
            阈值化后设置的目标图像最大像素值。

     参数type:
            阈值化输出图像模式。可选参数为
 THRESH_BINARY=CV_THRESH_BINARY,  //二值阈值化  dst=(src>T)?m:0
 THRESH_BINARY_INV=CV_THRESH_BINARY_INV,//dst=(src>T)?0:M
 THRESH_TRUNC=CV_THRESH_TRUNC, //截断阈值化 dst=(src>T)?M:src
 THRESH_TOZERO=CV_THRESH_TOZERO,//低阈值化 dst=(src>T)?src:0
 THRESH_TOZERO_INV=CV_THRESH_TOZERO_INV,//高阈值化 (src>T)?0:src
 THRESH_OTSU=CV_THRESH_OTSU //最大类间方差法 通过方差的计算来寻找一个合适的灰度级别来划分,该算法可以有效的避免图像亮度和对比度带来的影响. 对于OTSU法,因为是对图像的灰度级进行聚类,在执行该算法之前,需要计算图像的灰度直方图。

代码

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

using namespace cv;
using namespace std;

void onBarChange(int,void*);  //bar的回调函数

Mat src, src_gray;
Mat src_r,src_g,src_b;
vector<Mat> mv;    //用于存储分割的三通道图片
int th_gray,th_r,th_g,th_b;  //bar值记录


int main()
{
    namedWindow("src");
    namedWindow("gray");
    namedWindow("r");
    namedWindow("g");
    namedWindow("b");

    src = imread("H:\\cat.jpg");
    cvtColor(src,src_gray,CV_RGB2GRAY); //转为灰度图

    src_r.create(src.size(),CV_8UC1);
    src_g.create(src.size(),CV_8UC1);
    src_b.create(src.size(),CV_8UC1);

    split(src,mv);    //将三通道图片分割为单通道
    mv[0].copyTo(src_b);
    mv[1].copyTo(src_g);
    mv[2].copyTo(src_r);

    createTrackbar("gray","src",&th_gray,255,onBarChange);  //添加bar 最大值设置为255
    createTrackbar("r","src",&th_r,255,onBarChange);
    createTrackbar("g","src",&th_g,255,onBarChange);
    createTrackbar("b","src",&th_b,255,onBarChange);

    waitKey(0);
    return 0;
}



void onBarChange(int,void*)
{
    Mat r,g,b,gray;

    //阈值化操作 模式为二值阈值化
    threshold(src_gray,gray,th_gray,255,THRESH_BINARY); 
    threshold(src_r,r,th_r,255,THRESH_BINARY);
    threshold(src_g,g,th_g,255,THRESH_BINARY);
    threshold(src_b,b,th_b,255,THRESH_BINARY);

    imshow("src",src);
    imshow("gray",gray);
    imshow("r",r);
    imshow("g",g);
    imshow("b",b);
}



自适应阈值

针对有很强照明或反射梯度的图像,需要根据梯度进行阈值化时,自适应阈值很有用.

void adaptiveThreshold( InputArray src, OutputArray dst,
                        double maxValue,  //目标图像最大像素值
                        int adaptiveMethod, //自适应模式
                        int thresholdType, //阈值化模式
                        int blockSize, //自适应区域大小
                        double C //自适应常数
                        );
自适应阈值化有两种模式:
 由参数adaptiveMethod指定.
 ADAPTIVE_THRESH_MEAN_C=0,  //自适应阈值T在每个像素点都不同,通过计算像素点周围的bxb(blockSize指定b)区域的加权平均,减去一个常数(c指定)得到自适应阈值。
 ADAPTIVE_THRESH_GAUSSIAN_C=1 //在计算加权平均时候,在(x,y)周围的像素点依据高斯函数按照它们离中心点的距离进行加权计算。

----------

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

using namespace cv;
using namespace std;

void onBarChange(int,void*);  //bar的回调函数

Mat src,gray;
Mat th,th_adapter;
int thre;

int main()
{
    src = imread("H:\\adapter.jpg");
    cvtColor(src,gray,CV_RGB2GRAY);

    namedWindow("src",0);
    namedWindow("th",0);
    namedWindow("adapter",0);


    imshow("src",src);

    createTrackbar("th","src",&thre,100,onBarChange);
    adaptiveThreshold(gray,th_adapter,255,ADAPTIVE_THRESH_MEAN_C,THRESH_BINARY,3,5);



    imshow("adapter",th_adapter);



    waitKey(0);
    return 0;

}

void onBarChange(int,void*)
{

    threshold(gray,th,thre,255,THRESH_BINARY);
    imshow("th",th);

}

这里写图片描述


还有一些其他阈值方法,例如迭代法,最大熵。




常用滤波算法

线性滤波器(领域滤波)

    **低通滤波器 --> 模糊处理**
    **高通滤波器 --> 锐化处理**
  • 方框滤波
`void boxFilter( InputArray src, 
                 OutputArray dst,//目标图像大小应该和原图一致
                 int ddepth, //输出图像深度  -1为保持原图
                 Size ksize, //内核大小
                 Point anchor=Point(-1,-1), //内核中心点
                 bool normalize=true, //内核是否归一化
                 int borderType=BORDER_DEFAULT  //边界填充
                 );`   

  参数ksize:
       Size(m,n)即表示mxn的矩阵核

  参数normalize:
       归一化就是把处理的数据放缩到给定范围,例如把(0,30)归一化即缩小了30倍.归一化后便于直观处理。
       当为true时,方框滤波就是均值滤波。
       为false时,即计算周围领域的总和。

  • 均值滤波
void blur( InputArray src, OutputArray dst,
           Size ksize, 
           Point anchor=Point(-1,-1),
           int borderType=BORDER_DEFAULT 
           );

  • 高斯滤波
    图像与高斯分布(正态分布)做卷积操作。可以有效的抑制服从正态分布的噪声。

    高斯滤波认为图像在空间内的像素是缓慢变化的,在邻近点像素变化时不明显的。可以很好的抑制噪声点的影响。
    (一般情况下,我们不希望滤波处理影响到图像的边缘,但是高斯滤波会磨平边缘,达不到想要的结果,这种情况下可以使用"双边滤波算法")


void GaussianBlur( InputArray src,OutputArray dst, 
                   Size ksize,
                   double sigmaX, 
                   double sigmaY=0,
                   int borderType=BORDER_DEFAULT 
                   );


参数ksize:
    高斯内核的大小,例如Size(m,n)即代表mxn的高斯核.也可以为0,如果为0则由sigmaX和sigmaY计算。

参数sigmaX,sigmaY:
    高斯函数在X,Y方向的标准偏差。如果两个值为0的话,则由ksize参数计算(size,x,y不能同时为0)。

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

using namespace cv;
using namespace std;

Mat src,dst_box,dst_blur,dst_guassian;

int main()
{
    src = imread("H:\\cat.jpg");

    boxFilter(src,dst_box,-1,Size(3,3),Point(-1,-1),false); //不归一化处理
    blur(src,dst_blur,Size(5,5));   //均值滤波
    GaussianBlur(src,dst_guassian,Size(3,3),0,0,4);  //3阶高斯核 

    namedWindow("src");
    namedWindow("box");
    namedWindow("blur");
    namedWindow("guassians");

    imshow("src",src);
    imshow("box",dst_box);
    imshow("blur",dst_blur);
    imshow("guassians",dst_guassian);

    waitKey(0);
    return 0;
}


非线性滤波器

  • 中值滤波
    中值滤波器将中心像素的正方形领域内的每个像素值用中间像素值(需要对正方形每个像素值排序)替换。

    中值滤波对噪声抑制很有效(噪声点很难入选).但是因为需要做排序操作,故花费时间和资源会更多.

void medianBlur( InputArray src, OutputArray dst, 
                 int ksize  
                 );

参数ksize:
      必须是大于1的奇数。3,5,7……


  • 双边滤波
    双边滤波和高斯滤波相似,会依据每个像素及其邻域构成一个加权平均值,加权分为两个部分.
    1.与高斯滤波相似,选定高斯sigma区域
    2.选定一个加权值,参考下面sigmaColor参数介绍,利用邻域值的亮度差值来均衡边缘效应。

void bilateralFilter( InputArray src, OutputArray dst, 
                      int d, //滤波像素点直径
                      double sigmaColor, //颜色控制sigma
                      double sigmaSpace,
                      int borderType=BORDER_DEFAULT 
                      );
参数d:
    滤波过程中,像素点的邻域直径。该值越大就会糅合更大的区域颜色。也可以设定该值为0或者负数,通过sigmaSpace参数设定来判定该值。

参数sigmaColor:
    高斯加权,基于其他像素与中心像素的亮度差值(各种颜色差值)的加权。该值越大,就有更宽广的邻域颜色会被融合进来。

参数sigmaSpace:
   该值越大,参与滤波的邻域就越大,当d大于的情况下,该值不起作用。否则邻域正比与该值。


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

using namespace cv;
using namespace std;

Mat src,dst_med,dst_bin;


int main()
{
    src = imread("H:\\cat.jpg");

    medianBlur(src,dst_med,3);  //邻域为3的中值滤波
    bilateralFilter(src,dst_bin,20,20*2,20);//半径为10  颜色为40

    namedWindow("src");
    namedWindow("med");
    namedWindow("bin");

    imshow("src",src);
    imshow("med",dst_med);
    imshow("bin",dst_bin);

    waitKey(0);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值