利用OpenCV檢測手掌(palm)和拳頭(fist)

思路:利用訓練好的palm.xml和fist.xml文件,用OpenCV的CascadeClassifier對每一幀圖像檢測palm和fist,之後對多幀中檢測到的palm和fist進行聚類分組,滿足分組條件的區域爲最終檢測結果。


代碼:

 #include "opencv2/objdetect/objdetect.hpp"
 #include "opencv2/highgui/highgui.hpp"
 #include "opencv2/imgproc/imgproc.hpp"

 #include <iostream>
 #include <stdio.h>

 using namespace std;
 using namespace cv;

 /** Function Headers */
 void detectAndDisplay( Mat frame );
 void RestoreVectors(vector<vector<Rect>>& vecs_bank, vector<Rect>& vecAll);

 /** Global variables */
 String palm_cascade_name = "palm.xml";
 String fist_cascade_name = "fist.xml";
 CascadeClassifier palm_cascade;
 CascadeClassifier fist_cascade;
 string window_name = "Capture - Palm and fist detection";

 /** @function main */
 int main( int argc, const char** argv )
 {
   CvCapture* capture;
   Mat frame;

   //-- 1. Load the cascades
   if( !palm_cascade.load( palm_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };
   if( !fist_cascade.load( fist_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };

   //-- 2. Read the video stream
   capture = cvCaptureFromCAM( -1 );
   if( capture )
   {
     while( true )
     {
   frame = cvQueryFrame( capture );

   //-- 3. Apply the classifier to the frame
       if( !frame.empty() )
       { detectAndDisplay( frame ); }
       else
       { printf(" --(!) No captured frame -- Break!"); break; }

       int c = waitKey(10);
       if( (char)c == 'q' || (char)c == 'Q' || 27 == c) { break; }
      }
   }

   cvReleaseCapture(&capture);
   return 0;
 }

/** @function detectAndDisplay */
void detectAndDisplay( Mat frame )
{
  std::vector<Rect> faces;
  std::vector<Rect> palms;
  std::vector<Rect> fists;
  static vector<vector<Rect>> palms_bank;
  static vector<vector<Rect>> fists_bank;
  const int MAX_NUM = 3;
  Mat frame_gray;

  cvtColor( frame, frame_gray, CV_BGR2GRAY );
  equalizeHist( frame_gray, frame_gray );


  //-- Palm detection
  palm_cascade.detectMultiScale( frame_gray, palms, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
  palms_bank.push_back(palms);
  if(palms_bank.size() > MAX_NUM)
	  palms_bank.erase(palms_bank.begin());

  vector<Rect> palmAll;
  RestoreVectors(palms_bank, palmAll);
  groupRectangles(palmAll, 2);

   for( size_t j = 0; j < palmAll.size(); j++ )
  {
	rectangle(frame, palmAll[j], Scalar(0,255,0), 2);
  }

  //-- Fist detection
  fist_cascade.detectMultiScale( frame_gray, fists, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
  fists_bank.push_back(fists);
  if(fists_bank.size() > MAX_NUM)
	  fists_bank.erase(fists_bank.begin());

  vector<Rect> fistAll;
  RestoreVectors(fists_bank, fistAll);
  groupRectangles(fistAll, 2);

   for( size_t j = 0; j < fistAll.size(); j++ )
  {
	rectangle(frame, fistAll[j], Scalar(0,0,255), 2);
  }

  //-- Show what you got
  imshow( window_name, frame );
 }

void RestoreVectors(vector<vector<Rect>>& vecs_bank, vector<Rect>& vecAll)
{
	for(size_t i = 0; i < vecs_bank.size(); i++){
		vecAll.insert(vecAll.end(), vecs_bank[i].begin(), vecs_bank[i].end());
	}
}

首先,分類器palm_cascade和fist_cascade分別讀入palm.xml和fist.xml文件;

然後,分類器palm_cascade和fist_cascade分別調用detectMultiScale函數對輸入的灰度圖像進行檢測,檢測的結果是一系列Rect區域,分別存入palms和fists中;

之後,將每幀圖像檢測的結果palms和fists再存入palms_bank和fists_bank中,palms_bank和fists_bank中保存了MAX_NUM幀的檢測結果;

之後,調用RestoreVectors函數,將palms_bank和fists_bank中的結果重新存入vector結構中(因爲groupRectangles接受的參數是vector<Rect>,而不是vector<vector<Rect>>),並調用groupRectangles進行聚類。

最後,將聚類後的結果畫出來,palm用綠色畫出,fist用紅色畫出。


groupRectangles的說明如下:

groupRectangles對rectList中的Rect進行聚類,近似大小和近似位置的Rect被分爲一類(cluster),只有當一類中的Rect數目超過groupThreshold時,該類別纔會被保留,仍保留在rectList中。


參考:

[1] groupRectangles的說明文檔

[2] palm.xml和fist.xml的下載地址

[3] 人臉和眼睛檢測的opencv示例代碼


代碼,palm.xml和fist.xml文件,說明文檔可以從這裏下載:

http://download.csdn.net/detail/lichengyu/7751671

groupRectangles

Groups the object candidate rectangles.

C++: void groupRectangles(vector<Rect>& rectList, int groupThreshold, double eps=0.2)
C++: void groupRectangles(vector<Rect>& rectList, vector<int>& weights, intgroupThreshold, double eps=0.2)
Python: cv2.groupRectangles(rectList, groupThreshold[, eps]) → rectList, weights
Parameters:
  • rectList – Input/output vector of rectangles. Output vector includes retained and grouped rectangles. (The Python list is not modified in place.)
  • groupThreshold – Minimum possible number of rectangles minus 1. The threshold is used in a group of rectangles to retain it.
  • eps – Relative difference between sides of the rectangles to merge them into a group.

The function is a wrapper for the generic function partition() . It clusters all the input rectangles using the rectangle equivalence criteria that combines rectangles with similar sizes and similar locations. The similarity is defined by eps. When eps=0 , no clustering is done at all. If \texttt{eps}\rightarrow +\inf , all the rectangles are put in one cluster. Then, the small clusters containing less than or equal to groupThreshold rectangles are rejected. In each other cluster, the average rectangle is computed and put into the output rectangle list.


發佈了140 篇原創文章 · 獲贊 18 · 訪問量 79萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章