利用OpenCV检测手掌(palm)和拳头(fist)
来源:互联网 发布:v软件测试模型 编辑:程序博客网 时间:2024/05/02 11:56
思路:利用训练好的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 , 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.
- 利用OpenCV检测手掌(palm)和拳头(fist)
- 手掌与拳头检测
- 交互系统的构建之(四)手掌与拳头检测加盟TLD
- 手势识别-----检测拳头
- 交互系统的构建之(四)手掌与拳头检测加盟TLD——http://blog.csdn.net/zouxy09/article/details/7930025
- 利用opencv进行面部和眼睛检测
- opencv跟踪手掌 代码
- 利用OpenCV检测肤色
- fist
- 利用opencv检测出矩形
- 利用OpenCV的convexHull和convexityDefects做凸包(凸壳)检测及凸包(凸壳)的缺陷检测
- 在OpenCV下利用霍夫变换进行直线检测和圆检测
- OpenCV手势识别-手掌特征提取
- 指尖检测 & 手掌检测 & 手指弯曲程度检测
- opencv学习笔记,利用contourArea和arcLength检测物体的轮廓面积和周长
- 利用OpenCV实现人脸检测
- Python利用OpenCV实现人脸检测
- 利用OpenCV实现人脸检测
- 深入理解Java内存模型(一)——基础
- 「勺」charCodeAt() //返回在指定的位置的字符的编码 20140810 ①文本处理
- C语言实现矩阵行列转换
- Pow(x, n)
- 如何在SD卡中创建数据库
- 利用OpenCV检测手掌(palm)和拳头(fist)
- Android开发命名规范提高代码可以读性
- 「连」concat() //连接字符串 20140811 ①文本处理
- getClass().getResourceAsStream() .获取配置文件的方法
- Java POI导出Excel时,字体单元格颜色示例
- 使用 html5 的十大原因
- Activity页面状态保存 持久化
- JAVA JDK配置
- 「鄙」fixed() //以打字机文本显示字符 20140812 ①文本处理