一、概述
对每个数组元素应用固定级别的阈值。图像的阈值化(有些场合也称二值化)是图像分割的一种,一般用于将感兴趣区域从背景中区分出来,处理过程就是将每个像素和阈值进行对比,分离出来需要的像素设置为特定白色的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;
}