去轮廓分支

在一个应用中,需要提取轮廓线,但初次提取的会有一些细小分支,由于知道起点和终点,所以这里采用回溯法去掉轮廓分支


import cv2


def findPath(start, end, image, stack):
    # image: 二值图 value: 0 or 255
    # start: 起点位置 (int h, int w)
    # end:   终点位置 (int h, int w)
    h, w = image.shape[:2]

    if start[0] >= h or start[0] < 0 or start[1] >= w or start[1] < 0:
        return False
    if end[0] >= h or end[0] < 0 or end[1] >= w or end[1] < 0:
        return False
    stack.append(start)
    if len(image.shape) > 2:
        gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)              # 灰度化
        _, image = cv2.threshold(gray_image, 0, 255, cv2.THRESH_BINARY)  # 二值化

    if image[start[0]][start[1]] != 255 or image[end[0]][end[1]] != 255:
        print("起点或者终点不符合要求")
        return False

    while len(stack) > 0:
        cur = stack[-1]
        x_id = cur[0]
        y_id = cur[1]
        # 八领域 右-->右下-->下-->左下-->左-->左上-->上-->右上
        nb_ids = [[x_id, y_id+1], [x_id+1, y_id+1], [x_id+1, y_id], [x_id+1, y_id-1],
                  [x_id, y_id-1], [x_id-1, y_id-1], [x_id-1, y_id], [x_id-1, y_id+1]]
        flag = -1
        for nb_id in nb_ids:
            x = nb_id[0]
            y = nb_id[1]
            if x == end[0] and y == end[1]:
                stack.append(end_point)
                for x in range(h):
                    for y in range(w):
                        if image[x][y] == 255:
                            image[x][y] = 0
                return True

            if x >= h or x < 0 or y >= w or y < 0:
                continue

            if image[x][y] == 255:
                stack.append(nb_id)
                image[x][y] = 128
                flag = 1
                break

        if flag == -1:
            stack.pop()
            image[x_id][y_id] = 0

    if len(stack) == 0:
        print("未找到")
        return False




img_path = r"D://imageGumlineTest.png"
img = cv2.imread(img_path)
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY)

contours, hierarchy = cv2.findContours(thresh, 2, 1)
cnt = contours[0]
hull = cv2.convexHull(cnt, returnPoints=False)

defects = cv2.convexityDefects(cnt, hull)
max_dist = 0
start_point = -1
end_point = -1
far_point = -1
for i in range(defects.shape[0]):
    s, e, f, d = defects[i, 0]
    start = tuple(cnt[s][0])
    end = tuple(cnt[e][0])
    far = tuple(cnt[f][0])
    if d > max_dist:
        max_dist = d
        start_point = start
        end_point = end
        far_point = far

cv2.line(img, start_point, end_point, [0, 255, 0], 1)
cv2.circle(img, far_point, 2, [0, 0, 255], -1)
print(f"start_point: {start_point}, end_point: {end_point}")
cv2.imshow('final_img', img)

skeleton_img = cv2.imread(r"D://refCenterLineTest1.png")
gray_img = cv2.cvtColor(skeleton_img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY)
print(f"start: {thresh[42][27]}, end: {thresh[35][289]}")
cv2.line(skeleton_img, start_point, end_point, [0, 255, 0], 1)
cv2.circle(skeleton_img, start_point, 3, [0, 0, 255], -1)
cv2.circle(skeleton_img, end_point, 3, [0, 0, 255], -1)
cv2.circle(skeleton_img, far_point, 3, [0, 0, 255], -1)
cv2.imshow('thresh', thresh)

stack = []
s_p = [42, 27]
e_p = [35, 289]
findPath(s_p, e_p, thresh, stack)
cv2.imshow("skeleton", thresh)

cv2.waitKey(0)

stack里面存放得结果即为一条起点到终点得路径

原文地址:https://www.cnblogs.com/xiaxuexiaoab/p/14792381.html