Search code examples
opencvimage-processingcomputer-visioncontour

Find the Contour Properties


I'm using Visual Studio 2012 and OpenCV. I want to find the two-point coordinates with the following specifications.

  1. The first point: the highest and most leftmost point.

  2. The second point: the highest and most rightmost point.

Just like you see in the picture.

enter image description here

enter image description here

enter image description here

enter image description here


Solution

  • First I would like to point out that this answer is written in Python and it is meant to give an idea on how to approach such problem.

    Second it is a problem to define the highest and most left point (the same with highest and most right) because the shape of the contour varies a lot. Meaning that the most extreme values of right and left are not always complimentary with the highest value. Take the bottom image for example:

    enter image description here

    Top right red point is the highest north-wise but it is not the most right (it is the most left out of all 4 points) while bottom red point is the most right point but it is not the highest (it actually is the lowest north-wise!). And there are another 2 points which are in between and could fit the mentioned criteria.

    That being said I have made a script in Python for the most similar solution described in your images to show how I would try to handle the problem. It may not be what you want and there probably are better solutions out there but this will maybe give you an idea or clearify what you actually need.

    I took the liberty of downloading your sample pictures and edited them a little so I could make an example. Here are my "originals":

    enter image description here

    enter image description here

    I have extracted the contours of the image and select the biggest one - returns an array of points. Then I have extracted the higest value in X coordinate (the most right point) and the lowest Y coordinate (the most north point). Because the contour does not have straight lines I have made a threshold for how much the significant points can vary of the most extreme one (in your case the numbers could be different - my case +- 3). Then I have appended all the most right points in threshold in one list and all the most north points in another list. Then for the most left you select the point with lowest X coordinate from the list and the point with the lowest Y coordinate in the other list for your most right point.

    Here is the result:

    enter image description here

    enter image description here

    Hope it helps a bit. Cheers!

    Example in Python:

    import cv2
    import numpy as np
    
    img = cv2.imread('uplupr.png')
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, threshold = cv2.threshold(gray,170,255,cv2.THRESH_BINARY)
    im, contours, hierarchy = cv2.findContours(threshold,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
    mask = np.zeros(img.shape, dtype="uint8")
    cnt = max(contours, key=cv2.contourArea)
    cv2.drawContours(mask, [cnt], -1, (255,255,255), 1)
    top_right_append = 0
    top_up_append = 1000
    point_up = []
    point_right = []
    
    for i in cnt:
        top_up = int(i[:,1])
        top_right = int(i[:, 0])
        if top_right > top_right_append:
            top_right_append = int(top_right)
        if top_up < top_up_append:
            top_up_append = int(top_up)
    
    for i in cnt:
        if int(i[:,1]) < top_up_append+3:
            up = (int(i[:,0]), int(i[:,1]))
            point_up.append(up)
    
    for i in cnt:
        if int(i[:,0]) > top_right_append-3:
            right = (int(i[:,0]), int(i[:,1]))
            point_right.append(right)
    
    point_up.sort(key=lambda tup: tup[0])
    point_right.sort(key=lambda tup: tup[1])
    
    cv2.circle(mask,(point_up[0]), 4, (0,0,255), -1)
    cv2.circle(mask,(point_right[0]), 4, (0,0,255), -1)
    
    cv2.imshow('image', mask)