OpenCV每日函数 杂项图像转换模块 (6) threshold函数

一、概述

        对每个数组元素应用固定级别的阈值。图像的阈值化(有些场合也称二值化)是图像分割的一种,一般用于将感兴趣区域从背景中区分出来,处理过程就是将每个像素和阈值进行对比,分离出来需要的像素设置为特定白色的255或者黑色的0,具体看实际的使用需求而定。

        该函数将固定级别的阈值应用于多通道阵列。 该函数通常用于从灰度图像中获取双层(二进制)图像(比较也可用于此目的)或用于去除噪声,即过滤掉值过小或过大的像素。 该函数支持几种类型的阈值。 它们由类型参数确定。        

        此外,特殊值 THRESH_OTSU 或 THRESH_TRIANGLE 可以与上述值之一组合。 在这些情况下,该函数使用 Otsu 或 Triangle 算法确定最佳阈值,并使用它代替指定的阈值。

        目前,Otsu 和 Triangle 方法仅适用于 8 位单通道图像。

二、adaptiveThreshold函数

1、函数原型

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

2、参数详解

src 输入数组(多通道、8 位或 32 位浮点)。
dst 与 src 具有相同大小和类型以及相同通道数的输出数组。
thresh 阈值。
maxval 用于 THRESH_BINARY 和 THRESH_BINARY_INV 阈值类型的最大值。
type 阈值类型(请参阅阈值类型)。

         阈值类型介绍如下表

标志 标志值 dst(x,y)取值 条件 备注
cv2.THRESH_BINARY 0 maxval  if src(x,y)>thresh; 取值只有2种,真正意义的“二值化”
0 otherwise
cv2.THRESH_BINARY_INV 1 0 if src(x,y)>thresh;
maxval  otherwise
cv2.THRESH_TRUNC 2 threshold if src(x,y)>thresh; 最后的取值有多种
src(x,y) otherwise
cv2.THRESH_TOZERO 3 src(x,y) if src(x,y)>thresh;
0 otherwise
cv2.THRESH_TOZERO_INV 4 0 if src(x,y)>thresh;
src(x,y) otherwise
cv2.THRESH_MASK 7 / /
cv2.THRESH_OTSU 8 / 标志位,使用大津法选择最佳阈值
cv2.THRESH_TRIANGLE 16 / 标志位,使用三角算法选择最佳阈值

三、OpenCV源码

1、源码路径

opencv\modules\imgproc\src\thresh.cpp

2、源码代码

