赞
踩
opencv库的阈值分割分为全局分割和局部分割
全局分割:普通分割
- ret1,th1 = cv2.threshold(img,127, 255, cv2.THRESH_BINARY)
- #127为阈值
- #cv2.THRESH_BINARY |cv2.THRESH_BINARY_INV | cv2.THRESH_TRUNC
- |cv2.THRESH_TOZERO|cv2.THRESH_TOZERO_INV
局部分割:自适应分割,阈值自计算
- th2=cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)
- #阈值变为
- #均值:cv2.ADAPTIVE_THRESH_MEAN_C,
- #高斯加权:cv2.ADAPTIVE_THRESH_GAUSSIAN_C
- #窗口大小:11
- #c:均值-常数
特殊:OTUS 大津法,最大类间方差
ret2,th2 = cv2.threshold(img,0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
原理:
使用于双峰图像,将灰度直方图分为两部分,使得两部分类间方差最大,试了一下两部分类内方差最小也行,效果差不多,opencv的api用的是最大类间方差.
步骤:
灰度图片计算灰度直方图,并归一化
类间方差计算:其实就是求灰度的方差
假设当前灰度阈值为i,将[0,256]分为h1=[0,i-1]和h2=[i,256]两部分
求每一部分的灰度个数s = sum(h[i]),求s1,s2
求每一部分的灰度均值,mean = sum(h1[i]*i)/s求m1,m2,mg(总积分)
求每一个类间的方差,[s1*(m1-mg)*(m1-mg)+s2*(m2-mg)*(m2-mg)]/(s1+s2)
d.(1),类内方差v = sum((i-m)*(i-m)*h[i]/s),最小类内方差也行
i 取值[0,256],求使得类间方差最大的i就是阈值
- import cv2
- import numpy as np
- import matplotlib.pyplot as plt
-
- img = cv2.imread("otsu.jpg",0)
-
- hist = cv2.calcHist([img],[0],None,[256],[0,256])
- histnorm = (hist-hist.min())/(hist.max()-hist.min())
- bins = np.arange(256)
-
- # plt.plot(histnorm)
- # plt.xlim([0,256])
- # plt.show()
-
- fnmin = 99999
- tmp = 0
- fnmax = 0
- tm = 0
- p = hist/sum(hist)
- histnorm = np.squeeze(histnorm)
- for i in range(1,256):
- s1 = np.sum(histnorm[:i])
- s2 = np.sum(histnorm[i:])
- q1 = histnorm[i:]*bins[i:]
- m1 = np.sum(histnorm[:i] * bins[:i])/s1
- m2 = np.sum(histnorm[i:] * bins[i:])/s2
- mg = np.sum(histnorm* bins)/(s1+s2)
-
- #最大类间方差
- fm = (s1*(m1-mg)*(m1-mg)+ s2*(m2-mg)*(m2-mg))/(s1+s2)
- if fm>fnmax:
- fnmax = fm
- tm = i
-
- #最小类内方差
- v1 = np.sum((bins[:i] - m1)*(bins[:i] - m1)*(histnorm[:i])/s1)
- v2 = np.sum((bins[i:] - m2)*(bins[i:] - m2)*(histnorm[i:])/s2)
- fn = v1+v2
- if fn<fnmin:
- fnmin = fn
- tmp = i
-
-
- ret1,th1 = cv2.threshold(img,tm, 255, cv2.THRESH_BINARY)
- print(tm,ret1)
- ret2,th2 = cv2.threshold(img,tmp, 255, cv2.THRESH_BINARY)
- print(tmp,ret2)
- ret3,th3 = cv2.threshold(img,0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
- print(ret3)
-
- cv2.imshow("th1",th1)
- cv2.imshow("th2",th2)
- cv2.imshow("th3",th3)
- cv2.waitKey(0)

图片:从别博客里面保存的
结果:最大类间方差和cv2.THRESH_OTSU计算出来的阈值一样,最小类间方差要小一点
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。