2012-02-19 24 views
0

我試圖在Cuda平臺上實現Viola Johns人臉檢測算法(我知道openCV已經做到了這一點,我爲我的學校做了... :) )。使用OpenCV級聯 - 單獨使用haartraning XML文件

我的第一個階段是在CPU上實現算法。

我正在使用openCV庫,我知道openCV知道如何做人臉檢測,爲了理解,我想回到基本,並以我自己的方式做到這一點。

我使用openCV函數創建了積分和表示,以及squere和積分表示。

我迭代了級聯。通過階段,分類和rects迭代。 標準化每個窗口,計算每個分類器的總和,並與閾值進行比較,很遺憾,這似乎是我錯過了一些東西。因爲我無法檢測到臉部。

這似乎是我需要更好地瞭解cascade xml文件。

這裏有一個例子:

  <!-- tree 158 --> 
     <_> 
     <!-- root node --> 
     <feature> 
      <rects> 
      <_>3 6 2 2 -1.</_> 
      <_>3 6 1 1 2.</_> 
      <_>4 7 1 1 2.</_></rects> 
      <tilted>0</tilted></feature> 
     <threshold>2.3729570675641298e-003</threshold> 
     <left_val>0.4750812947750092</left_val> 
     <right_val>0.7060170769691467</right_val></_></_> 
    <_> 
     <!-- tree 159 --> 

  <!-- tree 159 --> 
     <_> 
     <!-- root node --> 
     <feature> 
      <rects> 
      <_>16 6 3 2 -1.</_> 
      <_>16 7 3 1 2.</_></rects> 
      <tilted>0</tilted></feature> 
     <threshold>-1.4541699783876538e-003</threshold> 
     <left_val>0.3811730146408081</left_val> 
     <right_val>0.5330739021301270</right_val></_></_></trees> 
    <stage_threshold>79.2490768432617190</stage_threshold> 
    <parent>16</parent> 
    <next>-1</next></_> 
<_> 

我想了解什麼是left_val和right_val的含義是什麼? 父,下一個值的含義是什麼? 如何計算每個分類器歸一化總和? 有什麼我在這裏做錯了嗎?看到我的代碼附加

基本上這是我正在做的一段時間,我想爲這個問題提供獎勵,但我沒有足夠的評級。任何幫助將非常感激。
Thnaks提前, 小號

int RunHaarClassifierCascadeSum(CascadeClassifier * face_cascade, CvMat* image , CvMat* sum , CvMat* sqsum, 
          CvMat* tilted,CvSize *scaningWindowSize, int iteratorRow, int iteratorCol) 

