Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

unable to understand this finger counting code

hi, can anybody explain me this code: this code is for counting number of finger. this is the input image image description

 // feature extraction.cpp : Defines the entry point for the console application.
//
//--------------------------------------In the name of GOD
//-------------------------------BOW+SVM by Mohammad Reza Mostajabi
//#include "stdafx.h"
#include <opencv\cv.h>
#include <opencv\highgui.h>
//#include <opencv\ml.h>
#include <stdio.h>
#include <iostream>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/nonfree/features2d.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2\ml\ml.hpp>
#include <vector>
using namespace cv;
using namespace std;

using std::cout;
using std::cerr;
using std::endl;
using std::vector;

RNG rnga(12345);



inline void mix_channels(cv::Mat const &src, cv::Mat &dst, std::initializer_list<int> from_to)
{
    cv::mixChannels(&src, 1, &dst, 1, std::begin(from_to), from_to.size() / 2);
}

double angle(std::vector<cv::Point>& contour, int pt, int r)
{
    int size = contour.size();
    cv::Point p0 = (pt>0) ? contour[pt%size] : contour[size - 1 + pt];
    cv::Point p1 = contour[(pt + r) % size];
    cv::Point p2 = (pt>r) ? contour[pt - r] : contour[size - 1 - r];

    double ux = p0.x - p1.x;
    double uy = p0.y - p1.y;
    double vx = p0.x - p2.x;
    double vy = p0.y - p2.y;
    return (ux*vx + uy*vy) / sqrt((ux*ux + uy*uy)*(vx*vx + vy*vy));
}

int rotation(std::vector<cv::Point>& contour, int pt, int r)
{
    int size = contour.size();
    cv::Point p0 = (pt>0) ? contour[pt%size] : contour[size - 1 + pt];
    cv::Point p1 = contour[(pt + r) % size];
    cv::Point p2 = (pt>r) ? contour[pt - r] : contour[size - 1 - r];

    double ux = p0.x - p1.x;
    double uy = p0.y - p1.y;
    double vx = p0.x - p2.x;
    double vy = p0.y - p2.y;
    return (ux*vy - vx*uy);
}

bool isEqual(double a, double b)
{
    return fabs(a - b) <= 1e-7;
}
int main()
{

    Mat input = imread("C:\\Users\\Intern-3\\Desktop\\IPF\\2.png");

    Size size = input.size();
    int erosion_size = 1;
    Mat HSV, threshold;
    cvtColor(input, HSV, COLOR_BGR2HSV);
    inRange(HSV, cv::Scalar(0, 0, 100), cv::Scalar(0, 0, 255), threshold);

    Mat erodeElement = getStructuringElement(MORPH_RECT, cv::Size(5, 5));
    Mat dilateElement = getStructuringElement(MORPH_RECT, cv::Size(8, 8));

    erode(threshold, threshold, erodeElement);

    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    Mat mask = threshold;
    findContours(mask.clone(), contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point(0, 0));

    /// Draw contours
    Mat drawing = Mat::zeros(mask.size(), CV_8UC3);
    for (int i = 0; i< contours.size(); i++)
    {
        Scalar color = Scalar(rnga.uniform(0, 255), rnga.uniform(0, 255), rnga.uniform(0, 255));
        drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
    }
    cout << "Contours = " << contours.size() << endl;
    for (int i = 0; i < contours.size(); i++)
    {
        cout << "area : " << contourArea(contours[i]) << endl;
    }
    imshow("contour", drawing);

    if (!contours.empty())
    {
        for (int i = 0; i<contours.size(); i++)
        {
            if (cv::contourArea(contours[i])>500)
            {
                Point center;
                std::vector<cv::Point> fingers;
                std::vector<cv::Point> contour;

                cv::Moments m = cv::moments(contours[i]);
                center.x = m.m10 / m.m00;
                center.y = m.m01 / m.m00;

                for (int j = 0; j < contours[i].size(); j += 16)
                {
                    double cos0 = angle(contours[i], j, 40);

                    if ((cos0 > 0.5) && (j + 16<contours[i].size()))
                    {
                        double cos1 = angle(contours[i], j - 16, 40);
                        double cos2 = angle(contours[i], j + 16, 40);
                        double maxCos = std::max(std::max(cos0, cos1), cos2);
                        bool equal = isEqual(maxCos, cos0);
                        signed int z = rotation(contours[i], j, 40);
                        if (equal == 1 && z<0)
                        {
                            fingers.push_back(contours[i][j]);
                        }
                    }
                }
                contour = contours[i];
                cout << "Finger Count : "<<fingers.size()<<endl;
                //hands.push_back(tmp);
            }
        }
    }

    imshow("input", input);
    waitKey(0);
}

in the following code i m not able to understand why this is being done to calculate angle. which 3 points (p0,p1,p2) is being considered to find the angle and its rotation.

the code block which i am not able to understand is :

if (cv::contourArea(contours[i])>500)
            {
                Point center;
                std::vector<cv::Point> fingers;
                std::vector<cv::Point> contour;

                cv::Moments m = cv::moments(contours[i]);
                center.x = m.m10 / m.m00;
                center.y = m.m01 / m.m00;

                for (int j = 0; j < contours[i].size(); j += 16)
                {
                    double cos0 = angle(contours[i], j, 40);

                    if ((cos0 > 0.5) && (j + 16<contours[i].size()))
                    {
                        double cos1 = angle(contours[i], j - 16, 40);
                        double cos2 = angle(contours[i], j + 16, 40);
                        double maxCos = std::max(std::max(cos0, cos1), cos2);
                        bool equal = isEqual(maxCos, cos0);
                        signed int z = rotation(contours[i], j, 40);
                        if (equal == 1 && z<0)
                        {
                            fingers.push_back(contours[i][j]);
                        }
                    }
                }
                contour = contours[i];
                cout << "Finger Count : "<<fingers.size()<<endl;
                //hands.push_back(tmp);
            }