Python中OTSU算法的原理與實(shí)現(xiàn)詳解
原理
OTSU算法是大津展之提出的閾值分割方法,又叫最大類間方差法。OTSU并不是一個(gè)英文縮寫,而是日語(yǔ)假名,是其提出者的姓氏“大津”。
假設(shè)存在閾值T可以將圖像分為兩部分,記二者均值為m1,m2,圖像總均值為m,像素被分入這兩部分的比例分別為p1?,p2? 。從而
p1?+p2=1
p1m1+p2m2=m
則類間方差可表示為
σ2=p1?(m1?−m)2+p2(m2-m)2?
=p1m12+p2m22-m2
實(shí)現(xiàn)和驗(yàn)證
由于OTSU算法的邏輯和公式都非常清晰,所以實(shí)現(xiàn)起來(lái)也及其方便
import numpy as np
import matplotlib.pyplot as plt
# 計(jì)算類間方差
def getVar(img, th):
slct = img>th
p1 = np.sum(slct)/img.size
if p1 in [0, 1]:
return 0
p2 = 1-p1
m1 = np.mean(img[slct])
m2 = np.mean(img[~slct])
m = p1*m1+p2*m2
return p1*m1**2+p2*m2**2-m**2
def otsu(img):
vs = [getVar(img, th) for th in range(256)]
return np.argmax(vs)
其中,getVar用于計(jì)算類間方差,后面的otsu則返回分割閾值。下面創(chuàng)建函數(shù)用于測(cè)試otsu算法
def drawOne(fig, index, img):
fig.add_subplot(index)
plt.imshow(img, cmap="gray")
plt.axis('off')
def test():
img = plt.imread(r"D:\Code\NotePL\python\lena.jpg").astype(float)
img = np.mean(img, axis=2)
th = otsu(img)
print(th)
fig = plt.figure(figsize=(8,3))
drawOne(fig, 131, img)
drawOne(fig, 132, img>th)
drawOne(fig, 133, img<=th)
plt.tight_layout()
plt.show()
效果如下

分析和優(yōu)化
由于圖像的像素值是八位整型,所以迭代256次就可以得到所有的類間方差。
img = plt.imread(r"D:\Code\NotePL\python\lena.jpg").astype(float) img = np.mean(img, axis=2) vs = [getVar(img, th) for th in range(256)] print(np.argmax(vs)) # 121 plt.plot(vs) plt.show()
類間方差分布如下,當(dāng)閾值是121時(shí),得到最大類間方差。

對(duì)于精度更高的16位圖像,或者其他非圖像的數(shù)值,遍歷的方案效率太低了,為此可進(jìn)行做一個(gè)步長(zhǎng)二分的爬山算法,代碼如下,最終得到的結(jié)果位121.7,由于在閾值分割時(shí)采用的是大于號(hào),所以效果與121相同。
def climb(img, step, st=0, err=0.1):
vSt = getVar(img, st)
while abs(step)>err:
ed = st+step
vEd = getVar(img, ed)
if vEd < vSt:
step = -step/2
st, vSt = ed, vEd
return ed
climb(img, 40)
# 121.71875
到此這篇關(guān)于Python中OTSU算法的原理與實(shí)現(xiàn)詳解的文章就介紹到這了,更多相關(guān)Python OTSU算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在pycharm中運(yùn)行js文件以及附加node.js下載步驟
js文件需要用node來(lái)運(yùn)行,所以首先要安裝node軟件,下面這篇文章主要給大家介紹了關(guān)于在pycharm中運(yùn)行js文件以及附加node.js下載步驟的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
人工智能學(xué)習(xí)Pytorch數(shù)據(jù)集分割及動(dòng)量示例詳解
這篇文章主要為大家介紹了人工智能學(xué)習(xí)Pytorch數(shù)據(jù)集分割及動(dòng)量示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-11-11
Python如何通過(guò)ip2region解析IP獲得地域信息
這篇文章主要介紹了Python如何通過(guò)ip2region解析IP獲得地域信息,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
Python GUI學(xué)習(xí)之登錄系統(tǒng)界面篇
這篇文章主要介紹了Python GUI學(xué)習(xí)之登錄系統(tǒng)界面篇,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
python實(shí)現(xiàn)發(fā)消息提醒功能的常見(jiàn)方法
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)發(fā)消息提醒功能的常見(jiàn)方法,文中的示例代碼講解詳細(xì),有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下2026-05-05
如何使用五行Python代碼輕松實(shí)現(xiàn)批量摳圖
簡(jiǎn)單來(lái)說(shuō),摳圖就是將照片的主體人或物品從圖片中摳出來(lái),以便貼到別處使用,下面這篇文章主要給大家介紹了關(guān)于如何使用五行Python代碼輕松實(shí)現(xiàn)批量摳圖的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04
詳解Python的collections模塊中的deque雙端隊(duì)列結(jié)構(gòu)
deque結(jié)構(gòu)可以看作是內(nèi)置的list結(jié)構(gòu)的加強(qiáng)版,且比隊(duì)列提供了更強(qiáng)大的方法,下面就通過(guò)幾個(gè)小例子來(lái)詳解Python的collections模塊中的deque雙端隊(duì)列結(jié)構(gòu):2016-07-07

