Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
251 views
in Technique[技术] by (71.8m points)

python - Find point on contour with given y-value

I have various contours extracted by cv2.findContours(cv2.CHAINE_APPROX_NONE). After that I also extracted the extreme points. Now I′d like to find the point in the contour opposite to the leftmost/rightmost. The point in the contour with the same y-coordinates as the leftmost/rightmost point, so to say. As the format of the coordinates is hardly readable by most functions, maybe the trick is to reorder them.

Any idea how to solve that?

    ###contour extraction
    cnts = cv2.findContours(img_thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    cnts = cnts[0]
    (cnts, _) = contours.sort_contours(cnts)

    cnt_number = 0

    for cnt in cnts:
        if cv2.contourArea(cnt) > 500:
        contour_lenght = cv2.arcLength(cnt, True)
        approx = cv2.approxPolyDP(cnt, 0.005 * contour_lenght, True)
        obj_cor = len(approx)

        if obj_cor > 4:
            cv2.drawContours(blank_image, cnt, -1, (0, 0, 0), 2)
            leftmost = tuple(cnt[cnt[:, :, 0].argmin()][0])
            rightmost = tuple(cnt[cnt[:, :, 0].argmax()][0])

Also thaught about doing a line-contour-intersection (like suggested by mathematical.coffee here Line intersecting contour in openCv) but not sure how...

            ###bounding box
            x, y, w, h = cv2.boundingRect(approx)
            ###end of line from leftmost
            left_y = leftmost[1]
            left_x = leftmost[0] + w
            left_line_endpoint = (left_x, left_y)
            ###line intersect function suggested by mathematical.coffee
            numpy.logical_and(...)
question from:https://stackoverflow.com/questions/65905993/find-point-on-contour-with-given-y-value

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

if i got your idea correctly this will be something like this (please excuse my poor command over linear algebra)

import cv2
import numpy as np

def intersection(l0, l1):   # (origin, drection), (origin, drection) -> point in scene coords
    l0 = np.float32(l0)
    l1 = np.float32(l1)

    dOrg = l1[0] -l0[0]
    g1ort = np.float32([-l1[1][1], l1[1][0]])
    g0 = np.float32([l0[1][0], l0[1][1]])

    if abs(np.dot(g0, g1ort)) < 1e-32:
        return None
    else:
        t0 = np.dot(dOrg, g1ort)/np.dot(g0, g1ort)
        return l0[0] +l0[1]*t0

img = np.zeros((450, 450, 3), dtype=np.uint8)

# badpoints = [[10,100], [180,250], [380,160], [220,360], [180,360], [70,210]]
points = [[200,100], [180,250], [380,160], [220,360], [180,360], [70,210]]
cont = [np.int32(points).reshape(len(points), 1, 2)]  # convert it into this weird format cv so wants
cv2.drawContours(img, cont, -1, (0,0xff,0), 3)

leftmost = points[np.argmin(np.array(points)[:,0])]
hor_line = [leftmost, [100, 0]]
cont_lines = np.float32(list(zip(points, points[1:]+[points[0]])))  # make segment list (scene coords)
cont_lines = [[segment[0], segment[1]-segment[0]] for segment in cont_lines]    # convert to parametric
intersections = [intersection(hor_line, line) for line in cont_lines]   # cache intersection results for each segt

for pt in intersections:
    if pt is not None:
        cv2.circle(img, tuple(np.int32(pt)), 7, (0,0,255), 3)

rightmost = None
for isect, segt in zip(intersections, cont_lines):
    if isect is not None:
        gline = segt[1]
        dOrg = isect -segt[0]
        t = np.dot(gline, dOrg)/np.dot(gline, gline)
        if 0 <= t <= 1:  # check that only those intersection points that lie in boundaries of segments are used
            if rightmost is None:
                rightmost = isect
            elif rightmost[0] < isect[0]:
                rightmost = isect

cv2.circle(img, tuple(np.int32(rightmost)), 11, (255,0,0), 3)

cv2.imshow('test', img)
cv2.waitKey(0)

consider replacing points array with badpoints. this will result in leftmost point also being topmost, so that there is no matching segment to the right of it to intersect


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...