I am using this code from the project FingertipTuio3D
std::vector<cv::Point2i> detectFingertips(cv::Mat1f z, float zMin = 0.0f, float zMax = 0.75f, cv::Mat1f& debugFrame = cv::Mat1f()) {
using namespace cv;
using namespace std;
bool debug = !debugFrame.empty();
vector<Point2i> fingerTips;
Mat handMask = z < zMax & z > zMin;
std::vector<std::vector<cv::Point>> contours;
findContours(handMask.clone(), contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); // we are cloning here since method will destruct the image
if (contours.size()) {
for (int i=0; i<contours.size(); i++) {
vector<Point> contour = contours[i];
Mat contourMat = Mat(contour);
double area = cv::contourArea(contourMat);
if (area > 3000) { // possible hand
Scalar center = mean(contourMat);
Point centerPoint = Point(center.val[0], center.val[1]);
vector<Point> approxCurve;
cv::approxPolyDP(contourMat, approxCurve, 20, true);
vector<int> hull;
cv::convexHull(Mat(approxCurve), hull);
// find upper and lower bounds of the hand and define cutoff threshold (don't consider lower vertices as fingers)
int upper = 640, lower = 0;
for (int j=0; j<hull.size(); j++) {
int idx = hull[j]; // corner index
if (approxCurve[idx].y < upper) upper = approxCurve[idx].y;
if (approxCurve[idx].y > lower) lower = approxCurve[idx].y;
}
float cutoff = lower - (lower - upper) * 0.1f;
// find interior angles of hull corners
for (int j=0; j<hull.size(); j++) {
int idx = hull[j]; // corner index
int pdx = idx == 0 ? approxCurve.size() - 1 : idx - 1; // predecessor of idx
int sdx = idx == approxCurve.size() - 1 ? 0 : idx + 1; // successor of idx
Point v1 = approxCurve[sdx] - approxCurve[idx];
Point v2 = approxCurve[pdx] - approxCurve[idx];
float angle = acos( (v1.x*v2.x + v1.y*v2.y) / (norm(v1) * norm(v2)) );
// low interior angle + within upper 90% of region -> we got a finger
if (angle < 1 && approxCurve[idx].y < cutoff) {
int u = approxCurve[idx].x;
int v = approxCurve[idx].y;
fingerTips.push_back(Point2i(u,v));
if (debug) {
cv::circle(debugFrame, approxCurve[idx], 10, Scalar(1), -1);
}
}
}
if (debug) {
// draw cutoff threshold
cv::line(debugFrame, Point(center.val[0]-100, cutoff), Point(center.val[0]+100, cutoff), Scalar(1.0f));
// draw approxCurve
for (int j=0; j<approxCurve.size(); j++) {
cv::circle(debugFrame, approxCurve[j], 10, Scalar(1.0f));
if (j != 0) {
cv::line(debugFrame, approxCurve[j], approxCurve[j-1], Scalar(1.0f));
} else {
cv::line(debugFrame, approxCurve[0], approxCurve[approxCurve.size()-1], Scalar(1.0f));
}
}
// draw approxCurve hull
for (int j=0; j<hull.size(); j++) {
cv::circle(debugFrame, approxCurve[hull[j]], 10, Scalar(1.0f), 3);
if(j == 0) {
cv::line(debugFrame, approxCurve[hull[j]], approxCurve[hull[hull.size()-1]], Scalar(1.0f));
} else {
cv::line(debugFrame, approxCurve[hull[j]], approxCurve[hull[j-1]], Scalar(1.0f));
}
}
}
}
}
}
return fingerTips;
}
When the code reaches this point vector<Point> contour = contours[i];
it fails with an AccessViolation:
Unhandled exception at 0x00b85039 in FingertipTuio3d.exe: 0xC0000005: Access violation reading location 0x00000008.
That location is in the size_type size() const
function of std::vector.
Any idea what is causing the problem, and how it might be fixed?
findContours
? – John BodeCV_EXPORTS void findContours( Mat& image, vector<vector<Point> >& contours, int mode, int method, Point offset=Point());
– Malfist