您的位置:首页 > 运维架构

OpenCV【3】---二值化图像

2015-12-26 20:00 204 查看
  本文主要讲解实现自定义的二值化功能以及讲解OpenCV中的二值化函数
adaptiveThreshold
threshold
来达到同样的目的,当然还有其他的二值化函数也可以达到同样的目的。

1 OpenCV二值化函数

  OpenCV提供了
全局固定阈值
局部自适应阈值
的函数来实现二值化图像。

  全局二值化方法(Global Binariztion Method)对每一幅图计算一个单一的阀值。灰度级大于阈值的像素被标记为背景色,否则为前景。

  局部二值化方法(Local Adaptive Binarization Method)以像素的邻域的信息为基础来计算每一个像素的阈值。其中一些方法还会计算整个图像中的一个阈值面。如果图像中的一个像素(x,y)的灰度级高于在(x,y)点的阈值面的计算值,那么把像素(x,y)标记为背景,否则为前景字符。

1.1 局部自适应阈值函数说明

C++:


void adaptiveThreshold(InputArray src, OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C)

C:


void cvAdaptiveThreshold(const CvArr* src, CvArr* dst, double max_value, int adaptive_method=CV_ADAPTIVE_THRESH_MEAN_C, int threshold_type=CV_THRESH_BINARY, int block_size=3, double param1=5 )

参数说明:

  src:单通道的输入图像

  dst:和输入图像同类型的输出图像

  maxValue: 二值化后非零的最大值设置,二值,顾名思义有两个值,一个是零,一个是(0~256)之间的值。具体和阈值类型搭配说明见下面。

  adaptiveMethod:自适应阈值算法选择:CV_ADAPTIVE_THRESH_MEAN_C 或CV_ADAPTIVE_THRESH_GAUSSIAN_C。具体说明见下面。

  thresholdType:阈值类型,下面有详细选择说明。注意,adaptiveThreshold方法只支持前两个参数

  blockSize:用来计算每个像素的阈值的邻域大小,如3,5,7等。

  C:从adaptiveMethod选择的方法中计算出来的平均值或加权平均值减去的参数值,可以是正数或负数。区别C方式函数,没有默认值。

详细说明:

[code]THRESH_BINARY/CV_THRESH_BINARY




[code]THRESH_BINARY_INV/CV_THRESH_BINARY_INV




[code]THRESH_TRUNC/CV_THRESH_TRUNC




[code]THRESH_TOZERO/CV_THRESH_TOZERO




[code]THRESH_TOZERO_INV/CV_THRESH_TOZERO_INV





  
上面的前两个参数是用于自适应阈值的函数。imgpro.hpp
types_c.h
中有定义枚举变量:

[code]enum
{
    CV_THRESH_BINARY=0,/*value=value>threshold?max_value:0*/
    CV_THRESH_BINARY_INV=1,/*value=value>threshold?0:max_value*/
    CV_THRESH_TRUNC=2,/*value=value>threshold?threshold:value*/
    CV_THRESH_TOZERO=3,/*value=value>threshold?value:0*/
    CV_THRESH_TOZERO_INV=4,/*value=value>threshold?0:value*/
    CV_THRESH_MASK=7,
    CV_THRESH_OTSU=8/*useOtsualgorithmtochoosetheoptimalthresholdvalue;
    combinetheflagwithoneoftheaboveCV_THRESH_*values*/
};
//!typeofthethresholdoperation
enum{
    THRESH_BINARY=CV_THRESH_BINARY,
    THRESH_BINARY_INV=CV_THRESH_BINARY_INV,
    THRESH_TRUNC=CV_THRESH_TRUNC,
    THRESH_TOZERO=CV_THRESH_TOZERO,
    THRESH_TOZERO_INV=CV_THRESH_TOZERO_INV,
    THRESH_MASK=CV_THRESH_MASK,
    THRESH_OTSU=CV_THRESH_OTSU
};


   T(x,y)为图像中每一个像素的阈值。可以看作是一种电路上的滤波方式,第一种为比较器。OTSU算法(大津法或最大类间方差法)。图像直观理解:



  
ADAPTIVE_THRESH_MEAN_C
方法:blockSize块的均值减去C作为阈值T(x,y)。

  
ADAPTIVE_THRESH_GAUSSIAN_C
方法:加权平均值(默认为标准差)减去C作为阈值T(x,y)。

1.2 全局固定阈值函数说明

C++:

double threshold(InputArray src, OutputArray dst, double thresh, double maxval, int type)

C:

double cvThreshold(const CvArr* src, CvArr* dst, double threshold, double max_value, int threshold_type)