double cv::threshold( InputArray _src, OutputArray _dst, double thresh, double maxval, int type )
{
    CV_INSTRUMENT_REGION();

    CV_OCL_RUN_(_src.dims() <= 2 && _dst.isUMat(),
                ocl_threshold(_src, _dst, thresh, maxval, type), thresh)

    Mat src = _src.getMat();
    int automatic_thresh = (type & ~CV_THRESH_MASK);
    type &= THRESH_MASK;

    CV_Assert( automatic_thresh != (CV_THRESH_OTSU | CV_THRESH_TRIANGLE) );
    if( automatic_thresh == CV_THRESH_OTSU )
    {
        int src_type = src.type();
        CV_CheckType(src_type, src_type == CV_8UC1 || src_type == CV_16UC1, "THRESH_OTSU mode");
        thresh = src.type() == CV_8UC1 ? getThreshVal_Otsu_8u( src )
                                       : getThreshVal_Otsu_16u( src );
    }
    else if( automatic_thresh == CV_THRESH_TRIANGLE )
    {
        CV_Assert( src.type() == CV_8UC1 );
        thresh = getThreshVal_Triangle_8u( src );
    }

    _dst.create( src.size(), src.type() );
    Mat dst = _dst.getMat();

    if( src.depth() == CV_8U )
    {
        int ithresh = cvFloor(thresh);
        thresh = ithresh;
        int imaxval = cvRound(maxval);
        if( type == THRESH_TRUNC )
            imaxval = ithresh;
        imaxval = saturate_cast<uchar>(imaxval);

        if( ithresh < 0 || ithresh >= 255 )
        {
            if( type == THRESH_BINARY || type == THRESH_BINARY_INV ||
                ((type == THRESH_TRUNC || type == THRESH_TOZERO_INV) && ithresh < 0) ||
                (type == THRESH_TOZERO && ithresh >= 255) )
            {
                int v = type == THRESH_BINARY ? (ithresh >= 255 ? 0 : imaxval) :
                        type == THRESH_BINARY_INV ? (ithresh >= 255 ? imaxval : 0) :
                        /*type == THRESH_TRUNC ? imaxval :*/ 0;
                dst.setTo(v);
            }
            else
                src.copyTo(dst);
            return thresh;
        }

       CV_OVX_RUN(!ovx::skipSmallImages<VX_KERNEL_THRESHOLD>(src.cols, src.rows),
                  openvx_threshold(src, dst, ithresh, imaxval, type), (double)ithresh)

        thresh = ithresh;
        maxval = imaxval;
    }
    else if( src.depth() == CV_16S )
    {
        int ithresh = cvFloor(thresh);
        thresh = ithresh;
        int imaxval = cvRound(maxval);
        if( type == THRESH_TRUNC )
            imaxval = ithresh;
        imaxval = saturate_cast<short>(imaxval);

        if( ithresh < SHRT_MIN || ithresh >= SHRT_MAX )
        {
            if( type == THRESH_BINARY || type == THRESH_BINARY_INV ||
               ((type == THRESH_TRUNC || type == THRESH_TOZERO_INV) && ithresh < SHRT_MIN) ||
               (type == THRESH_TOZERO && ithresh >= SHRT_MAX) )
            {
                int v = type == THRESH_BINARY ? (ithresh >= SHRT_MAX ? 0 : imaxval) :
                type == THRESH_BINARY_INV ? (ithresh >= SHRT_MAX ? imaxval : 0) :
                /*type == THRESH_TRUNC ? imaxval :*/ 0;
                dst.setTo(v);
            }
            else
                src.copyTo(dst);
            return thresh;
        }
        thresh = ithresh;
        maxval = imaxval;
    }
    else if (src.depth() == CV_16U )
    {
        int ithresh = cvFloor(thresh);
        thresh = ithresh;
        int imaxval = cvRound(maxval);
        if (type == THRESH_TRUNC)
            imaxval = ithresh;
        imaxval = saturate_cast<ushort>(imaxval);

        int ushrt_min = 0;
        if (ithresh < ushrt_min || ithresh >= (int)USHRT_MAX)
        {
            if (type == THRESH_BINARY || type == THRESH_BINARY_INV ||
               ((type == THRESH_TRUNC || type == THRESH_TOZERO_INV) && ithresh < ushrt_min) ||
               (type == THRESH_TOZERO && ithresh >= (int)USHRT_MAX))
            {
                int v = type == THRESH_BINARY ? (ithresh >= (int)USHRT_MAX ? 0 : imaxval) :
                        type == THRESH_BINARY_INV ? (ithresh >= (int)USHRT_MAX ? imaxval : 0) :
                  /*type == THRESH_TRUNC ? imaxval :*/ 0;
                dst.setTo(v);
            }
            else
                src.copyTo(dst);
            return thresh;
        }
        thresh = ithresh;
        maxval = imaxval;
    }
    else if( src.depth() == CV_32F )
        ;
    else if( src.depth() == CV_64F )
        ;
    else
        CV_Error( CV_StsUnsupportedFormat, "" );

    parallel_for_(Range(0, dst.rows),
                  ThresholdRunner(src, dst, thresh, maxval, type),
                  dst.total()/(double)(1<<16));
    return thresh;
}

四、效果图像示例

原图
Binary
Otsu

猜你喜欢

转载自blog.csdn.net/bashendixie5/article/details/125274031