{

// Normalize the current scanning window - Detection window 
// Variance(x) = E(x^2) - (E(x))^2 = detectionWindowSquereExpectancy - detectionWindowExpectancy^2 
// Expectancy(x) = E(x) = sum_of_pixels/size_of_window 

double detectionWindowTotalSize = scaningWindowSize->height * scaningWindowSize->width; 

// calculate the detection Window Expectancy , e.g the E(x) 
double sumDetectionWindowPoint1,sumDetectionWindowPoint2,sumDetectionWindowPoint3,sumDetectionWindowPoint4;  // ______________________ 
sumDetectionWindowPoint1 = cvGetReal2D(sum,iteratorRow,iteratorCol);           // |R1    R2| 
sumDetectionWindowPoint2 = cvGetReal2D(sum,iteratorRow+scaningWindowSize->width,iteratorCol);     // |     | Sum = R4-R2-R3+R1 
sumDetectionWindowPoint3 = cvGetReal2D(sum,iteratorRow,iteratorCol+scaningWindowSize->height);     // |R3________________R4| 
sumDetectionWindowPoint4 = cvGetReal2D(sum,iteratorRow+scaningWindowSize->width,iteratorCol+scaningWindowSize->height); 
double detectionWindowSum = calculateSum(sumDetectionWindowPoint1,sumDetectionWindowPoint2,sumDetectionWindowPoint3,sumDetectionWindowPoint4); 
const double detectionWindowExpectancy = detectionWindowSum/detectionWindowTotalSize;  // E(x) 

// calculate the Square detection Window Expectancy , e.g the E(x^2) 
double squareSumDetectionWindowPoint1,squareSumDetectionWindowPoint2,squareSumDetectionWindowPoint3,squareSumDetectionWindowPoint4;  // ______________________ 
squareSumDetectionWindowPoint1 = cvGetReal2D(sqsum,iteratorRow,iteratorCol);           // |R1    R2| 
squareSumDetectionWindowPoint2 = cvGetReal2D(sqsum,iteratorRow+scaningWindowSize->width,iteratorCol);     // |     | Sum = R4-R2-R3+R1 
squareSumDetectionWindowPoint3 = cvGetReal2D(sqsum,iteratorRow,iteratorCol+scaningWindowSize->height);     // |R3________________R4| 
squareSumDetectionWindowPoint4 = cvGetReal2D(sqsum,iteratorRow+scaningWindowSize->width,iteratorCol+scaningWindowSize->height); 
double detectionWindowSquareSum = calculateSum(squareSumDetectionWindowPoint1,squareSumDetectionWindowPoint2,squareSumDetectionWindowPoint3,squareSumDetectionWindowPoint4); 
const double detectionWindowSquareExpectancy = detectionWindowSquareSum/detectionWindowTotalSize;  // E(x^2) 

const double detectionWindowVariance = detectionWindowSquareExpectancy - std::pow(detectionWindowExpectancy,2); // Variance(x) = E(x^2) - (E(x))^2 
const double detectionWindowStandardDeviation = std::sqrt(detectionWindowVariance); 

if (detectionWindowVariance<=0) 
    return -1 ; // Error 

// Normalize the cascade window to the normal scale window 
double normalizeScaleWidth = double(scaningWindowSize->width/face_cascade->oldCascade->orig_window_size.width); 
double normalizeScaleHeight = double(scaningWindowSize->height/face_cascade->oldCascade->orig_window_size.height); 

// Calculate the cascade for each one of the windows 
for(int stageIterator=0; stageIterator< face_cascade->oldCascade->count; stageIterator++)  // Stage iterator 
{ 

    CvHaarStageClassifier* pCvHaarStageClassifier = face_cascade->oldCascade->stage_classifier + stageIterator; 
    for (int CvHaarStageClassifierIterator=0;CvHaarStageClassifierIterator<pCvHaarStageClassifier->count;CvHaarStageClassifierIterator++) // Classifier iterator 
    { 
     CvHaarClassifier* classifier = pCvHaarStageClassifier->classifier + CvHaarStageClassifierIterator; 
     float classifierSum=0.; 

     for(int CvHaarClassifierIterator = 0; CvHaarClassifierIterator < classifier->count;CvHaarClassifierIterator++) // Feature iterator 
     { 
      CvHaarFeature * pCvHaarFeature = classifier->haar_feature; 

      // Remark 
      if (pCvHaarFeature->tilted==1) 
       break; 
      // Remark 

      for(int CvHaarFeatureIterator = 0; CvHaarFeatureIterator< CV_HAAR_FEATURE_MAX; CvHaarFeatureIterator++) // 3 Features iterator 
      { 
       CvRect * currentRect = &(pCvHaarFeature->rect[CvHaarFeatureIterator].r); 
       // Normalize the rect to the scaling window scale 
       CvRect normalizeRec; 
       normalizeRec.x = (int)(currentRect->x*normalizeScaleWidth); 
       normalizeRec.y = (int)(currentRect->y*normalizeScaleHeight); 
       normalizeRec.width = (int)(currentRect->width*normalizeScaleWidth); 
       normalizeRec.height = (int)(currentRect->height*normalizeScaleHeight); 

       double sumRectPoint1,sumRectPoint2,sumRectPoint3,sumRectPoint4;        // ______________________ 
       sumRectPoint1 = cvGetReal2D(sum,normalizeRec.x,normalizeRec.y);        // |R1    R2| 
       sumRectPoint2 = cvGetReal2D(sum,normalizeRec.x+normalizeRec.width,normalizeRec.y);   // |     | Sum = R4-R2-R3+R1 
       sumRectPoint3 = cvGetReal2D(sum,normalizeRec.x,normalizeRec.y+normalizeRec.height);   // |R3________________R4| 
       sumRectPoint4 = cvGetReal2D(sum,normalizeRec.x+normalizeRec.width,normalizeRec.y+normalizeRec.height); 

       double nonNormalizeRect = calculateSum(sumRectPoint1,sumRectPoint2,sumRectPoint3,sumRectPoint4);  // 
       double sumMean = detectionWindowExpectancy*(normalizeRec.width*normalizeRec.height);     // sigma(Pi) = normalizeRect = (sigma(Pi- rect) - sigma(mean))/detectionWindowStandardDeviation 
       double normalizeRect = (nonNormalizeRect - sumMean)/detectionWindowStandardDeviation;     // 

       classifierSum += (normalizeRect*(pCvHaarFeature->rect[CvHaarFeatureIterator].weight)); 
      } 
     } 
//    if (classifierSum > (*(classifier->threshold))) 
//     return 0;  // That's not a face ! 
     if (classifierSum > ((*(classifier->threshold))*detectionWindowStandardDeviation)) 
      return -stageIterator;  // That's not a face ! , failed on stage number 

    } 
} 
return 1; // That's a face 
    } 

回答

1

你需要做一些大的變化。首先,分類器 - >閾值是每個功能的閾值。 classifier-> alpha指向由2個元素組成的數組 - left_val和right_val(據我的理解)。你應該把這樣的分類環 -

a = classifier->alpha[0] 
b = classifier->alpha[1] 
t = *(classifier->threshold) 
stage_sum += classifierSum < t ? a : b 

然後通過比較與stage_classifiers :: CvHaarStageClassifier門檻stage_sum這是階段門檻,循環之後[I]。如果它通過所有的人都那麼它的臉! 如果你使用haarcascade_frontalface_alt.xml,'parent'和'next'在這裏是沒用的,它只是一個基於stump的級聯而不是基於樹。