├── HandDetector.cpp ├── HandDetector.h ├── README.md └── main.cpp /HandDetector.cpp: -------------------------------------------------------------------------------- 1 | #include "HandDetector.h" 2 | 3 | using namespace cv; 4 | using namespace std; 5 | 6 | /******************************************************* 7 | ******************************************************** 8 | *********************HandDetector*********************** 9 | ******************************************************** 10 | *******************************************************/ 11 | 12 | void HandDetector::setParams(HandDetector::Params& p) 13 | { 14 | param.area = p.area; 15 | param.cosThreshold = p.cosThreshold; 16 | param.equalThreshold = p.equalThreshold; 17 | param.r = p.r; 18 | param.step = p.step; 19 | } 20 | 21 | bool HandDetector::isEqual(double a, double b) 22 | { 23 | return fabs(a - b) <= param.equalThreshold; 24 | } 25 | 26 | double HandDetector::angle(std::vector& contour, int pt, int r) 27 | { 28 | int size = contour.size(); 29 | cv::Point p0=(pt>0)?contour[pt%size]:contour[size-1+pt]; 30 | cv::Point p1=contour[(pt+r)%size]; 31 | cv::Point p2=(pt>r)?contour[pt-r]:contour[size-1-r]; 32 | 33 | double ux=p0.x-p1.x; 34 | double uy=p0.y-p1.y; 35 | double vx=p0.x-p2.x; 36 | double vy=p0.y-p2.y; 37 | return (ux*vx + uy*vy)/sqrt((ux*ux + uy*uy)*(vx*vx + vy*vy)); 38 | } 39 | 40 | signed int HandDetector::rotation(std::vector& contour, int pt, int r) 41 | { 42 | int size = contour.size(); 43 | cv::Point p0=(pt>0)?contour[pt%size]:contour[size-1+pt]; 44 | cv::Point p1=contour[(pt+r)%size]; 45 | cv::Point p2=(pt>r)?contour[pt-r]:contour[size-1-r]; 46 | 47 | double ux=p0.x-p1.x; 48 | double uy=p0.y-p1.y; 49 | double vx=p0.x-p2.x; 50 | double vy=p0.y-p2.y; 51 | return (ux*vy - vx*uy); 52 | } 53 | 54 | void HandDetector::detect(cv::Mat& mask, std::vector& hands) 55 | { 56 | hands.clear(); 57 | vector> contours; 58 | vector hierarchy; 59 | 60 | findContours(mask.clone(), contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point(0, 0) ); 61 | if(!contours.empty()) 62 | { 63 | for(int i=0; iparam.area) 66 | { 67 | Hand tmp; 68 | cv::Moments m=cv::moments(contours[i]); 69 | tmp.center.x=m.m10/m.m00; 70 | tmp.center.y=m.m01/m.m00; 71 | 72 | for(int j = 0; j < contours[i].size(); j+= param.step ) 73 | { 74 | double cos0 = angle (contours[i], j, param.r); 75 | 76 | if ((cos0 > 0.5)&&(j+param.step& hands) 98 | { 99 | int size = hands.size(); 100 | std::vector> c; 101 | for(int i = 0; i 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class Hand 14 | { 15 | public: 16 | Hand(){}; 17 | ~Hand(){}; 18 | std::vector fingers; 19 | cv::Point center; 20 | std::vector contour; 21 | }; 22 | 23 | class HandDetector 24 | { 25 | public: 26 | struct Params 27 | { 28 | int area; 29 | int r; 30 | int step; 31 | double cosThreshold; 32 | double equalThreshold; 33 | }; 34 | 35 | public: 36 | HandDetector(){}; 37 | ~HandDetector(){}; 38 | 39 | void detect(cv::Mat& mask, std::vector& hands); 40 | void setParams(Params& p); 41 | private: 42 | Params param; 43 | signed int rotation(std::vector& contour, int pt, int r); 44 | double angle(std::vector& contour, int pt, int r); 45 | bool isEqual(double a, double b); 46 | }; 47 | 48 | void drawHands(cv::Mat& image, std::vector& hands); 49 | 50 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | HandDetector 2 | ============ 3 | 4 | Hand and Fingertip Detecot with OpenCV -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "HandDetector.h" 3 | 4 | using namespace std; 5 | using namespace cv; 6 | 7 | int main() 8 | { 9 | cv::VideoCapture cap(CV_CAP_OPENNI); 10 | cv::namedWindow("depth", 1); 11 | cv::namedWindow("bgr", 1); 12 | 13 | HandDetector::Params p; 14 | p.area=1000; 15 | p.cosThreshold=0.5; 16 | p.equalThreshold=1e-7; 17 | p.r=40; 18 | p.step=16; 19 | 20 | HandDetector hDetector; 21 | hDetector.setParams(p); 22 | std::vector hands; 23 | 24 | while(1) 25 | { 26 | cv::Mat depthMap; 27 | cv::Mat bgrImage; 28 | 29 | cap.grab(); 30 | 31 | cap.retrieve( depthMap, CV_16UC1 ); 32 | cap.retrieve( bgrImage, CV_32FC1 ); 33 | 34 | cv::Mat tmp; 35 | cv::cvtColor(depthMap, tmp, CV_GRAY2BGR); 36 | 37 | cv::threshold(depthMap, depthMap, 60, 255, cv::THRESH_BINARY); 38 | 39 | hDetector.detect(depthMap, hands); 40 | 41 | if(!hands.empty()) 42 | { 43 | drawHands(tmp, hands); 44 | drawHands(bgrImage, hands); 45 | } 46 | 47 | cv::imshow("depth", tmp); 48 | cv::imshow("bgr", bgrImage); 49 | 50 | if( cv::waitKey( 20 ) >= 0 ) 51 | break; 52 | } 53 | 54 | cv::waitKey(); 55 | return 0; 56 | } --------------------------------------------------------------------------------