GECKO 1.0
Human-computer interface based on hand gesture recognition
void HandDescriptor::fingerExtraction ( ) [private]

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);
    }
}
 All Classes Functions Variables