OpenCV:不使用RETR_EXTERNAL去除形状轮廓上的重复轮廓

3

OpenCV将为多边形轮廓注册内部和外部轮廓。

使用以下测试代码运行

import cv2
import numpy as np

def extract_contours():
    path = 'test.png'
    blank = np.zeros((184,184,3), np.uint8)
    blank[:] = (255,255,255)
    raw = cv2.imread(path, cv2.IMREAD_UNCHANGED)
    raw = 255-raw
    img = cv2.cvtColor(raw, cv2.COLOR_BGR2GRAY)
    contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    print(len(contours))
    for cnt in contours:
        area = cv2.contourArea(cnt)
        if area > 400: 
            approx = cv2.approxPolyDP(cnt, 0.009 * cv2.arcLength(cnt, True), True)
            cv2.drawContours(blank, [approx], 0, (0, 0, 255), 1)

    cv2.imwrite('contours.png', blank)

extract_contours()

在这张图片上

hollow square

将会在外圆和内圆边缘上产生两组轮廓,如下所示

double contours

是否有一种快速的方法可以将这两个轮廓集合折叠成一个单独的轮廓,最好是两者的平均值?我对CV2和计算机视觉都很新,不知道很多技巧。我不想使用RETR_EXTERNAL,因为我不想错过任何嵌套的形状。


使用contourArea函数来获取一个有符号的结果,然后相应地筛选轮廓。 - Christoph Rackwitz
1个回答

2

您可以使用您在调用cv2.findContours方法时定义的hierarchy变量,来确定轮廓是位于轮廓外部还是内部:

import cv2
import numpy as np

def extract_contours():
    path = 'test.png'
    blank = np.zeros((184, 184, 3), np.uint8)
    blank[:] = (255, 255, 255)
    raw = cv2.imread(path, cv2.IMREAD_UNCHANGED)
    raw = 255 - raw
    img = cv2.cvtColor(raw, cv2.COLOR_BGR2GRAY)
    contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    for cnt, hrc in zip(contours, hierarchy[0]):
        area = cv2.contourArea(cnt)
        if area > 400: 
            approx = cv2.approxPolyDP(cnt, 0.009 * cv2.arcLength(cnt, True), True)
            if hrc[2] < 0:
                cv2.drawContours(blank, [approx], 0, (0, 0, 255), 1)
            elif hrc[3] < 0:
                cv2.drawContours(blank, [approx], 0, (0, 255, 0), 1)

    cv2.imwrite('contours.png', blank)

extract_contours()

生成的图像:

在此输入图片描述

在外轮廓和内轮廓之间绘制轮廓线:

import cv2
import numpy as np

def extract_contours():
    path = 'test.png'
    blank = np.zeros((184, 184, 3), np.uint8)
    blank[:] = (255, 255, 255)
    raw = cv2.imread(path, cv2.IMREAD_UNCHANGED)
    raw = 255 - raw
    img = cv2.cvtColor(raw, cv2.COLOR_BGR2GRAY)
    contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    exte = None
    inte = None
    for cnt, hrc in zip(contours, hierarchy[0]):
        area = cv2.contourArea(cnt)
        if area > 400: 
            approx = cv2.approxPolyDP(cnt, 0.009 * cv2.arcLength(cnt, True), True)
            if hrc[2] < 0:
                exte = approx.squeeze()
            elif hrc[3] < 0:
                inte = approx.squeeze()
    exte = exte[np.lexsort(exte.T)]
    inte = inte[np.lexsort(inte.T)]
    box = cv2.convexHull((exte[exte[:, 0].argsort()] + inte[inte[:, 0].argsort()]) // 2)
    cv2.drawContours(blank, [box], -1, (0, 0, 255), 1)
    cv2.imwrite('contours.png', blank)

extract_contours()

生成的图片:

在此输入图片描述


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接