GECKO 1.0
Human-computer interface based on hand gesture recognition
|
Extracts the number, position and orientation of the fingers. { std::vector< ConvexityDefect > passed_first_condition; //-- At this point, I lost all imagination available for variable naming std::vector< ConvexityDefect > passed_second_condition; std::vector< cv::Point > fingertips; std::vector< int > fingertips_indexes; //-- Check first assumption: min_inscribed_radius < depth_defect < max_enclosing_radius for(int i = 0; i < _hand_convexity_defects.size(); i++) { if ( _hand_convexity_defects[i].depth < _min_enclosing_circle_radius && _hand_convexity_defects[i].depth > _max_circle_inscribed_radius ) passed_first_condition.push_back( _hand_convexity_defects[i] ); } //-- Check second assumption: angle between convex is less than 90ยบ for (int i = 0; i < passed_first_condition.size(); i++) if ( findAngle(passed_first_condition[i].start, passed_first_condition[i].end, passed_first_condition[i].depth_point) < 90 ) passed_second_condition.push_back( passed_first_condition[i]); //std::cout << "[Debug] Fingertips candidates: " << passed_second_condition.size() << std::endl; //-- Find fingertips using k-curvature const int k =9; const int distance = 2; const int max_angle = 70; const int fingertip_threshold = 50; for (int i = 0; i < passed_second_condition.size(); i++) for (int ending = 0; ending < 2; ending++) { // if ( ending == 0) // std::cout << i << "-> Starting points: " << std::endl; // else // std::cout << i << "-> Ending points: " << std::endl; float best_angle = max_angle; int best = -10; for( int j = -distance; j < distance; j++) { int index_c; if ( ending == 0) index_c = passed_second_condition[i].start_index + j; else index_c = passed_second_condition[i].end_index + j; if (index_c < 0 ) index_c += _hand_contour[0].size(); if (index_c >= _hand_contour[0].size()) index_c -= _hand_contour[0].size(); int index_l = index_c - k; if (index_l < 0 ) index_l = index_l + _hand_contour[0].size(); int index_h = index_c + k; if (index_h >= _hand_contour[0].size() ) index_h = index_h - _hand_contour[0].size(); cv::Point center = _hand_contour[0].at( index_c ); cv::Point start = _hand_contour[0].at( index_l); cv::Point end = _hand_contour[0].at( index_h ); // cv::circle(dst, center, 2, cv::Scalar( 128, 180, 30) ); // cv::circle(dst, start, 2, cv::Scalar( 30, 180, 128)); // cv::circle(dst, end, 2, cv::Scalar( 30, 128, 180)); float current_angle = findAngle( start, end, center); //std::cout << "\tIt works! " << current_angle << std::endl; if ( current_angle < max_angle && current_angle < best_angle ) { best_angle = current_angle; best = index_c; } } //std::cout << "\tBest angle: " << best_angle << std::endl; std::cout.flush(); if ( best_angle != max_angle ) { //-- Check that the point you are about to include is not close to any point already detected bool detected = false; for (int n = 0; n < fingertips.size(); n++) { float distance = sqrt( pow( _hand_contour[0].at(best).x - fingertips.at(n).x, 2) + pow( _hand_contour[0].at(best).y - fingertips.at(n).y, 2) ); if ( distance < fingertip_threshold ) { detected = true; break; } } if ( !detected ) { fingertips_indexes.push_back( best ); fingertips.push_back( _hand_contour[0].at( fingertips_indexes.back())); } } } _hand_num_fingers = fingertips.size(); _hand_fingertips = fingertips; std::cout << "[Debug] Found " << _hand_num_fingers << " fingers." ; if (_hand_num_fingers > 5) { std::cout << "Not a (human) hand"; _hand_found = false; } std::cout << std::endl; //-- Find a second point to draw the finger lines: _hand_finger_line_origin.clear(); for(int i = 0; i < fingertips.size(); i++) { int index_l = fingertips_indexes[i] - k; if (index_l < 0 ) index_l = index_l + _hand_contour[0].size(); int index_h = fingertips_indexes[i] + k; if (index_h >= _hand_contour[0].size() ) index_h = index_h - _hand_contour[0].size(); cv::Point start = _hand_contour[0].at( index_l ); cv::Point end = _hand_contour[0].at( index_h ); cv::Point half_point = cv::Point( (start.x + end.x) /2, (start.y + end.y) / 2 ); _hand_finger_line_origin.push_back( half_point); } } |