参数说明:

  maxval:二值最大值

  thresh:固定阈值大小

  type:阈值计算方式类型,同上。

2 实例

2.1 自定义实现简单的二值化

  自己实现简单的二值化功能(类似固定阈值方式,非0即255)。可以读取彩色图像,因为距离计算是求取了三个通道的,这一点不同于OpenCV提供的二值化函数必须为单通道图像。原理简单,就是通过对每个像素跟设定的固定值进行距离比较,在设定的距离范围内就将其设置为二值的某个值。

OpenCV动态库加入到工程配置文件中

[code]xxx.pro


[code]INCLUDEPATH += E:\OpenCV2_4_11_MinGW\include
LIBS+=-LE:\\OpenCV2_4_11_MinGW\\bin\
    libopencv_core2411\
    libopencv_highgui2411\
    libopencv_imgproc2411\
    libopencv_features2d2411\
    libopencv_calib3d2411\


计算当前像素点与设定的目标像素点的距离

  计算方法有很多,常见的有欧几里得距离、曼哈顿距离(街区距离)、闵科夫斯基距离等。这里用的是曼哈顿距离计算公式。

[code]int ColorDetector::getDistance(const Vec3b& color) const
{
    return abs(color[0] - target[0]) +
            abs(color[1] - target[1]) +
            abs(color[2] - target[2]);
}


对图像进行二值化处理

  二值画处理的原理就是计算当前像素与设定的像素的距离是否在我们设定的阈值距离
minDist
之内,是则将像素点置为255,否则置为0。

[code]Mat ColorDetector::process(const Mat image)
{
    int count = 0;
    //按需重新分配二值图像
    //与输入图像的尺寸相同,但是只有一个通道(二值化)
    result.create(image.rows,image.cols,CV_8U);

    Mat_<Vec3b>::const_iterator it =
            image.begin<Vec3b>();
    Mat_<Vec3b>::const_iterator itend =
            image.end<Vec3b>();
    Mat_<uchar>::iterator itout =
            result.begin<uchar>();
    for(;it!= itend;++it,++itout){
        count++;
        if(getDistance(*it) < minDist){
            *itout = 255;
        }
        else {
            *itout = 0;
        }
    }    
    return result;
}


最后得到二值化结果

  二值化的结果要很好的话是跟设定的像素点的BGR值和阈值距离有关的。



2.2 基于OpenCV库函数实现二值化

  基于库函数就比较容易了。

全局固定阈值关键代码:

[code]void MainWindow::on_pushButton_2_clicked()
{
    if(!image.data)return ;
    Mat result;
    //创建同原始图像等大小的图像空间
    result.create(image.rows,image.cols,CV_8U);
    //二值化
    //CV_THRESH_OTSU参数自动生成阈值,跟第三个参数也就没有关系了。
    threshold(image,result,0,255,  CV_THRESH_BINARY | CV_THRESH_OTSU);
    //获取处理后的结果
    if(!result.data){
        return ;
    }
    //转为QImage格式。注意这不需要用cvtColor()函数来转换格式,因为process中就是二值化图像了,即只有一个通道。
    QImage img = QImage((const unsigned char*)(result.data),
                    result.cols,result.rows,result.cols*result.channels(),QImage::Format_Grayscale8);
    //显示到label上
    ui->label_2->setPixmap(QPixmap::fromImage(img));
    ui->label_2->resize(ui->label_2->pixmap()->size());
}


局部自适应阈值关键代码:

[code]void MainWindow::on_pushButton_3_clicked()
{
    if(!image.data)return ;
    Mat result;
    //创建同原始图像等大小的图像空间
    result.create(image.rows,image.cols,CV_8U);
    //自适应二值化
    adaptiveThreshold(image,result,255,CV_ADAPTIVE_THRESH_GAUSSIAN_C,CV_THRESH_BINARY,3,5);
    //获取处理后的结果
    if(!result.data){
        return ;
    }
    //转为QImage格式。注意这不需要用cvtColor()函数来转换格式,因为process中就是二值化图像了,即只有一个通道。
    QImage img = QImage((const unsigned char*)(result.data),
                    result.cols,result.rows,result.cols*result.channels(),QImage::Format_Grayscale8);
    //显示到label上
    ui->label_3->setPixmap(QPixmap::fromImage(img));
    ui->label_3->resize(ui->label_3->pixmap()->size());
}


结果:



  当然,我们还可以多测试下不同的参数会有什么影响。

测试源码下载:

http://download.csdn.net/download/freeape/9378465

参考资料:

http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html?highlight=cvadaptivethreshold

http://blog.csdn.net/tyf122/article/details/8738156
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: