對OpenCV中Haar特征CvHaarClassifierCascade等結構理解


首先說一下這個級聯分類器,OpenCV中級聯分類器是根據VJ 04年的那篇論文(Robust Real-Time Face Detection)編寫的,查看那篇論文,知道構建分類器的步驟如下:

1、根據haar-like特征訓練多個弱分類器

2、使用adaboost算法將多個弱分類器組合成一個強分類器

3、最終的分類器是由多個強分類器級聯而成

下面這幅圖是弱分類器組合成強分類器的示意圖(圖片來源於網絡):

下面這張是多個強分類器級聯的示意圖(圖片來源於網絡):

在了解了級聯分類器是怎么一回事后,我們來看一看OpenCV里面級聯分類器的結構

在調用OpenCV中的級聯分類器對目標進行分類時,都會將一個訓練好的分類器(一個訓練好的.xml文件)讀入到一個CvHaarClassifierCascade結構中,如下:

 1 CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad( "haarcascade_frontalface_alt.xml", 0, 0, 0 );  

那么這個CvHaarClassifierCascade結構體里面的內容都有哪些呢?

 1 typedef struct CvHaarClassifierCascade
 2 {
 3     int  flags;                 /* 標志位 */
 4     int  count;                 /* 分級分類器中強分類器的數量 */
 5     CvSize orig_window_size;     /* 訓練中原始目標的大小 */ 
 6     
 7     /* these two parameters are set by cvSetImagesForHaarClassifierCascade */
 8     CvSize real_window_size;     /* 待檢測物體的大小 */
 9     double scale;                /* Haar塊縮放的尺寸 */
10     
11     CvHaarStageClassifier* stage_classifier; /* 定義強分類器數組 */ 
12     CvHidHaarClassifierCascade* hid_cascade;
13 }CvHaarClassifierCascade;

第一個flags,還不是很清楚,在debug模式下,flags=1112539136(好吧,這個值很詭異),我也不是很清楚

第二個count,表示整個分級分類器中強分類器的數量,即最后參與級聯的強分類器的個數

第三個orig_window_size,表示的是在訓練時用的正樣本的尺寸,OpenCV中的尺寸是20x20

第四個和第五個,注釋中說了,這兩個參數需要自己設置,具體每個參數看注釋

第六個stage_classifier,是強分類器指針,指向一個強分類器數組,之前的count是多少,那么此處的強分類器就有多少

最后一個hid_cascade,還不是很清楚

下面來看上面第六個參數的強分類器結構體

 1 typedef struct CvHaarStageClassifier
 2 {
 3     int  count;  /* number of classifiers in the battery 構成強分類器的弱分類器的數量*/
 4     float threshold; /* threshold for the boosted classifier 疊加分類器的閾值*/
 5     CvHaarClassifier* classifier; /* array of classifiers 定義分類器數組*/
 6     /* these fields are used for organizing trees of stage classifiers,
 7        rather than just stright cascades */
 8     int next;
 9     int child;
10     int parent;
11 }CvHaarStageClassifier;

第一個count,表示該強分類器中,弱分類器的數量,即該強分類器由多少個弱分類器組成

第二個threshold,疊加分類器的閾值(好吧。。這個我也不知道)

第三個classifier,是一個指針,指向的是一個弱分類器數組,之前的count是多少,此處的弱分類器就有多少

后面3個都不清楚。。。(望知道的網友給予幫助)

下面是弱分類器的結構

 1 typedef struct CvHaarClassifier
 2 {
 3     int count;      /* number of nodes in the decision tree */
 4     /* these are "parallel" arrays. Every index i corresponds to a node of the decision tree (root has 0-th index).
 5     left[i] - index of the left child (or negated index if the left child is a leaf)
 6     right[i] - index of the right child (or negated index if the right child is a leaf)
 7     threshold[i] - branch threshold. if feature responce is <= threshold, left branch is chosen, otherwise right branch is chosed.
 8     alpha[i] - output value correponding to the leaf. */
 9 
10     CvHaarFeature* haar_feature;
11     float* threshold;
12     int* left;
13     int* right;
14     float* alpha;
15 }CvHaarClassifier;

第一個count,在opencv里,發現始終都是1,自己想了想,因為這個結構體記錄的是一個弱分類器,自然弱分類器的個數就是1了。

第二個haar_feature,也是一個指針,指向一個(因為count是1)特征結構體CvHaarFeature,這個結構體中記錄的內容是弱分類器的類型(包括該haar-like特征的位置,大小,以及種類,這個結構體會在下面給出,再細說)

第三個threshold,就是那個判別函數:h(x,f,p,theta) = (p*f(x) < p*theta ? 1 : 0),中的閾值theta

   

第四個left,第五個right不是很清楚(求知道的同學詳解啊~~~~)

第六個alpha,就是這個弱分類器的權重(每一個強分類器都是由多個弱分類器按照各自的權重進行表決,而得到的)

特征的結構體如下

 1 #define CV_HAAR_FEATURE_MAX  3
 2 // 一個Haar特征由2~3個具有相應權重的矩形組成
 3 typedef struct CvHaarFeature
 4 {
 5     int  tilted;      // 0 means up-right feature, 1 means 45-rotated feature
 6     struct
 7     {
 8         CvRect r;
 9         float weight;
10     } rect[CV_HAAR_FEATURE_MAX]; 
11     // 2-3 rectangles with weights of opposite signs and with absolute values inversely proportional to the areas of the rectangles. if rect[2].weight != 0, then the feature     consists of 3 rectangles, otherwise it consists of 2.
12 }CvHaarFeature;

第一個參數titled,0表示該特征是標准的haar-like特征,1表示旋轉45°后的特征

  標准的haar-like特征如下:

      

  而旋轉45°后的特征如下:

      

第二個參數是個結構體數組,每個結構體中包括一個矩形和一個權重,這個數組的大小是CV_HAAR_FEATURE_MAX(3)(注釋中說:此處可能有2~3個矩形,這里的矩形等看了下面的解釋就知道了),這個矩形和權重有什么用呢?

  在debug模式下,查看第一個弱分類器數組內的元素

  第一個元素:

1 rect[0].r.x = 3
2 rect[0].r.y = 7
3 rect[0].r.width = 14
4 rect[0].r.height = 4
5 rect[0].weight = -1

  第二個元素:

1 rect[1].r.x = 3
2 rect[1].r.y = 9
3 rect[1].r.width = 14
4 rect[1].r.height = 2
5 rect[1].weight = 2

  第三個元素則全都是0

  這么看這些坐標,並不是很清楚,我們可以畫個圖:

  

  由圖可見,第一個矩形表示的是A+B區域,第二個矩形表示的是B區域。

  此時再看一看每個元素的權重weight,結合積分圖的概念,發現第一個矩形的積分圖乘以其權重加上第二個積分圖乘以其權重,恰好得到下述結果:

  (A+B)*(-1)+B*2=B-A

  看到這個公式,大家都不會陌生,這正式VJ論文中給出的眾多haar-like模板中的其中一個模板的計算方法(此處不知如何表達,大家將就,看懂就行) 

我們繼續考察第二個弱分類器的特征部分,其特征參數如下:

1 rect[0].r.x = 1, rect[0].r.y = 2
2 rect[0].r.width = 18, rect[0].r.height = 4
3 rect[0].weight = -1
4 
5 rect[1].r.x = 7, rect[1].r.y = 2
6 rect[1].r.width = 6, rect[1].r.height = 4
7 rect[1].weight = 3

數組的第三個元素依然都是是0,對其繪圖:

  

  第一塊矩形區域是A+B+C,第二塊矩形區域是B,積分圖乘以權重,再相加,可得:

  (A+B+C)*(-1)+B*3 = 2*B-A-C

  也是haar-like特征模板之一(此處不知如何表達,大家將就,看懂就行)

剛剛找了好久,找到一個第三個元素權重不為0的,該數組三個元素如下:

 1 rect[0].r.x = 0, rect[0].r.y = 2
 2 rect[0].r.width = 20, rect[0].r.height = 6;
 3 rect[0].weight = -1
 4 
 5 rect[1].r.x = 10, rect[1].r.y = 2
 6 rect[1].r.width = 10, rect[1].r.height = 3;
 7 rect[1].weight = 2
 8 
 9 rect[2].r.x = 0, rect[2].r.y = 5
10 rect[2].r.width = 10, rect[2].r.height = 3;
11 rect[2].weight = 2

 

 繪圖可得:

  

  將每個矩形乘以相應的權重,相加可得:

  (A+B+C+D)*(-1)+2*B + 2*C = B+C-(A+D)

  也是模板之一

  (佩服設計這個結構體的程序員)

到此,四個結構體都說完了,如有不對,請大家指正


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM