Hi friends, I have written some code to detect hand. This code can detect my hand and cam find convexity defects but i dont know how to count convexity defects. Please help me. i am very confuse. Please help :) Thank you so much.... :)
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include<Windows.h>
using namespace cv;
using namespace std;
int minH = 0, maxH = 20, minS = 30, maxS = 150, minV = 60, maxV = 255;
Mat frame;
int Count=0 ;
int fingers = 0;
float innerAngle(float px1, float py1, float px2, float py2, float cx1, float cy1)
{
float dist1 = std::sqrt((px1 - cx1)*(px1 - cx1) + (py1 - cy1)*(py1 - cy1));
float dist2 = std::sqrt((px2 - cx1)*(px2 - cx1) + (py2 - cy1)*(py2 - cy1));
float Ax, Ay;
float Bx, By;
float Cx, Cy;
//find closest point to C
//printf("dist = %lf %lf\n", dist1, dist2);
Cx = cx1;
Cy = cy1;
if (dist1 < dist2)
{
Bx = px1;
By = py1;
Ax = px2;
Ay = py2;
}
else {
Bx = px2;
By = py2;
Ax = px1;
Ay = py1;
}
float Q1 = Cx - Ax;
float Q2 = Cy - Ay;
float P1 = Bx - Ax;
float P2 = By - Ay;
float A =acos((P1*Q1 + P2*Q2) / (sqrt(P1*P1 + P2*P2) * sqrt(Q1*Q1 + Q2*Q2)));
A = A * 180 / CV_PI;
return A;
}
void CallbackFunc(int event, int x, int y, int flags, void* userdata)
{
Mat RGB = frame(Rect(x, y, 1, 1));
Mat HSV;
cvtColor(RGB, HSV, CV_BGR2HSV);
Vec3b pixel = HSV.at<Vec3b>(0, 0);
if (event == EVENT_LBUTTONDBLCLK) // on double left clcik
{
cout << "Click" << endl;
int h = pixel.val[0];
int s = pixel.val[1];
int v = pixel.val[2];
if (Count == 0)
{
minH = h;
maxH = h;
minS = s;
maxS = s;
minV = v;
maxV = v;
}
else
{
if (h < minH)
{
minH = h;
}
else if (h > maxH)
{
maxH = h;
}
if (s < minS)
{
minS = s;
}
else if (s > maxS)
{
maxS = s;
}
if (v < minV)
{
minV = v;
}
else if (v > maxV)
{
maxV = v;
}
}
Count++;
}
cout << pixel << endl;
}
int main()
{
cv::VideoCapture cap(0);
const char* windowName = "Fingertip detection";
cv::namedWindow(windowName);
cv::setMouseCallback(windowName, CallbackFunc, NULL);
int inAngleMin = 200, inAngleMax = 300, angleMin = 180, angleMax = 359, lengthMin = 10, lengthMax = 80;
/* cv::createTrackbar("Inner angle min", windowName, &inAngleMin, 360);
cv::createTrackbar("Inner angle max", windowName, &inAngleMax, 360);
cv::createTrackbar("Angle min", windowName, &angleMin, 360);
cv::createTrackbar("Angle max", windowName, &angleMax, 360);
cv::createTrackbar("Length min", windowName, &lengthMin, 100);
cv::createTrackbar("Length max", windowName, &lengthMax, 100);*/
while (1)
{
cap >> frame;
cv::Mat hsv;
cv::cvtColor(frame, hsv, CV_BGR2HSV);
cv::inRange(hsv, cv::Scalar(minH, minS, minV), cv::Scalar(maxH, maxS, maxV), hsv);
// Pre processing
int blurSize = 5;
int elementSize = 5;
cv::medianBlur(hsv, hsv, blurSize);
cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(2 * elementSize + 1, 2 * elementSize + 1), cv::Point(elementSize, elementSize));
cv::dilate(hsv, hsv, element);
// Contour detection
vector<std::vector<cv::Point> > contours;
vector<cv::Vec4i> hierarchy;
cv::findContours(hsv, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
size_t largestContour = 0;
for (size_t i = 1; i < contours.size(); i++)
{
if (cv::contourArea(contours[i]) > cv::contourArea(contours[largestContour]))
largestContour = i;
}
cv::drawContours(frame, contours, largestContour, cv::Scalar(0, 0, 255), 1);
// Convex hull
if (!contours.empty())
{
vector<vector<Point> > hull(1);
convexHull(Mat(contours[largestContour]), hull[0], false);
cv::drawContours(frame, hull, 0, Scalar(0, 255, 0), 3);
if (hull[0].size() > 2)
{
Point2f mycenter;
float radii;
vector<int> hullIndexes;
convexHull(Mat(contours[largestContour]), hullIndexes, true);
vector<Vec4i> convexityDefects;
cv::convexityDefects(Mat(contours[largestContour]), hullIndexes, convexityDefects);
Rect boundingBox = cv::boundingRect(hull[0]);
rectangle(frame, boundingBox, cv::Scalar(255, 0, 0));
Point center = Point(boundingBox.x + boundingBox.width / 2, boundingBox.y + boundingBox.height / 2);
vector<Point> validPoints;
vector<vector<Vec4i> >defects(contours.size());
// minEnclosingCircle(contours[largestContour], mycenter, radii);
for (size_t i = 0; i < convexityDefects.size(); i++)
{
cv::Point p1 = contours[largestContour][convexityDefects[i][0]];
cv::Point p2 = contours[largestContour][convexityDefects[i][1]];
cv::Point p3 = contours[largestContour][convexityDefects[i][2]];
double angle = std::atan2(center.y - p1.y, center.x - p1.x) * 180 / CV_PI;
double inAngle = innerAngle(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
double length = sqrt(std::pow(p1.x - p3.x, 2) + std::pow(p1.y - p3.y, 2));
if (angle > angleMin - 180 && angle < angleMax - 180 && inAngle > inAngleMin - 180 && inAngle < inAngleMax - 180 && length > lengthMin / 100.0 * boundingBox.height && length < lengthMax / 100.0 * boundingBox.height)
{
validPoints.push_back(p1);
}
}
for (size_t i = 0; i < validPoints.size(); i++)
{
circle(frame, validPoints[i], 9, cv::Scalar(0, 255, 0), 2);
}
}
cv::imshow(windowName, frame);
putText(frame, "Fingers : " + to_string(fingers), Point(50, 100), 2, 2, CV_RGB(0, 255, 0), 4, 8);
cout << to_string(fingers) << endl;
waitKey(200);
if (cv::waitKey(30) >= 0) break;
}
}
return 0;
}