用OpenCV實現Otsu演算法

2021-07-05 16:49:00 字數 2774 閱讀 7341

最近在學習影象分割反面的知識,在岡薩雷斯的那本書上看到otsu演算法,身邊的同學都是用matlab來實現這個演算法。我覺得matlab寫得話,但是**的效率應該不會高。於是又惡補了一些opencv的一些基本知識,然後看了augusdi的部落格,分析了一下他的**並附上,第二份**是來自某一位大牛的**,寫得更加易懂。

otsu法(最大類間方差法,有時也稱之為大津演算法)使用的是聚類的思想,把影象的灰度數按灰度級分成2個部分,使得兩個部分之間的灰度值差異最大,每個部分之間的灰度差異最小,通過方差的計算來尋找乙個合適的灰度級別 來劃分。 所以 可以在二值化的時候 採用otsu演算法來自動選取閾值進行二值化。otsu演算法被認為是影象分割中閾值選取的最佳演算法,計算簡單,不受影象亮度和對比度的影響。因此,使類間方差最大的分割意味著錯分概率最小。

設t為設定的閾值。 w0

: 分開後 前景畫素點數占影象的比例 u0

: 分開後 前景畫素點的平均灰度 w1

:分開後 被景畫素點數占影象的比例 u1

: 分開後 被景畫素點的平均灰度 u=

w0∗u

0+w1

∗u1 :影象總平均灰度

從l個灰度級遍歷t,使得t為某個值的時候,前景和背景的方差最大, 則 這個 t 值便是我們要求得的閾值。其中,方差的計算公式如下: g=

wo∗(

u0−u

)∗(u

0−u)

+w1∗

(u1−

u)∗(

u1−u

) 此公式計算量較大,可以採用: g=

w0∗w

1∗(u

0−u1

)∗(u

0−u1

) 由於otsu演算法是對影象的灰度級進行聚類,so 在執行otsu演算法之前,需要計算該影象的灰度直方圖。

第乙份**:來自augusdi

#include

#include

#include

int otsu(iplimage* src);

int main()

int otsu(iplimage* src)

; for (int m = 0; m < height; m++)

}int threshold;

long sum0 = 0, sum1 = 0; //儲存前景的灰度總和和背景灰度總和

long cnt0 = 0, cnt1 = 0; //前景的總個數和背景的總個數

double w0 = 0, w1 = 0; //前景和背景所佔整幅影象的比例

double u0 = 0, u1 = 0; //前景和背景的平均灰度

double variance = 0; //最大類間方差

int i, j;

double u = 0;

double maxvariance = 0;

for (i = 1; i < 256; i++) //一次遍歷每個畫素

u0 = (double)sum0 / cnt0;

w0 = (double)cnt0 / size;

for (j = i; j <= 255; j++)

u1 = (double)sum1 / cnt1;

w1 = 1 - w0; // (double)cnt1 / size;

u = u0 * w0 + u1 * w1; //影象的平均灰度

printf("u = %f\n", u);

//variance = w0 * pow((u0 - u), 2) + w1 * pow((u1 - u), 2);

variance = w0 * w1 * (u0 - u1) * (u0 - u1);

if (variance > maxvariance)

}printf("threshold = %d\n", threshold);

return threshold;

}

第二份**:

#include 

#include

int otsu(iplimage *image)

//統計灰度級中每個畫素在整幅影象中的個數

for (i = y; i < height; i++)

}//計算每個畫素在整幅影象中的比例

for (i = 0; i < 256; i++)

//經典ostu演算法,得到前景和背景的分割

//遍歷灰度級[0,255],計算出方差最大的灰度值,為最佳閾值

float w0, w1, u0tmp, u1tmp, u0, u1, u, deltatmp, deltamax = 0;

for (i = 0; i < 256; i++)

else

//前景部分

}u0 = u0tmp / w0; //第一類的平均灰度

u1 = u1tmp / w1; //第二類的平均灰度

u = u0tmp + u1tmp; //整幅影象的平均灰度

//計算類間方差

deltatmp = w0 * (u0 - u)*(u0 - u) + w1 * (u1 - u)*(u1 - u);

//找出最大類間方差以及對應的閾值

if (deltatmp > deltamax)

}//返回最佳閾值;

return threshold;

}int main(int argc, char* argv)

OpenCv 中Otsu 演算法實現

大津法或最大類間方差法 使用的是聚類的思想,把影象的灰度數按灰度級分成2個部分,使得兩個部分之間的灰度值差異最大,每個部分之間的灰度差異最小,通過方差的計算來尋找乙個合適的灰度級別來劃分。所以可以在二值化的時候採用otsu演算法來自動選取閾值進行二值化。otsu演算法被認為是影象分割中閾值選取的最佳...

OTSU演算法介紹及openCV的C 實現

otsu演算法也稱最大類間差法,有時也稱之為大津演算法。前景與背景影象的類間方差最大。因方差是灰度分布均勻性的一種度量,背景和前景之間的類間方差越大,說明構成影象的兩部分的差別越大,當部分前景錯分為背景或部分背景錯分為前景都會導致兩部分差別變小。因此,使類間方差最大的分割意味著錯分概率最小。ostu...

C 實現otsu演算法

類間方差最大化閾值分割演算法 otsu 可以自動計算影象二值化時的閾值,otsu的中心思想是閾值t應使目標與背景兩類的類間方差最大。具體原理如下 otsu是按影象的灰度特性,將影象分成背景和目標兩部分。背景和目標之間的類間方差越大,說明構成影象的兩部分的差別越大,當部分目標錯分為背景或部分背景錯分為...