Order of points in findcontours()

Hello,

I need to order a set of points that form a curve on an image.
After processing, the input image is a black background with a single white line.

I am using findcontours() to follow the edge and output the list of points that form the line. I want points to start at one end of the line and follow it to the other end.

contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE )

After inspecting the points, I was surprised to see that they are not in the order I expected. The contour seems to start at the top center, trace one side, then backtrack to the other side before returning to the center. Perhaps the function is trying to trace the perimeter of the line?

Here is the original image and a second image with annotations that roughly show the order of the contour points. The actual contour points are listed below.

picture for forum

00:[214, 105]
01:[213, 106]
02:[212, 106]
03:[211, 106]
04:[210, 106]
05:[209, 107]
06:[208, 107]
07:[207, 107]
08:[206, 108]
09:[205, 108]
10:[204, 109]
11:[203, 109]
12:[204, 109]
13:[205, 109]
14:[206, 108]
15:[207, 108]
16:[208, 107]
17:[209, 107]
18:[210, 107]
19:[211, 107]
20:[212, 106]
21:[213, 106]
22:[214, 106]
23:[215, 106]
24:[216, 106]
25:[217, 106]
26:[218, 106]
27:[219, 106]
28:[220, 106]
29:[221, 106]
30:[222, 106]
31:[223, 106]
32:[224, 106]
33:[225, 107]
34:[226, 107]
35:[227, 107]
36:[228, 107]
37:[229, 108]
38:[230, 108]
39:[231, 108]
40:[232, 108]
41:[233, 109]
42:[234, 109]
43:[235, 109]
44:[234, 109]
45:[233, 108]
46:[232, 108]
47:[231, 108]
48:[230, 107]
49:[229, 107]
50:[228, 107]
51:[227, 107]
52:[226, 106]
53:[225, 106]
54:[224, 106]
55:[223, 106]
56:[222, 106]
57:[221, 105]
58:[220, 105]
59:[219, 105]
60:[218, 105]
61:[217, 105]
62:[216, 105]
63:[215, 105]

Why are the points not ordered continuously from one end of the line to the other?
How can I put them in order?

Thanks!

that is precisely the purpose of findContours: trace the perimeter of every connected component.

your connected component isn’t 1-width in every point either, nor is it a line or even just a tree, considering 4-connectivity or 8-connectivity.

your connected component, as presented, does not imply a unique “order” of points.

also, you’re asking us to generalize from a single example.

Could using a thinning algorithm on the input make it work with findcontours?

even then, findcontours will still circumnavigate the thinned blob exactly once.

it is the wrong function for the job.

at least with a thinned blob, one could then walk the pixels and recover some useful graph structure. it will still not be perfect. at every fork, you’ll get cycles. you’d have to deal with those.

That makes sense.
Like you say, this probably isn’t the right function for the job.

Thank you for your explanation, it was very helpful!