【OpenCV3】threshold()函数详解
threshold()函数源码
double cv::threshold( InputArray _src, OutputArray _dst, double thresh, double maxval, int type ) {
// 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, /**< use Otsu algorithm to choose the optimal threshold value;
// combine the flag with one of the above CV_THRESH_* values */
// CV_THRESH_TRIANGLE =16 /**< use Triangle algorithm to choose the optimal threshold value;
// combine the flag with one of the above CV_THRESH_* values, but not
// with CV_THRESH_OTSU */
//};
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);// 排除前五种可能,判断是否是CV_THRESH_OTSU \ CV_THRESH_TRIANGLE(8,16) type &= THRESH_MASK; // THRESH_MASK(7) 得到当前二值化的类型(前五种),0,1,2,3,4 CV_Assert( automatic_thresh != (CV_THRESH_OTSU | CV_THRESH_TRIANGLE) ); if( automatic_thresh == CV_THRESH_OTSU )// 判断是否是CV_THRESH_OTSU(8) {
// 使用算法选择最佳阈值;将标志与上述cv_thresh_*值之一相结合 计算最佳阈值 CV_Assert( src.type() == CV_8UC1 ); thresh = getThreshVal_Otsu_8u( src ); } else if( automatic_thresh == CV_THRESH_TRIANGLE )// 判断是否是CV_THRESH_TRIANGLE(16) {
// 使用三角算法选择最优阈值;将标志与上述cv_thresh_*值之一组合,但不使用cv_thresh_otsu 计算最佳阈值 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 )// 如果原始图像的深度为8位无符号 { int ithresh = cvFloor(thresh);// 将thresh向下取整 thresh = ithresh; int imaxval = cvRound(maxval); // 将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 )// 如果原始图像的深度为16位short类型 { 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 )// 如果原始图像的深度为16位无符号 { 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 )// 如果原始图像的深度为32位浮点型 ; else if( src.depth() == CV_64F )// 如果原始图像的深度为64位浮点型 ; else CV_Error( CV_StsUnsupportedFormat, "" ); // 不能识别的图像格式 parallel_for_(Range(0, dst.rows), ThresholdRunner(src, dst, thresh, maxval, type), dst.total()/(double)(1<<16)); return thresh; }
threshold()函数二值化的方法(types)/** Threshold types */
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, /**< use Otsu algorithm to choose the optimal threshold value; combine the flag with one of the above CV_THRESH_* values
使用算法选择最佳阈值;将标志与上述cv_thresh_*值之一相结合*/ CV_THRESH_TRIANGLE =16 /**< use Triangle algorithm to choose the optimal threshold value; combine the flag with one of the above CV_THRESH_* values, but not with CV_THRESH_OTSU
使用三角算法选择最优阈值;将标志与上述cv_thresh_*值之一组合,但不使用cv_thresh_otsu*/ };