otsu演算法:最大類間方差法(大津演算法),是一種確定閾值的演算法。
對於影象i(x,y),前景(即目標)和背景的分割閾值記作t,屬於前景的畫素點數占整幅影象的比例記為ω0,其平均灰度μ0;背景畫素點數占整幅影象的比例為ω1,其平均灰度為μ1。影象的總平均灰度記為μ,類間方差記為g。
假設影象的背景較暗,並且影象的大小為m×n,影象中畫素的灰度值小於閾值t的畫素個數記作n0,畫素灰度大於閾值t的畫素個數記作n1,則有:
(1) ω0=n0/ (m×n)
(2) ω1=n1/ (m×n)
(3) n0 + n1 = m×n
(4) ω0 + ω1 = 1
(5) μ = ω0 * μ0 + ω1 * μ1
(6) g = ω0 * (μ0 - μ)2 + ω1 * (μ1 - μ)2
將式(5)代入式(6),得到等價公式:
(7) g = ω0 *ω1 * (μ0 - μ1)2
採用遍歷的方法得到使類間方差g最大的閾值t。
優點:演算法簡單,當目標與背景的面積相差不大時,能夠有效地對影象進行分割。
缺點:當影象中的目標與背景的面積相差很大時,表現為直方圖沒有明顯的雙峰,或者兩個峰的大小相差很大,分割效果不佳,或者目標與背景的灰度有較大的重疊時也不能準確的將目標與背景分開。
原因:該方法忽略了影象的空間資訊,同時將影象的灰度分布作為分割影象的依據,對雜訊也相當敏感。
opencv可以直接呼叫這種演算法,threshold(gray, dst,0,
255, cv_thresh_otsu)
;
import numpy as np
defotsu_threshold
(im)
: width, height = im.size
img_size = width * height
pixel_counts = np.zeros(
256)
for x in
range
(width)
:for y in
range
(height)
: pixel = im.getpixel(
(x, y)
) pixel_counts[pixel]
= pixel_counts[pixel]+1
# 得到的以0-255索引的畫素值個數列表
s_max =(0
,-10)
for threshold in
range
(256):
# 遍歷所有閾值
# 更新
n_0 =
sum(pixel_counts[
:threshold]
)# 得到閾值以下畫素個數
n_1 =
sum(pixel_counts[threshold:])
# 得到閾值以上畫素個數
w_0 = n_0 / img_size
w_1 = n_1 / img_size
# 得到閾值下所有畫素的平均灰度
u_0 =
sum(
[i * pixel_counts[i]
for i in
range(0
, threshold)])
/ n_0 if n_0 >
0else
0# 得到閾值上所有畫素的平均灰度
u_1 =
sum(
[i * pixel_counts[i]
for i in
range
(threshold,
256)])
/ n_1 if n_1 >
0else
0# 總平均灰度
u = w_0 * u_0 + w_1 * u_1
# 類間方差
g = w_0 *
(u_0 - u)
*(u_0 - u)
+ w_1 *
(u_1 - u)
*(u_1 - u)
# 類間方差等價公式
# g = w_0 * w_1 * (u_0 * u_1) * (u_0 * u_1)
# 取最大的
if g > s_max[1]
: s_max =
(threshold, g)
return s_max[
0]
給我一塊石頭
給我一塊石頭!專案經理應該小心的遊戲之一 克里夫與團隊一起,用一周時間制訂出了專案日程。他們完成了 哈德遜灣式啟動 並且確定已經識別出了主要的技術風險。他將風險和日程安排告訴了他的上司諾姆。你就不能再早點完成專案了麼?諾姆的一句話將克里夫送回了團隊,步履蹣跚。克里夫與團隊又花了一周時間修改時間表,得...
我是一塊硬碟
發信人 lesliechen 打死我也不說 信區 campus east 標 題 我是一塊硬碟 zz 發信站 bbs 同舟共濟站 wed jul 7 13 27 53 2004 站內 我是乙個硬碟,st380021a,在乙個普普通通的台式電腦裡工作。別人總認為我們是高科技白領,工作又乾淨又體面,似乎...
我是一塊硬碟
我是一條記憶體。我在一台台式電腦裡工作,但是我記不得我是從 來的,是什麼牌子,因為我健忘。我的上司是cpu大哥,他是我們的老大。都說他是電腦的腦子,可是我看他的腦子 實在是太小了,比我還要健忘。每天他總是不停地問我,某某頁某某位址存的是什麼?我總是不厭其煩地告訴他,可是不出一秒鐘他又忘記了,又要問一...