如何获得带洞二进制掩模的边界坐标?

3
我有以下图像: 测试图像 我想获得每个斑点(我们称之为斑点A和B)的外部和内部轮廓的(x, y)坐标列表。
import cv2
from skimage import measure

blob = cv2.imread('blob.png', 0)
contours, hier = cv2.findContours(blob, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
labels = measure.label(blob)
props = measure.regionprops(labels)

for ii in range(0,len(props))
xy = props[ii].coords

plt.figure(figsize=(18, 16))
plt.imshow(blob, cmap='gray')
plt.plot(xy[:, 0], xy[:,1])
plt.show()

期望输出的图像,其中蓝色和红色是从坐标列表 A 和 B 中提取的:

期望输出


你可以使用形态学函数来消除孔洞,然后找到外边界的边界框。然后使用它从(非形态化的)图像中提取一个补丁并找到孔洞(之后需要将补丁坐标添加回去)。 - Pam
1个回答

5
您可以直接从cv2.findContours中获取(x, y)坐标。要识别单个斑点,请查看层次结构hier。第四个索引告诉您可能的内部(或子)轮廓与哪个外部(或父)轮廓相关联。大多数外部轮廓的索引为-1,其他所有轮廓都具有非负值。因此,在迭代轮廓时,一个朴素的方法是每次看到-1时增加一个斑点计数器,并绘制具有相同颜色的所有轮廓,直到下一个-1出现。
import cv2
from skimage import io         # Only needed for web grabbing images, use cv2.imread for local images

# Read image; find contours with hierarchy
blob = io.imread('https://istack.dev59.com/Ga5Pe.webp')
contours, hier = cv2.findContours(blob, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Define sufficient enough colors for blobs
colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]

# Draw all contours, and their children, with different colors
out = cv2.cvtColor(blob, cv2.COLOR_GRAY2BGR)
k = -1
for i, cnt in enumerate(contours):
    if (hier[0, i, 3] == -1):
        k += 1
    cv2.drawContours(out, [cnt], -1, colors[k], 2)

cv2.imshow('out', out)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果

当然,使用NumPy可以优化获取属于同一blob的所有轮廓,但在此处循环感觉最直观。我省略了所有其他的内容(skimage,Matplotlib),因为它们似乎与此处不相关。正如我所说,(x,y)坐标已经存储在contours中。

希望这能帮到你!


编辑:我还没有验证OpenCV是否总是连续地获取一个最外层轮廓的所有轮廓,或者例如给定层次级别的所有轮廓是否依次存储。因此,对于更复杂的层次结构,应先进行测试,或者从一开始就使用NumPy查找所提到的索引。


我尝试修改你的代码,但在循环过程中遇到了一些问题。我试图在不同的图像中绘制蓝色和绿色对象。你能帮我解决这个问题吗? - ChristineP
@ChristineP 那听起来就像是一个新问题。所以,请不要犹豫,提出另一个问题,并在那里描述您的问题,包括您的(修改后的)代码。为了上下文和参考,您可以链接到这个问题。 - HansHirse
感谢您的建议:https://stackoverflow.com/questions/58970920/python-find-contour-of-multiple-objects-with-their-holes - ChristineP

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