|
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);
}
}
|
1.7.4