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;
2 | No.2 Revision |
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:
3 | No.3 Revision |
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: