【OPENCV】Otsu 阈值分割算法

原理

Otsu 的原理是最小化类间方差,从像素分布直方图的角度来看就是在像素分布直方图的峰值之间找一个点,使得两个类之间的方差最大,类内方差最小。


Screen Shot 2019-01-28 at 12.02.02 PM.png
image.png

这个算法可以用于OCR, 车牌分割等等

实现

  1. 这个实现是遍历每一个分割值,然后求解全局最优解,具体到工程应用也有一些优化算法。
img = cv.imread('noisy2.png',0)
blur = cv.GaussianBlur(img,(5,5),0)
# find normalized_histogram, and its cumulative distribution function
hist = cv.calcHist([blur],[0],None,[256],[0,256])
hist_norm = hist.ravel()/hist.max()
Q = hist_norm.cumsum()
bins = np.arange(256)
fn_min = np.inf
thresh = -1
for i in range(1,256):
    p1,p2 = np.hsplit(hist_norm,[i]) # probabilities
    q1,q2 = Q[i],Q[255]-Q[i] # cum sum of classes
    b1,b2 = np.hsplit(bins,[i]) # weights
    # finding means and variances
    m1,m2 = np.sum(p1*b1)/q1, np.sum(p2*b2)/q2
    v1,v2 = np.sum(((b1-m1)**2)*p1)/q1,np.sum(((b2-m2)**2)*p2)/q2
    # calculates the minimization function
    fn = v1*q1 + v2*q2
    if fn < fn_min:
        fn_min = fn
        thresh = i
# find otsu's threshold value with OpenCV function
ret, otsu = cv.threshold(blur,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
print( "{} {}".format(thresh,ret) )

Reference

  1. https://www.hindawi.com/journals/mse/2014/794574/
  2. https://www.hindawi.com/journals/mse/2014/794574/
  3. https://en.wikipedia.org/wiki/Otsu%27s_method
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容