OTSU閾值化學習

2021-08-14 03:32:25 字數 4389 閱讀 2179

一副影象包括目標,背景及雜訊,想要直接提取目標物體,通常是採用灰度變換閾值化操作。閾值化的方法經典的otsu,固定閾值,自適應閾值,雙閾值及半閾值化操作。

otsu閾值化:

前景和背景之間的類間方差如果越大,就說明構成影象的兩個部分之間的差別越大,當部分目標被錯分為背景或部分背景被錯分為目標,都會導致兩部分差別變小,當所取閾值的分割使類間方差最大時就意味著錯分概率最小

對於影象i(x,y),前景(即目標)和背景的分割閾值記作t,屬於前景的畫素點數占整幅影象的比

例記為ω0,其平均灰度μ0;背景畫素點數占整幅影象的比例為ω1,其平均灰度為μ1。影象的總平均

灰度記為μ,類間方差記為g。

假設影象的背景較暗,並且影象的大小為m×n,

影象中畫素的灰度值小於閾值t的畫素個數記作n0,畫素灰度大於閾值t的畫素個數記作n1,則有:

ω0=n0/ m×n (1)

ω1=n1/ m×n (2)

n0+n1=m×n (3)

ω0+ω1=1 (4)

μ=ω0*μ0+ω1*

μ1 (5)

g=ω0(μ0-μ)^2+ω1(μ1-μ)^2 (6)

將式(5)代入式(6),得到等價公式: g=ω0ω1(μ0-μ1)^2 (7)。

**實現:

otsu閾值化。otsu-最大類間方差法

otsu演算法對不均勻光照的不能產生很好的效果,但計算簡單,適用性強。

#include

#include

#include

#include

using namespace std;

using namespace cv;

//------------【全域性函式宣告】-------------

int otsu(mat grayimage);     //otsu法函式實現

//-----------【主函式】---------------

int main()

//------------讀取源影象並檢查影象是否讀取成功------------

cout<< "讀取錯誤,請重新輸入正確路徑!\n";

system("pause");

return-1;

imshow("【源影象】",srcimage);

//------------灰度轉換------------

matsrcgray;

cvtcolor(srcimage,srcgray, cv_rgb2gray);       //轉為灰度圖

imshow("【灰度圖】",srcgray);

//------------呼叫otsu()閾值化所得到閾值------------

intotsuthreshold = otsu(srcgray);

cout<< "呼叫otsu()閾值化所得到閾值:" << otsuthreshold << endl;

matotsuresultimage = mat::zeros(srcgray.rows, srcgray.cols, cv_8uc1);//建立輸出結果影象

//------------利用得到的閾值實現二值化操作------------

for(int i = 0; i < srcgray.rows; i++)

for(int j = 0; j < srcgray.cols; j++)

//閾值判斷。 若該點值大於閾值,則設為255,否則設為0。

if(srcgray.at(i, j) > otsuthreshold)

otsuresultimage.at(i,j) = 255;

else

otsuresultimage.at(i,j) = 0;

imshow("【otus閾值化影象】",otsuresultimage);

waitkey(10000);      //等待10秒退出程式

return0;

//---------------【otsu法函式實現】----------------------

int otsu(mat grayimage)

intnrows = grayimage.rows;//行數

intncols = grayimage.cols;//列數       

intthreshold = 0;    //初始化閾值

//------------初始化統計引數------------

intnsumpix[256];   //用於灰度級中每個畫素在整幅影象中的個數

floatnprodis[256];         //用於記錄每個灰度級佔影象中的概率分布

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

nsumpix[i]= 0;

nprodis[i]= 0;

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

for(int i = 0; i < nrows; i++)

for(int j = 0; j < ncols; j++)

nsumpix[(int)grayimage.at(i,j)]++;

//------------計算每個灰度級佔影象中的概率分布------------

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

nprodis[i]= (float)nsumpix[i] / (ncols*nrows);

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

floatwb, wf; //比重. wb-背景部分; wf-前景部分

floatu0_temp, u1_temp, u0, u1;  //平均值

floatdelta_temp;   //存放臨時方差

doubledelta_max = 0.0;         //初始化最大類間方差

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

wb= wf = u0_temp = u1_temp = u0 = u1 = delta_temp = 0;//初始化相關引數

for(int j = 0; j < 256; j++)

//背景部分

if(j <= i)

//當前i為分割閾值,第一類總的概率

wb+= nprodis[j];    //比重

u0_temp+= j*nprodis[j];

//前景部分

else

//當前i為分割閾值,第一類總的概率

wf+= nprodis[i];     //比重

u1_temp+= j*nprodis[j];

//------------分別計算各類的平均值------------

u0= u0_temp / wb;

u1= u1_temp / wf;

//-----------計算最大類間方差------------

delta_temp= (float)(wb*wf*pow((u0 - u1), 2));//形如pow(x,y);其作用是計算x的y次方。

//------------依次找到最大類間方差下的閾值------------

if(delta_temp > delta_max)

delta_max= delta_temp;

threshold= i;

}//計算結束

returnthreshold;    //返回otus計算出的閾值

固定閾值化:

opencv中提供了閾值化函式threshold,函式模型如下:

doublethreshold(inputarraysrc, outputarraydst, doublethresh, doublemaxval, inttype)

threshold函式應用在單通道影象中固定閾值化狐狸,通常是為了得到二值化影象或是為了去除雜訊。

thresh是設定的閾值。maxval表示預設最大值,在type為thresh_binary和thresh_binary_inv型別 中有效。type型別由thres_binary二進位制閾值化,thres_binary_inv反二進位制閾化,thresh_trunc截斷閾值化,thresh_tozero閾值化為0;

**實現:

#include"opencv2/imgproc/imgproc.hpp"

#include"opencv2/highgui/highgui.hpp"

int main()

type

otsu閾值分割演算法原理 閾值分割 Otsu法

演算法實現 不呼叫函式 include include using namespace std using namespace cv 實現灰度直方圖的繪製 void drawpicture mat inpicture,mat outpicture ma hist const int bins 256...

OTSU閾值分割

otsu演算法 1 原理 對於影象i x,y 前景 即目標 和背景的分割閾值記作t,屬於前景的畫素點數占整幅影象的比例記為 0,其平均灰度 0 背景畫素點數占整幅影象的比例為 1,其平均灰度為 1。影象的總平均灰度記為 類間方差記為g。假設影象的背景較暗,並且影象的大小為m n,影象中畫素的灰度值小...

OTSU閾值分割

在計算機視覺中我們常常關注的目標特徵是顏色和灰度,刻畫影象中的兩個區域視覺相似性有許多方法,如形狀描繪子,顏色特徵,距特徵等。對於某種場景下的應用,具有獨特的紋理物件可以使用乙個很好的紋理特徵符。針對顏色不同的區域中的單體物件相同的擴充套件,我們可以使用顏色特徵來測量物件的不用部分的相似性。如果物體...