【图像识别】初探数字识别-水表(2)

在上一个博文中,高斯滤波后对灰度值用canny检测边缘。调整canny参数,检测边缘。下面换一种方式,即先二值化后,再findContours检测检测轮廓。

图像二值化

cv2.threshold(), cv2.adaptiveThreshold(), Otsu’s thresholding.

简单阈值划分

cv2.threshold(InputArray src, int threshold, int maxValue, int thresholdType)

函数返回两个量,retVal和阈值转换后的图像thresholded image。其中,第一个值retVal是在使用Ostu时,返回Ostu最优阈值;否则,则返回自己设置的阈值,例如127。

  • scr 输入图像
  • thresholf 分割阈值
  • maxValue 超过阈值后设定为最大值
  • thresholdType 阈值类型,一共有5种类型表示二值化的图片处理方式。cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV是最常见的两种,前者表示大于阈值的取最大值(255),小于阈值的取最小值0;后者,小于阈值的取最大值(255),大于阈值的取最小值0。

自适应阈值划分

cv2.adaptiveThreshold((InputArray src, OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C)

  • src:输入图
  • dst:输出图,大小与原图一致
  • maxValue:最大值,同上
  • adaptiveMethod:
    自适应方法,分为局部均值法CV_ADAPTIVE_THRESH_MEAN_C和高斯均值法CV_ADAPTIVE_THRESH_GAUSSIAN_C
  • thresholdType:二值化类型,只有两种:cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV。
  • blockSize:均值计算区域,只能选奇数3,5,7……。
  • C:常数,区域均值后减去该常数。

其中,与全局均值作为阈值不同的,自适应法,是采用局部均值的方法来处理每个小区域。这样做可以排除,光线条件差异引起的图片整体明暗度的差异。

具体的,局部均值法CV_ADAPTIVE_THRESH_MEAN_C,计算blockSize * blockSize区域内的均值,减去常数C,作为该区域阈值;高斯均值法CV_ADAPTIVE_THRESH_GAUSSIAN_C ,计算blockSize * blockSize区域内的高斯均值(Gaussian Blur),减去常数C。
水表对比
左上是全局threshold=127划分的效果,光线条件不同,由于反光等使得阈值划分效果很差。右上是局部均值法;左下是高斯均值法,都采用了blockSize=11,差异并不明显。右下,高斯均值法,阈值类型为cv2.THRESH_BINARY_INV。

Otsu’s Binarization

现在假设,我们有了二值化分割的图像,那么问题是,如何判定分割的好坏呢?现考虑一个双峰图像,对于有明显双峰的图像,可以设定阈值为在两个峰之间的某个值,Otsu就是这样一种方法。Ostu的原理,寻找一个阈值,使得类间方差最小化。他为双峰图像计算阈值,然而对非双峰图像不太准确。对于一个双峰图像,用Ostu来选择阈值,可以使得前景,背景区分明显。

运用Ostu计算处理图像的方法,cv2.THRESH_OTSU
ret,th = cv2.threshold(img,0,255,cv2.THRESH_BINARY + cv2.THRESH_OTSU)

官方文档中还有关于Ostu的实现。

参考文献:

http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html
http://monkeycoding.com/?p=603
https://blog.csdn.net/wenhao_ir/article/details/51565517
https://docs.opencv.org/3.1.0/d7/d4d/tutorial_py_thresholding.html

猜你喜欢

转载自blog.csdn.net/zeo_m/article/details/82286798