如果有多个图形存在包含关系,如何将包含关系的图形辨认为一个轮廓?
如图,图中有四个图形,希望的效果为红色线条为一个轮廓,绿色线条为一个轮廓,最终图上只有两个轮廓。
我自己的思路是先将图形变为凸包,再将中心点计算出来并记录,再用is_inside()函数判断该中心点是否再凸包内,最后用cv2.convexHull(np.concatenate(,))将两个轮廓变为一个轮廓。
in_convex_hulls = [] # 在内部的凸包
in_centers = [] # 存放在内部的中心点
for convex_hull in new_hull:
found = False # 一个凸包内可能包含多个中心点,所以添加一个标志防止重复添加进列表。
# 调用is_inside()函数检测点是否在凸包内
for i,center in enumerate(centers):
if is_inside(convex_hull, center): # 思路:再遍历一边所有的中心点,找出中心点对应的凸包
in_convex_hulls.append(convex_hull)
in_centers.append(center)
# cv2.drawContours(image, [convex_hull], 0, (0, 0, 255), 2)
found = True
break
多个图形存在包含关系,将包含关系的图形辨认为一个轮廓。
https://blog.csdn.net/weixin_46131719/article/details/122395359
用这个实例的思路,链接:https://blog.csdn.net/weixin_44634704/article/details/126489355
【通过寻找轮廓、绘制轮廓去分析相似度和包含情况】
这篇文章参考一下,https://www.codenong.com/29663764/
我理解你的意思是将红色的两个图形识别为一个轮廓。这是做不到的,因为图像中轮廓的定义是一条连续的封闭的曲线,两个红色图性不相连,所以必然不能构成一个轮廓。
你如果一定要做,可以自行构造:
(1)识别所有轮廓;
(2)根据识别的轮廓,仅选择外层轮廓获取其编号;
(3)对于每个外层轮廓编号如 Ce,根据所有轮廓属性,查找 父轮廓编号为 Ce 的轮廓 C1,C2,...
(4)构造你要的轮廓,将 Ce、C1、... 的数据点集合并。
但如果你只是想从查找的轮廓中,找到包含关系,则非常简单,按照轮廓属性查找父轮廓/子轮廓即可。
hierarchy:轮廓的层次结构和拓扑信息,是一个形如 (1,k,4) 的 Numpy 数组。hierarchy[0][i] 表示第 i 个轮廓的层次结构,是包含 4个值的数组 [Next, Previous, First Child, Parent],分别代表第 i 个轮廓的同层的后一个轮廓、同层的前一个轮廓、第一个子轮廓、父轮廓的编号
你可以先看一下:【youcans 的 OpenCV 例程200篇】194.寻找图像轮廓(https://blog.csdn.net/youcans/article/details/124997148)
使用 OpenCV 中的 findContours 函数可以轻松地检测出图像中的轮廓。此函数可以接受一个二值图像(即黑白图像)并返回图像中所有轮廓的列表。
findContours 函数有多个参数,其中最重要的是两个:mode 和 method。mode 参数决定轮廓的检测模式,method 参数决定轮廓的近似方法。
你可以使用 method 参数将包含关系的轮廓视为一个轮廓。method 参数接受一个整数值,其中 CV_CHAIN_APPROX_NONE 表示保留所有轮廓点,CV_CHAIN_APPROX_SIMPLE 表示仅保留拐点。因此,可以使用 CV_CHAIN_APPROX_SIMPLE 参数来将所有包含关系的轮廓视为一个轮廓。
参考
import cv2
# 读入图像并转化为二值图像
image = cv2.imread("image.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 检测轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
cv2.drawContours(image, contours, -1, (0, 255, 0), 3)
# 显示图像
cv2.imshow("Image", image)
cv2.waitKey(0)
cv2.findContours()这个函数,将mode参数设置为cv2.RETR_EXTERNAL,就只检测外轮廓,不会检测内嵌轮廓,这时候的外轮廓就是你要的另个轮廓合并为一个。而cv2.RETR_TREE这个参数的话,适合根据hierarchy给出的轮廓关系来玩一些花活,比如填充两个轮廓之间的区域,内部子轮廓为空等
import cv2
import numpy as np
src=cv2.imread('1.png')
gray=cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)
_,thresh=cv2.threshold(gray,100,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
cv2.drawContours(src, contours, -1, (0, 0, 255), -1,8)
cv2.imshow('1',src)
cv2.waitKey()
在 OpenCV 中,你可以使用函数 cv2.findContours() 来找到图像中的轮廓。这个函数会返回一个列表,列表中的每个元素都是一个轮廓。你可以使用 cv2.drawContours() 函数来在图像上绘制轮廓。
下面是一个例子,展示了如何找到一幅图像中所有轮廓:
import cv2
# 读取图像
image = cv2.imread('image.png')
# 转化为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 找到轮廓
_, contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
cv2.drawContours(image, contours, -1, (0, 0, 255), 3)
# 显示图像
cv2.imshow('Image', image)
cv2.waitKey(0)
如果你想要找到包含关系的轮廓,你可以使用函数 cv2.findContours() 的第二个参数。这个参数表示轮廓检索模式,有以下几种选择:
你可以使用 cv2.RETR_TREE 这个参数来检索所有轮廓,并建立完整的层级关系。这样,你就可以通过遍历这些轮廓的层级关系来找到包含关系的轮廓了。
下面是一个例子,展示了如何找到包含关系的轮廓:
import cv2
# 读取图像
image = cv2.imread('image.png')
# 转化为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 找到轮廓
_, contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 遍历所有轮廓
for contour in contours:
# 找到当前轮廓的父轮廓
parent = contour
while parent is not None:
# 绘制父轮廓
cv2.drawContours(image, [parent], -1, (0, 0, 255), 3)
# 获取父轮廓的父轮廓
_, _, _, parent = cv2.convexHull(parent)
# 显示图像
cv2.imshow('Image', image)
cv2.waitKey(0)
在这个例子中,我们使用函数 cv2.convexHull() 来获取当前轮廓的父轮廓。我们循环遍历每一个轮廓,并找到它的父轮廓,最后绘制出来。这样就可以找到包含关系的轮廓了。
findContours的模式就是干这事用的
我等等写给你