Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

why not use the findNonZero() function. The following code seems to give the sequence of the points from top-bottom, left-right:

Mat cn;
Canny(src, cn, 100, 255);
imshow("canny", cn);

vector<Point> pnts;
findNonZero(cn, pnts);

cout << "Total number of points: " << pnts.size() << endl;

for(size_t i = 0; i < pnts.size(); ++i)
    cout << pnts[i] << endl;

why not use the findNonZero() function. The following code seems to give the sequence of the points from top-bottom, left-right:

Mat cn;
Canny(src, cn, 100, 255);
imshow("canny", cn);

vector<Point> pnts;
findNonZero(cn, pnts);

cout << "Total number of points: " << pnts.size() << endl;

for(size_t i = 0; i < pnts.size(); ++i)
    cout << pnts[i] << endl;

edit: update

then if you still want to use the contour properties you will need to use the CV_CHAIN_APPROX_NONE flag. According to the documentation:

CV_CHAIN_APPROX_NONE stores absolutely all the contour points. That is, any 2 subsequent points (x1,y1) and (x2,y2) of the contour will be either horizontal, vertical or diagonal neighbors, that is, max(abs(x1-x2),abs(y2-y1))==1.

and a code snippet:

// Find contours
vector<Vec4i> hierarchy;
std::vector<std::vector<cv::Point> > contours;
cv::findContours(src, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);

Mat dst = Mat::zeros(src.size(), CV_8UC3);
for(size_t i = 0; i < contours[0].size(); ++i) // since we have only one contour
{
    cout << contours[0][i] << endl; // print the points
    circle(dst, contours[0][i], 0, Scalar(0, 0, 255));
}

imshow("dst", dst);
waitKey();

just bear in mind that the points are stored in an anti-clockwise sequence. But that's quite easy to address, just search the web how to do it. The result can be seen below:

image description

why not use the findNonZero() function. The following code seems to give the sequence of the points from top-bottom, left-right:

Mat cn;
Canny(src, cn, 100, 255);
imshow("canny", cn);

vector<Point> pnts;
findNonZero(cn, pnts);

cout << "Total number of points: " << pnts.size() << endl;

for(size_t i = 0; i < pnts.size(); ++i)
    cout << pnts[i] << endl;

edit: update

then if you still want to use the contour properties you will need to use the CV_CHAIN_APPROX_NONE flag. flag instead of the CV_CHAIN_APPROX_SIMPLE one that you are using. According to the documentation:documentation:

CV_CHAIN_APPROX_NONE stores absolutely all the contour points. That is, any 2 subsequent points (x1,y1) and (x2,y2) of the contour will be either horizontal, vertical or diagonal neighbors, that is, max(abs(x1-x2),abs(y2-y1))==1.

CV_CHAIN_APPROX_SIMPLE compresses horizontal, vertical, and diagonal segments and leaves only their end points. For example, an up-right rectangular contour is encoded with 4 points.

So, due to that compression you were lacking some points, and a code snippet:

// Find contours
vector<Vec4i> hierarchy;
std::vector<std::vector<cv::Point> > contours;
cv::findContours(src, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);

Mat dst = Mat::zeros(src.size(), CV_8UC3);
for(size_t i = 0; i < contours[0].size(); ++i) // since we have only one contour
{
    cout << contours[0][i] << endl; // print the points
    circle(dst, contours[0][i], 0, Scalar(0, 0, 255));
}

imshow("dst", dst);
waitKey();

just bear in mind that the points are stored in an anti-clockwise sequence. But that's quite easy to address, just search the web how to do it. The result can be seen below:

image description