對OpenCV直方圖的數據結構CvHistogram的理解

前幾天被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種。

下面的是圖片的網址,還有代碼。

http://www.opencv.org.cn/index.php/%E5%9B%BE%E5%83%8F%E9%A2%9C%E8%89%B2%E5%88%86%E5%B8%83%E7%9B%B4%E6%96%B9%E5%9B%BE

 

如今,你們對直方圖的維數,應該有一點認識了。如今來講說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的函數內部看看。

相關文章
相關標籤/搜索