前幾天被OpenCV的直方圖的數據結構CvHistogram弄得很糾結。上網一搜,也沒什麼相關的資料。如今有點頭緒了,就寫點東西,讓後面的人好走一些吧。php
先來看看CvHistogram的定義:數組
typedef struct CvHistogram數據結構
{函數
int type;學習
CvArr* bins;指針
float thresh[CV_MAX_DIM][2]; /* For uniform histograms. */調試
float** thresh2; /* For non-uniform histograms. */orm
CvMatND mat; /* Embedded matrix header for array histograms. */圖片
}內存
CvHistogram;
第一個成員type,相信你們都見過不少結構都有其。好比:CvMat、CvMatND、IplImage(圖像結構中,其用nSize成員代替)。這個成員用來區分各個類型的。OpenCV不少函數的原型都用到了一個CvArr*類型。這個類型說明能夠接受一個CvMat或者IplImage類型的指針。這是咱們對它的最初理解。其實,看過CvArr定義的人都知道,實際上是typedef void CvArr;並不是派生關係。 對於OPenCV函數內部,獲得的是一個void指針,這時就有必要確切的知道獲得的究竟是一個什麼類型(是CvMat指針仍是IplImage指針,仍是CvMatND指針)。這樣type的做用就體現了。
第二個 成員bins。一個CvArr(即void)指針。你們能夠先把其理解成一個快捷方式。其等於mat成員的data成員。等一下再說這個成員。
第三個成員是thresh。是一個二維數組。並且第二維是2.設想一下,這個函數是求圖像的分佈像素值(像素灰度值)分佈狀況。而不一樣的人,對不一樣的灰度值感興趣。這時,OpenCV就必須可以讓用戶自行指定一個灰度值的範圍。這就須要一個上界和下界來指定一個範圍。這就是第二維的大小是2的緣由。在講第一維前,先來講說直方圖的維數。一開始我對什麼「一維直方圖」、「二維直方圖」不是很明。不知道怎麼樣纔算是二維的。後面找到了一張二維直方圖才明白。《學習OpenCV》、網上都有不少一維的直方圖。我也在這裏給出一個一維的直方圖:
一維直方圖
最重要的仍是二維的直方圖。
二維直方圖,其中第一維是16.第二維爲8.你們能夠在圖中看到最左邊的8條紅柱(固然第一條是白色的)。其紅的程度不一樣。對於其餘顏色也是分紅了8中不一樣的程度。一共有16種。
下面的是圖片的網址,還有代碼。
如今,你們對直方圖的維數,應該有一點認識了。如今來講說thresh成員。正是由於直方圖能夠有多維的,因此,必須得用thresh來指明各維的上下界。因此這個thresh成員是一個二維的指針。
如今到了thresh2成員。先一下這個問題:直方圖的bin的個數和各個bin的大小 是怎麼肯定的?
bin的個數是經過cvCreateHist函數的參數來設定的。而各個bin的大小就有兩種狀況了。1:每一個bin都同樣大。2:每一個bin的大小不同大。對於每一個bin同樣大的話,bin的大小是比較容易解決的。相信你們都想到了,平均便可,由於有了上下界和bin的個數。而對於種狀況就要用到thresh2這個成員了。
試想一下,要是不將每個bin的大小設爲同樣的話,那麼就得由用戶本身設定每個bin的大小(就是設定每個bin的上下界)。固然要是多維的直方圖,那麼就要爲每一維的全部bin都設定上下界。這就須要一個二維數組來存儲這樣的數據。從CvHistogram這個結構體能夠看到thresh2成員是一個二維指針。這就是thresh2的來由了。
最後一個成員mat。這個成員是用來存數據的。前面的bins指針實際上是等於mat成員的data的。因此,只能在mat裏存放數據了。
cvCalcHist函數對圖像進行操做後,獲得了每個bin的大小,並存放到mat的data成員指向的內存中。至於bings成員。請看下面的代碼
if( type == CV_HIST_ARRAY )
{
hist->bins = cvInitMatNDHeader( &hist->mat, dims, sizes,
CV_HIST_DEFAULT_TYPE );
cvCreateData( hist->bins );
}
else if( type == CV_HIST_SPARSE )
hist->bins = cvCreateSparseMat( dims, sizes, CV_HIST_DEFAULT_TYPE );
因此,bins成員的值和mat裏的data成員的值同樣。之因此說是快捷方式,應該能夠經過它能夠快速獲得存放直方圖信息的地址。
mat成員還有一個dim的結構體。這個結構體的size成員用來存儲直方圖中各維的bin的個數。而該結構體的step成員是從本維本數據跳到下本維的下一個數據的字節數。好比說,對於前面那個二維直方圖的例子。其dim[0].step = 32;而dim[1].step = 4.對於第二維來講,之因此是4.是由於每個bin都是用float類型存儲的。因此跳4.就像一個float數組。下標爲2的地址和下標爲3的地址就是相差4(字節)。而第一維是32.是由於有第二維有8個bin,每一個bin爲4位。因此要跳過8*4=32位。
其實,要想出較好的理解這個結構,最好仍是本身敲代碼,寫一個能執行的例子出來。看看結果。而後,在調試的狀況下,進入OpenCV的函數內部看看。