1

I have stored the defects using convexity defects in an 4 element vector integer array using vec4i.

My convex hull array is in hull element and contours in Contours; What i want to do is draw a line from start point of a convexity defect to the end point of one. For this i need to access the element start index which is present in the vec4i of a defects vector!

How do i do this??

 #include <opencv\cv.h> #include <opencv2\highgui\highgui.hpp> #include<opencv\cvaux.h> #include<opencv\cxcore.h> #include <opencv2\imgproc\imgproc.hpp> #include <iostream> #include<conio.h> #include <stdlib.h> using namespace cv; using namespace std; int main(){ Mat img, frame, img2, img3; VideoCapture cam(0); while (true){ cam.read(frame); cvtColor(frame, img, CV_BGR2HSV); //thresholding inRange(img, Scalar(0, 143, 86), Scalar(39, 255, 241), img2); imshow("hi", img2); //finding contours vector<vector<Point>> Contours; vector<Vec4i> hier; //morphological transformations erode(img2, img2, getStructuringElement(MORPH_RECT, Size(3, 3))); erode(img2, img2, getStructuringElement(MORPH_RECT, Size(3, 3))); dilate(img2, img2, getStructuringElement(MORPH_RECT, Size(8, 8))); dilate(img2, img2, getStructuringElement(MORPH_RECT, Size(8, 8))); //finding the contours required findContours(img2, Contours, hier, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, Point(0, 0)); //finding the contour of largest area and storing its index int lrgctridx = 0; int maxarea = 0; for (int i = 0; i < Contours.size(); i++) { double a = contourArea(Contours[i]); if (a> maxarea) { maxarea = a; lrgctridx = i; } } //convex hulls vector<vector<Point> >hull(Contours.size()); vector<vector<Vec4i>> defects(Contours.size()); for (int i = 0; i < Contours.size(); i++) { convexHull(Contours[i], hull[i], false); convexityDefects(Contours[i], hull[i], defects[i]); } //REQUIRED contour is detected,then convex hell is found and also convexity defects are found and stored in defects if (maxarea>100){ drawContours(frame, hull, lrgctridx, Scalar(255, 255, 255), 1, 8, vector<Vec4i>(), 0, Point()); \\ drawing the required lines joining defects!im facing problem on how to acheive this since i dont know how to access the elements stored in defects line(frame, \\startindex, \\endindex, \\color, 1); } imshow("output", frame); char key = waitKey(33); if (key == 27) break; } 

}

Also my output window shows error when i add the convexityDefects(..) line i think it is in wrong format! Thanks in advance.

19
  • what's stored in the Vec4i ? Commented Jul 11, 2015 at 13:24
  • I have added my code. I have tried and stored the information about the convexity defects in the the 4 element vector array.Also my output window crashes on adding the line convexityDefects(...) in the code.I think it is formatted wrongly. Commented Jul 11, 2015 at 13:58
  • that code seems familiar.. :D Commented Jul 11, 2015 at 14:03
  • That is because i posted part of it yesterday..im learning step by step..working on hand gesture identification! Commented Jul 11, 2015 at 14:09
  • 1
    see my answer. Next time spend a little more time on google and SO Commented Jul 11, 2015 at 14:52

1 Answer 1

6

convexityDefects needs a

Convex hull obtained using convexHull() that should contain indices of the contour points that make the hull.

that contains more than 3 indices. So you need this:

vector<vector<Point> >hull(Contours.size()); vector<vector<int> > hullsI(Contours.size()); // Indices to contour points vector<vector<Vec4i>> defects(Contours.size()); for (int i = 0; i < Contours.size(); i++) { convexHull(Contours[i], hull[i], false); convexHull(Contours[i], hullsI[i], false); if(hullsI[i].size() > 3 ) // You need more than 3 indices { convexityDefects(Contours[i], hullsI[i], defects[i]); } } 

Then your drawing part is (adapted from here):

