Search code examples
pythonimageopencvcoordinates

How to get ordered coords using cv2.goodFeaturesToTrack (from bottom to top and left to right)


Hey Everybody!

I'm trying to extract the coordinates of the lines as depicted in the picture, but the retrieved coordinates are not ordered (either from left-right or bottom-top). Is there a way to do it? Input image Output image using goodFeaturesToTrack I would like to acknowledge @Jeru Luke , @Baraa and @stateMachine for their privous answers in this regard.

I tried the following:

x_corners = cv2.goodFeaturesToTrack(h_BeamsCopy, None, 0.01, 10) # None: find all the corners
x_corners = np.int0(x_corners)
for i, hcorner enumerate(x_corners):
    xh, yh = hcorner.ravel()
    cv2.circle(h_BeamsCopy, (xh, yh), 5, (255,100,0), -1)
    cv2.putText(h_BeamsCopy, str(i), (int(xh), int(yh)), font, 0.5, (255, 255, 255), 1)

I expected the retrieved points would be ordered from bottom-top and left-right as illustrated in the following picture: Expected result


Solution

  • Ordering of goodFeaturesToTrack is explained in the docs:

    The remaining corners are sorted by the quality measure in the descending order.

    You can sort them yourself based on position:

    x_corners = cv2.goodFeaturesToTrack(h_BeamsCopy, None, 0.01, 10) # None: find all the corners
    x_corners = np.int0(x_corners)
    
    # Flatten to x,y
    corners = (corner.ravel() for corner in x_corners)
    # Sort according to your pic (down-up, left-right -> y=0 is top, x=0 is left)
    # y-axis is turned negative to use ascending sort in our favor
    corners = sorted(corners, key=lambda c: (-1 * c[1], c[0]))
    

    Sample output:

    >>> corners = [(2,5), (7,4), (849,590), (2, 590)]
    >>> sorted(corners, key=lambda c: (-1 * c[1], c[0]))
    [(2, 590), (849, 590), (2, 5), (7, 4)]