首页 > 解决方案 > 非二值图像的有效轮廓

问题描述

我有这张图片: 在此处输入图像描述

我想得到每个唯一(非零)值的轮廓,所以基本上这个输出:

[array([[1, 1],
        [3, 2],
        [3, 1]], dtype=int32),
 array([[4, 2],
        [4, 3],
        [5, 3],
        [5, 2]], dtype=int32),
 array([[2, 4],
        [3, 4]], dtype=int32)]

我可以通过将图像转换为二进制掩码然后使用cv2'sfindContours函数来实现这一点,它可以得到我想要的输出。

import numpy as np
import cv2

img = np.array([
    [0,0,0,0,0,0,0],
    [0,1,1,1,0,0,0],
    [0,0,1,1,2,2,0],
    [0,0,0,0,2,2,0],
    [0,0,3,3,0,0,0]
])

contour_list = []

for level in [l for l in np.unique(img) if l != 0]:
    mask = (img == level).astype(np.uint8)
    contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]
    contours[0] = cv2.approxPolyDP(contours[0], 0.5, True)
    contours_xy = contours[0][:, 0]
    contour_list.append(contours_xy)


contour_list

但是,对于具有许多独特级别的大型图像,这种方法很慢。有没有办法提高这个功能的速度(没有多处理)?我觉得我忽略了一些功能。

标签: python-3.xopencvmaskcontouropencv-python

解决方案


调整原始图像的大小,执行此过程,然后缩放结果轮廓以适合原始图像。

import cv2
import numpy as np

img = cv2.imread('images/multi-level-color.png',0)
img_r = cv2.resize(img,(int(img.shape[1]*0.1),int(img.shape[0]*0.1)))

cv2.imshow('img_r',img_r)
cv2.waitKey(0)

contour_list = []
contour_list_r = []

for level in [l for l in np.unique(img) if l != 0]:
    #mask = (img == level).astype(np.uint8)

    contours = cv2.findContours(img_r, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]
    contours[0] = cv2.approxPolyDP(contours[0], 0.5, True)
    contours_xy = contours[0][:, 0]
    contours_xy_r = contours[0][:, 0]*10

    contour_list.append(contours_xy)
    contour_list_r.append(contours_xy_r)


print("resized 0.1",contour_list[0])

print("resized 10",contour_list_r[0])

原图: 在此处输入图像描述

调整大小的图像进行处理: 在此处输入图像描述

输出:

调整大小 0.1

[[11 10]
 [11 20]
 [20 20]
 [21 21]
 [21 31]
 [42 31]
 [43 32]
 [43 41]
 [42 42]
 [21 42]
 [21 52]
 [42 52]
 [42 42]
 [43 41]
 [63 41]
 [63 21]
 [43 21]
 [42 20]
 [42 10]]

调整大小 10

[[110 100]
 [110 200]
 [200 200]
 [210 210]
 [210 310]
 [420 310]
 [430 320]
 [430 410]
 [420 420]
 [210 420]
 [210 520]
 [420 520]
 [420 420]
 [430 410]
 [630 410]
 [630 210]
 [430 210]
 [420 200]
 [420 100]]

推荐阅读