0 引
图像阈值,即图像的分割基准,基于此可完成图像的二值化。图像二值化可用于OCR成图像的分割(也是最为简单的一种)。这种分割是基于图像像素值级别的差异,且一般的对象是灰度图像。
1 图像二值化
如上所述,图像阈值的进一步处理就是二值化,二值化包含但不限于“大于阈值为255,小于阈值为0”的处理模式。具体如下所示。其实个人理解这些方法只是提供了一种在处理图像时的思路,并不一定要死记住方法的名字。
为了更好解释,假设待处理图像的直方图如下。
1.1二进制阈值化
1.2反二进制阈值化
1.3截段阈值化
1.4阈值化0
1.5 反阈值化0
2 OpenCV API
double cvThreshold( const void* srcarr, void*dstarr, double thresh, double maxval, int type );
srcarr源数组,dstarr为目标数组,thresh为阈值,maxval为欲设最大值,type为阈值处理的类型,有如下几种:
CV_THRESH_BINARY,表示dsti=(srci>T)?M:0。
CV_THRESH_BINARY_INV,表示dsti=(srci>T)?0:M。
CV_THRESH_TRUNC,表示dsti=(srci>T)?M:srci。
CV_THRESH_TOZERO_INV,表示dsti=(srci>T)?0:srci。
CV_THRESH_TOZERO,表示dsti=(srci>T)?srci:0。
另外,type值还有两个选择,可以指定thresh值,此时传入参数thresh不会起作用。
CV_THRESH_OTSU 使用大津法选择最优的thresh;
CV_THRESH_TRIANGLE 使用三角法确定thresh;
3 阈值的选择
上文中介绍API的同时,也介绍了两种算法确定的thresh:大津法和三角法。
3.1 大津法
大津法又称为最大类间方差法。优点计算简单且不受亮度和对比度的影响。算法的基本思想是找到的阈值满足low(即低于选择的阈值)部分与high(即高于阈值部分)的类方差是最大的。
类方差是一个新概念,在正式解释之前先补充另外一个在算法中使用的概念即前景与后景,前景与后景是根据阈值区分的,即上述的low部分与high部分,至于哪个是前景哪个是后景,需要根据图像的特征确定(例如黑背景白字的图片,那么前景就是指high部分的白字)。
假设图像背景是黑色时,且分辨率为M*N,阈值为T,记小于T的像素个数为N0且其平均灰度为μ0,大于的个数记为N1且其平均灰度为μ1,则类方差g的计算公式如下。
ω0=N0/ M×N (1)
ω1=N1/ M×N (2)
N0+N1=M×N (3)
ω0+ω1=1 (4)
μ=ω0*μ0+ω1*μ1 (5)
g=ω0(μ0-μ)^2+ω1(μ1-μ)^2 (6)
将式(5)代入式(6),得到等价公式:
g=ω0ω1(μ0-μ1)^2 (7) 这就是类间方差
而OTSU算法则是找到使类间方差最大的像素值,作为阈值。代码演示如下。
int GetOTUSThresh(cv::Matimg) { assert(img.channels() == 1); int gray_cnt[256] = { 0 }; // stastics for (inti = 0; i < img.rows; i++) { for (intj = 0; j < img.cols; j++) { gray_cnt[img.at<unsignedchar>(i, j)]++; } } // otus double max_delta = 0.0; double delta; int thresh; double weight_l, weight_h; double u_l, u_h, u; int cnt_l, cnt_h; for (inti = 0; i < 256; i++) { cnt_l = cnt_h = 0; u_l = u_h = 0.0; for (intj = 0; j < 256; j++) { if (j <i) { cnt_l += gray_cnt[j]; u_l += j * gray_cnt[j]; } else { cnt_h += gray_cnt[j]; u_h += j*gray_cnt[j]; } } u_l = u_l / cnt_l; u_h = u_h / cnt_h; weight_l = (double)cnt_l / (img.rows*img.cols); weight_h = 1 - weight_l; delta = weight_h*weight_l*(u_h -u_l)*(u_h - u_l); if (delta >max_delta) { max_delta =delta; thresh = i; } } return thresh; } |
3.2 三角法
4 自适应图像阈值
所谓自适应,即将图像分为若干个大小相同的block,每个block的阈值会根据周围局部像素值动态改变待比较的阈值。这样做的好处是亮处较亮的地方二值化阈值通常较高,而亮度较低的则更低,对噪声不会那么敏感。具体的分为两种方法,局部邻域块的均值和局部邻域块的高斯加权和。事实上对于成像效果不好的图,往往自适应阈值法更加适用。
OPENCV中的API
void adaptiveThreshold(InputArray src,OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double param)
参数 adaptiveMethod:采用的算法两个取值ADAPTIVE_THRESH_MEAN_C 和 ADAPTIVE_THRESH_GAUSSIAN_C分别对应局部邻域块的均值和局部邻域块的高斯加权和。
参数param:引入的微调参数,最终的阈值等于通过adpativeMethod得到的值与param的差值,也可以负数。
5 参考
http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/threshold/threshold.html