图像二值化是一个很基础的操作,一个好的二值化算法,往往如神来之笔,解决一些棘手的算法问题。它也是最基本的图像分割算法。
应用领域比较广泛:比如在 二维码识别、OCR字符识别、以及各种 基于轮廓、形状 等搜索算法,都是先基于二值化算法,然后分析形状和识别。
二值化主要分为2个种类:
- 局部二值化算法:自适应高斯、自适应均值、NiblackNickSauvolaWolf 等等
- 单阈值二值化(全局二值化)算法:OTSU、KMeans、Triangle、最小熵、均值、分位数等等。
- 多阈值二值化算法:muti-OTSU, 极大稳定区域,以及一些 分割算法。
我目前集成了一些 二值化算法,各有不同的效果,根据应用场景,使用效果最好的算法。
大部分算法,都是 OpenCV内置的,我只是改动了一下接口,然后更好的集成到我的测试平台中。
比如:最大类间方差算法(OTSU)
KLIB_DECL double hist_otsu(const Mat& _src) {Size size = _src.size();int step = (int)_src.step;if (_src.isContinuous()){size.width *= size.height;size.height = 1;step = size.width;}const int N = 256;int i, j, h[N] = { 0 };for (i = 0; i < size.height; i++){const uchar* src = _src.ptr() + step*i;j = 0;for (; j < size.width; j++)h[src[j]]++;}double mu = 0, scale = 1. / (size.width*size.height);for (i = 0; i < N; i++)mu += i*(double)h[i];mu *= scale;double mu1 = 0, q1 = 0;double max_sigma = 0, max_val = 0;for (i = 0; i < N; i++){double p_i, q2, mu2, sigma;p_i = h[i] * scale;mu1 *= q1;q1 += p_i;q2 = 1. - q1;if (std::min(q1, q2) < FLT_EPSILON || std::max(q1, q2) > 1. - FLT_EPSILON)continue;mu1 = (mu1 + i*p_i) / q1;mu2 = (mu - q1*mu1) / q2;sigma = q1*q2*(mu1 - mu2)*(mu1 - mu2);if (sigma > max_sigma){max_sigma = sigma;max_val = i;}}return max_val;}
这段代码,就是我从 OpenCV源码库里抄录下来的,主要是我想提供 灵活阈值,增加一个系数。
其他算法类似,我都进行了一些集成和封装。
测试 全局二值化算法:
显示的效果如下:
其中 全局阈值
KMeans 115
OTSU 117
分位数 129
极大值比例 196
均值 124
全局最小熵 101
三角值 115.
其中算法耗时,都比较短:
[KAlgImgConvertBGR2Gray] 执行时间[0.6386(ms)][KAlgImgBinKmens] 执行时间[0.3835(ms)][KAlgImgBinOTSU] 执行时间[0.2565(ms)][KAlgImgBinPtile] 执行时间[0.2422(ms)][KAlgImgBinMaxPercent] 执行时间[0.3607(ms)][KAlgImgBinMean] 执行时间[0.1119(ms)][KAlgImgBinEntropy] 执行时间[0.2979(ms)][KAlgImgBinTriangle] 执行时间[0.2244(ms)]
局部二值化算法测试
可以明显感受到 有些局部二值化 和 边缘检测 效果类似。
其中算法耗时:
[KAlgImgBinNiblack] 执行时间[4.2036(ms)][KAlgImgBinNick] 执行时间[4.7597(ms)][KAlgImgBinSauvola] 执行时间[4.1442(ms)][KAlgImgBinWellner] 执行时间[3.126(ms)][KAlgImgBinWolf] 执行时间[6.3202(ms)][KAlgImgBinHysteresisAuto] 执行时间[13.1141(ms)][KAlgImgBinAdaptGauss] 执行时间[0.9003(ms)][KAlgImgBinAdaptMean] 执行时间[0.3454(ms)]
这些二值化算法,各有特色,在某些特殊场景下,是很有意义的。
先了解算法,然后测试算法,最后在实际中使用算法,并改进算法。
图像处理,是一个长期积累的过程。大家如果感兴趣,我继续分享学过的图像处理算法。