/// Draw convexityDefects for (int i = 0; i < Contours.size(); ++i) { for(const Vec4i& v : defects[i]) { float depth = v[3] / 256; if (depth > 10) // filter defects by depth, e.g more than 10 { int startidx = v[0]; Point ptStart(Contours[i][startidx]); int endidx = v[1]; Point ptEnd(Contours[i][endidx]); int faridx = v[2]; Point ptFar(Contours[i][faridx]); line(frame, ptStart, ptEnd, Scalar(0, 255, 0), 1); line(frame, ptStart, ptFar, Scalar(0, 255, 0), 1); line(frame, ptEnd, ptFar, Scalar(0, 255, 0), 1); circle(frame, ptFar, 4, Scalar(0, 255, 0), 2); } } } 

Complete code

#include <opencv2\opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main() { Mat img, frame, img2, img3; VideoCapture cam(0); while (true){ cam.read(frame); cvtColor(frame, img, CV_BGR2HSV); //thresholding inRange(img, Scalar(0, 143, 86), Scalar(39, 255, 241), img2); imshow("hi", img2); //finding contours vector<vector<Point>> Contours; vector<Vec4i> hier; //morphological transformations erode(img2, img2, getStructuringElement(MORPH_RECT, Size(3, 3))); erode(img2, img2, getStructuringElement(MORPH_RECT, Size(3, 3))); dilate(img2, img2, getStructuringElement(MORPH_RECT, Size(8, 8))); dilate(img2, img2, getStructuringElement(MORPH_RECT, Size(8, 8))); //finding the contours required findContours(img2, Contours, hier, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, Point(0, 0)); //finding the contour of largest area and storing its index int lrgctridx = 0; int maxarea = 0; for (int i = 0; i < Contours.size(); i++) { double a = contourArea(Contours[i]); if (a> maxarea) { maxarea = a; lrgctridx = i; } } //convex hulls vector<vector<Point> >hull(Contours.size()); vector<vector<int> > hullsI(Contours.size()); vector<vector<Vec4i>> defects(Contours.size()); for (int i = 0; i < Contours.size(); i++) { convexHull(Contours[i], hull[i], false); convexHull(Contours[i], hullsI[i], false); if(hullsI[i].size() > 3 ) { convexityDefects(Contours[i], hullsI[i], defects[i]); } } //REQUIRED contour is detected,then convex hell is found and also convexity defects are found and stored in defects if (maxarea>100){ drawContours(frame, hull, lrgctridx, Scalar(2555, 0, 255), 3, 8, vector<Vec4i>(), 0, Point()); /// Draw convexityDefects for(int j=0; j<defects[lrgctridx].size(); ++j) { const Vec4i& v = defects[lrgctridx][j]; float depth = v[3] / 256; if (depth > 10) // filter defects by depth { int startidx = v[0]; Point ptStart(Contours[lrgctridx][startidx]); int endidx = v[1]; Point ptEnd(Contours[lrgctridx][endidx]); int faridx = v[2]; Point ptFar(Contours[lrgctridx][faridx]); line(frame, ptStart, ptEnd, Scalar(0, 255, 0), 1); line(frame, ptStart, ptFar, Scalar(0, 255, 0), 1); line(frame, ptEnd, ptFar, Scalar(0, 255, 0), 1); circle(frame, ptFar, 4, Scalar(0, 255, 0), 2); } } } imshow("output", frame); char key = waitKey(33); if (key == 27) break; } } 
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for your example. It mostly works fine with the only exception that convexHull(Contours[i], hullsI[i], false); needs "true" clockwise parameter. Perhaps this is opencv 3+ thing. Using false leads to inability to find all defects.
@Umka the false is to return indices (instead of points) which are needed by the convexityDefects function. Not really sure what you're talking about, actually
In my opencv 3.3 there is such a convexityHull(): CV_EXPORTS_W void convexHull( InputArray points, OutputArray hull, bool clockwise = false, bool returnPoints = true ); This is what I mean.
@Umka yes, you're right. That false is for clockwise, but I intented to use it for returnPoints. Luckily I passed a vector, so the returnPoints flag was ignored anyway. Then it problably changes if you do CW or CCW... I don't know actually. Thanks for the feedback ;)
You have no idea how long it took me to find an example of drawing contour defects. Thank you sir :-)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.