当前位置:   article > 正文

cv::阈值分割OTUS原理+代码_opencv otsu分割算法 源代码 c++

opencv otsu分割算法 源代码 c++

opencv库的阈值分割分为全局分割和局部分割

全局分割:普通分割

  1. ret1,th1 = cv2.threshold(img,127, 255, cv2.THRESH_BINARY)
  2. #127为阈值
  3. #cv2.THRESH_BINARY |cv2.THRESH_BINARY_INV | cv2.THRESH_TRUNC
  4. |cv2.THRESH_TOZERO|cv2.THRESH_TOZERO_INV

局部分割:自适应分割,阈值自计算

  1. th2=cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)
  2. #阈值变为
  3. #均值:cv2.ADAPTIVE_THRESH_MEAN_C,
  4. #高斯加权:cv2.ADAPTIVE_THRESH_GAUSSIAN_C
  5. #窗口大小:11
  6. #c:均值-常数

特殊:OTUS 大津法,最大类间方差

ret2,th2 = cv2.threshold(img,0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

原理:

使用于双峰图像,将灰度直方图分为两部分,使得两部分类间方差最大,试了一下两部分类内方差最小也行,效果差不多,opencv的api用的是最大类间方差.

步骤:

  1. 灰度图片计算灰度直方图,并归一化

  1. 类间方差计算:其实就是求灰度的方差

  1. 假设当前灰度阈值为i,将[0,256]分为h1=[0,i-1]和h2=[i,256]两部分

  1. 求每一部分的灰度个数s = sum(h[i]),求s1,s2

  1. 求每一部分的灰度均值,mean = sum(h1[i]*i)/s求m1,m2,mg(总积分)

  1. 求每一个类间的方差,[s1*(m1-mg)*(m1-mg)+s2*(m2-mg)*(m2-mg)]/(s1+s2)

d.(1),类内方差v = sum((i-m)*(i-m)*h[i]/s),最小类内方差也行

  1. i 取值[0,256],求使得类间方差最大的i就是阈值

  1. import cv2
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. img = cv2.imread("otsu.jpg",0)
  5. hist = cv2.calcHist([img],[0],None,[256],[0,256])
  6. histnorm = (hist-hist.min())/(hist.max()-hist.min())
  7. bins = np.arange(256)
  8. # plt.plot(histnorm)
  9. # plt.xlim([0,256])
  10. # plt.show()
  11. fnmin = 99999
  12. tmp = 0
  13. fnmax = 0
  14. tm = 0
  15. p = hist/sum(hist)
  16. histnorm = np.squeeze(histnorm)
  17. for i in range(1,256):
  18. s1 = np.sum(histnorm[:i])
  19. s2 = np.sum(histnorm[i:])
  20. q1 = histnorm[i:]*bins[i:]
  21. m1 = np.sum(histnorm[:i] * bins[:i])/s1
  22. m2 = np.sum(histnorm[i:] * bins[i:])/s2
  23. mg = np.sum(histnorm* bins)/(s1+s2)
  24.    
  25.     #最大类间方差
  26. fm = (s1*(m1-mg)*(m1-mg)+ s2*(m2-mg)*(m2-mg))/(s1+s2)
  27. if fm>fnmax:
  28. fnmax = fm
  29. tm = i
  30.     #最小类内方差
  31. v1 = np.sum((bins[:i] - m1)*(bins[:i] - m1)*(histnorm[:i])/s1)
  32. v2 = np.sum((bins[i:] - m2)*(bins[i:] - m2)*(histnorm[i:])/s2)
  33. fn = v1+v2
  34. if fn<fnmin:
  35. fnmin = fn
  36. tmp = i
  37. ret1,th1 = cv2.threshold(img,tm, 255, cv2.THRESH_BINARY)
  38. print(tm,ret1)
  39. ret2,th2 = cv2.threshold(img,tmp, 255, cv2.THRESH_BINARY)
  40. print(tmp,ret2)
  41. ret3,th3 = cv2.threshold(img,0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
  42. print(ret3)
  43. cv2.imshow("th1",th1)
  44. cv2.imshow("th2",th2)
  45. cv2.imshow("th3",th3)
  46. cv2.waitKey(0)

图片:从别博客里面保存的

结果:最大类间方差和cv2.THRESH_OTSU计算出来的阈值一样,最小类间方差要小一点

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/481166
推荐阅读
相关标签
  

闽ICP备14008679号