一副影象包括目標,背景及雜訊,想要直接提取目標物體,通常是採用灰度變換閾值化操作。閾值化的方法經典的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閾值分割
在計算機視覺中我們常常關注的目標特徵是顏色和灰度,刻畫影象中的兩個區域視覺相似性有許多方法,如形狀描繪子,顏色特徵,距特徵等。對於某種場景下的應用,具有獨特的紋理物件可以使用乙個很好的紋理特徵符。針對顏色不同的區域中的單體物件相同的擴充套件,我們可以使用顏色特徵來測量物件的不用部分的相似性。如果物體...