阈值可以被视作最简单的图像分割方法属于像素级分割。设定阈值后图像中每个像素预期比较选择保留或剔除,从而达到所需要的部分图像。
阈值是对灰度图像进行操作得到的二值图像(二值图像中所有的像素只能从0和1这两个值中取)
阈值函数有两种:
1、固定阈值:Threshold()函数
double cv::threshold( InputArray _src, OutputArray _dst, double thresh, double maxval, int type )
第一个参数:输入图像数组
第二个参数:输出图像数组
第三个参数:设定阈值
第四个参数:设定的最大值
第五个参数:设置取阈值的方法
double cv::threshold( InputArray _src, OutputArray _dst, double thresh, double maxval, int type )
{
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 )
{
CV_Assert( src.type() == CV_8UC1 );
thresh = getThreshVal_Otsu_8u( 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;
}
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_32F )
;
else
CV_Error( CV_StsUnsupportedFormat, "" );
parallel_for_(Range(0, dst.rows),
ThresholdRunner(src, dst, thresh, maxval, type),
dst.total()/(double)(1<<16));
return thresh;
}
2、自适应阈值:adaptiveThreshold()函数
void cv::adaptiveThreshold( InputArray _src, OutputArray _dst, double maxValue,
int method, int type, int blockSize, double delta )
第一个参数:输入图像数组
第二个参数:输出图像数组
第三个参数:设定的最大值
第四个参数:算法
第五个参数:阈值类型 THRESH_BINARY,THRESH_BINARY_INV
第六个参数:一个像素的领域尺寸
第七个参数:减去平均或加权平均值后的平均值
void cv::adaptiveThreshold( InputArray _src, OutputArray _dst, double maxValue, int method, int type, int blockSize, double delta ) { Mat src = _src.getMat(); CV_Assert( src.type() == CV_8UC1 ); CV_Assert( blockSize % 2 == 1 && blockSize > 1 ); Size size = src.size(); _dst.create( size, src.type() ); Mat dst = _dst.getMat(); if( maxValue < 0 ) { dst = Scalar(0); return; } Mat mean; if( src.data != dst.data ) mean = dst; if( method == ADAPTIVE_THRESH_MEAN_C ) boxFilter( src, mean, src.type(), Size(blockSize, blockSize), Point(-1,-1), true, BORDER_REPLICATE ); else if( method == ADAPTIVE_THRESH_GAUSSIAN_C ) GaussianBlur( src, mean, Size(blockSize, blockSize), 0, 0, BORDER_REPLICATE ); else CV_Error( CV_StsBadFlag, "Unknown/unsupported adaptive threshold method" ); int i, j; uchar imaxval = saturate_cast<uchar>(maxValue); int idelta = type == THRESH_BINARY ? cvCeil(delta) : cvFloor(delta); uchar tab[768]; if( type == CV_THRESH_BINARY ) for( i = 0; i < 768; i++ ) tab[i] = (uchar)(i - 255 > -idelta ? imaxval : 0); else if( type == CV_THRESH_BINARY_INV ) for( i = 0; i < 768; i++ ) tab[i] = (uchar)(i - 255 <= -idelta ? imaxval : 0); else CV_Error( CV_StsBadFlag, "Unknown/unsupported threshold type" ); if( src.isContinuous() && mean.isContinuous() && dst.isContinuous() ) { size.width *= size.height; size.height = 1; } for( i = 0; i < size.height; i++ ) { const uchar* sdata = src.ptr(i); const uchar* mdata = mean.ptr(i); uchar* ddata = dst.ptr(i); for( j = 0; j < size.width; j++ ) ddata[j] = tab[sdata[j] - mdata[j] + 255]; } }