void HandDetection::detectHands(Mat& depthImage, Mat& color) { vector<Point> manoI, manoD; vector<vector<Point> > contornos; vector<Vec4i> hierarchy; vector<int> phull1, phull2; vector<CvConvexityDefect> fingerTips1, fingerTips2; vector<Point> curva1, curva2; Point ref(0, ROWS/2); vector<Point> palm2; int distancia1;// distancia2; distancia1 = 2000; // distancia2 = 2000; cv::findContours(depthImage, contornos, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE); for(size_t i=0; i<contornos.size(); i++) { double aux = contourArea(Mat(contornos[i])); if(aux > 0 && aux >= 1000 && aux <= 35000) {//35000 // Comparar cada blob en base a la distancia con su punto de "tracking" Rect r = boundingRect(Mat(contornos[i])); Point punto = Utils::getRectCenter(r); int d = (int)Utils::OXDistance(punto, ref); int aux1 = (int)Utils::OXDistance(punto, m_left_hand->getEstimatedPoint()); // int aux2 = (int)Utils::OXDistance(punto, m_right_hand->getEstimatedPoint()); bool isleft = false; if(d < COLS/2 ){//&& area > _leftHand->getArea() manoI = contornos[i]; m_left_hand->setContour(manoI); m_left_hand->setCenter(punto); m_left_hand->setWhich(LEFT_HAND); isleft = true; distancia1 = aux1; } if(d >= COLS/2){ manoD = contornos[i]; m_right_hand->setContour(manoD); m_right_hand->setCenter(punto); m_right_hand->setWhich(RIGHT_HAND); } } } m_left_hand->trackObject(color);//tienes q ver que pasa si lefhand vale lo mismo q antes // m_right_hand->trackObject(color); Point p = m_right_hand->getCenter(); circle(color, p, 10, Scalar(200,200,200), 5, -1); //Calculamos los poligonos de Hull (convex Hull) if(manoD.size() > 0){ Rect r1 = boundingRect(Mat(manoD)); rectangle(color, r1, Scalar(0,0,255), 3); Mat matriz1(manoD); if(matriz1.rows > 0 && matriz1.cols > 0){ //Calculamos el poligono convexo que recubre la mano //Simplificamos, primero, el contorno. approxPolyDP(matriz1, curva1, APPROX_POLY_SIDES, true);//20 Mat curvi(curva1); convexHull(curvi, phull1, CV_CLOCKWISE); vector<Point> poly; for(int i=0; i<(int)phull1.size(); i++){ poly.push_back(curva1[phull1[i]]); } //Ahora dibujamos los defectos de convexidad vector<CvConvexityDefect> defects; findConvexityDefects(curva1, phull1, defects);//pasar curva2 a int* //De todos los start y end, te quedas con los que coincidan del poligono aproximado findFingerTips(curva1, defects, fingerTips1); int fingersCount = (int)fingerTips1.size(); m_right_hand->setFingers(fingersCount); } } if(manoI.size() > 0){ Rect r2 = boundingRect(Mat(manoI)); rectangle(color, r2, Scalar(255,0,0), 3); Mat matriz2(manoI); if(matriz2.rows > 0 && matriz2.cols > 0){ //Calculamos el poligono convexo que recubre la mano //Simplificamos, primero, el contorno. approxPolyDP(matriz2, curva2, APPROX_POLY_SIDES, true);//20 Mat curvi(curva2); convexHull(curvi, phull2, CV_CLOCKWISE); vector<Point> poly; for(int i=0; i<(int)phull2.size(); i++){ poly.push_back(curva2[phull2[i]]); } //Ahora dibujamos los defectos de convexidad vector<CvConvexityDefect> defects; findConvexityDefects(curva2, phull2, defects);//pasar curva2 a int* //De todos los start y end, te quedas con los que coincidan del poligono aproximado findFingerTips(curva2, defects, fingerTips2); //Analizamos la informacion de los supuestos dedos for(int i=0; i<(int)fingerTips2.size(); i++){ CvPoint cvp1 = *(fingerTips2.at(i).start); CvPoint cvp2 = *(fingerTips2.at(i).end); CvPoint cvdef = *(fingerTips2.at(i).depth_point); Point p1(cvp1.x, cvp1.y); Point p2(cvp2.x, cvp2.y); Point p3(cvdef.x, cvdef.y); line(color, p1, p3, Scalar(0, 255, 0), 1, CV_AA); line(color, p2, p3, Scalar(0, 255, 0), 1, CV_AA); cv::circle(color, p1, 10, Scalar(200,200,200), -1, CV_AA); cv::circle(color, p3, 10, Scalar(0,0,0), 2, CV_AA); palm2.push_back(p3); } //Obtenemos el centro de la palma // if(palm2.size() > 0){ // minEnclosingCircle(Mat(palm2), center2, radius2); // cv::circle(color, center2, radius2, Scalar(255,255,255), -1, CV_AA); // } int fingersCount = (int)fingerTips2.size(); m_left_hand->setFingers(fingersCount); } } }
std::pair<vector<Point>, std::pair<Point,double>> Detect::operator() (Mat& frame, Mat& raw, int count) { vector<Point> tips; // first find the curves in the image vector<vector<Point>> polyCurves = getPolyCurves(frame); //std::cout << polyCurves.size() << std::endl; // Find max inscribed circle for the 0th polycurve and draw it. std::pair<Point, double> maxCircle = findMaxInscribedCircle(polyCurves, raw); circle(raw, maxCircle.first, maxCircle.second, cv::Scalar(220,75,20), 1, CV_AA); // Good PolyCurve is with 3.5 * max inscribed radius vector<vector<Point>> goodPolyCurves; getRegionOfInterest(goodPolyCurves, polyCurves, maxCircle); // draw good poly curve drawContours(raw,goodPolyCurves, -1 , cv::Scalar(0,255,0), 2); // Find min enclosing circle on goodPolyCurve and draw it std::pair<Point2f, double> minCircle = findMinEnclosingCircle(goodPolyCurves); circle(raw, minCircle.first, minCircle.second, cv::Scalar(220,75,20), 1, CV_AA); // now find the convex hull for each polyCurve if (goodPolyCurves.size() < 1) { return std::pair<vector<Point>, std::pair<Point, double>>(tips, maxCircle); } // Get convex hulls vector<vector<int>> hullIndices = getConvexHulls(goodPolyCurves); vector<vector<Point>> hullPoints; for(int i = 0; i < goodPolyCurves.size(); i++) { if (goodPolyCurves[i].size() > 0) { vector<Point> hullPoint; convexHull(goodPolyCurves[i], hullPoint); hullPoints.push_back(hullPoint); } } // Draw the convex hulls drawContours(raw, hullPoints, -1, cv::Scalar(255, 0, 0), 2); for (int i = 0; i < 1; ++i) { vector<Vec4i> defects; // find convexity defects for each poly curve and draw them convexityDefects(goodPolyCurves[i], hullIndices[i], defects); defects = filterDefects(defects); vector<Point> defectEnds; for (int j = 0; j < defects.size(); ++j) { Vec4i& defect = defects[j]; int startIdx = defect[0]; int endIdx = defect[1]; int farIdx = defect[2]; Point start = goodPolyCurves[i][startIdx]; Point end = goodPolyCurves[i][endIdx]; Point far = goodPolyCurves[i][farIdx]; if(euclideanDist(far, start) > maxCircle.second) { defectEnds.push_back(start); defectEnds.push_back(end); } } tips = findFingerTips(defectEnds, maxCircle, raw); } flip(raw, raw, 1); imshow("hand", raw); // movie code (we should return the frame to HandMade and put movie code there with the others.) if(makeMoviesD) { char buffer[30]; sprintf(buffer, "detected/detected_%03d.jpg", count++); imwrite(buffer, raw); } return std::pair<vector<Point>, std::pair<Point, double>>(tips, maxCircle); }