Python OpenCV:在特定轮廓内绘制外部轮廓
Posted
技术标签:
【中文标题】Python OpenCV:在特定轮廓内绘制外部轮廓【英文标题】:Python OpenCV: draw outer contours inside a specific contour 【发布时间】:2019-01-25 22:33:17 【问题描述】:我是 OpenCV 新手,我正在尝试在特定轮廓内绘制外部轮廓。这是我用来澄清的图像(已经灰度化、阈值化等)
我想要的是在外部矩形内找到所有圆的轮廓(总共 120 个)。
contours = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
所以我基本上为此使用了RETR_EXTERNAL
,但它只返回外部矩形。我尝试使用RETR_TREE
,但在这种情况下,它返回的轮廓比圆圈多,出于某种我不明白的原因。澄清一下:我只想要每个圆圈 1 个轮廓。
如何使用RETR_EXTERNAL
并忽略外轮廓(矩形),使其只返回圆圈?
【问题讨论】:
这个案例需要用到层次的概念。 【参考方案1】:按区域过滤轮廓:
我按区域过滤轮廓以隔离圆圈。我认为您可能需要在thresholding 图像上多做一些工作,以帮助从图像中的边界划定圆圈。我使用了以下代码:
import cv2
import numpy as np
img = cv2.imread("/your/path/C03eN.jpg")
def find_contours_and_centers(img_input):
img_gray = cv2.cvtColor(img_input, cv2.COLOR_BGR2GRAY)
img_gray = cv2.bilateralFilter(img_gray, 3, 27,27)
#(T, thresh) = cv2.threshold(img_input, 0, 100, 0)
_, contours_raw, hierarchy = cv2.findContours(img_gray, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
contours = [i for i in contours_raw if cv2.contourArea(i) > 20]
contour_centers = []
for idx, c in enumerate(contours):
M = cv2.moments(c)
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
samp_bounds = cv2.boundingRect(c)
contour_centers.append(((cX,cY), samp_bounds))
print("0 contour centers and bounds found".format(len(contour_centers)))
contour_centers = sorted(contour_centers, key=lambda x: x[0])
return (contours, contour_centers)
conts, cents = find_contours_and_centers(img.copy())
circles = [i for i in conts if np.logical_and((cv2.contourArea(i) > 650),(cv2.contourArea(i) < 4000))]
cv2.drawContours(img, circles, -1, (0,255,0), 2)
cv2.imwrite("/your/path/tester.jpg", img)
结果:
编辑:
如果您只想提取较大外矩形内的图像部分,请使用cv2.RETR_EXTERNAL
,让您专注于内圈,您可以执行以下操作:
import cv2
import numpy as np
img = cv2.imread("/your/path/C03eN.jpg")
def find_contours_and_centers(img_input):
img_gray = cv2.cvtColor(img_input, cv2.COLOR_BGR2GRAY)
img_gray = cv2.bilateralFilter(img_gray, 3, 27,27)
#(T, thresh) = cv2.threshold(img_input, 0, 100, 0)
#_, contours_raw, hierarchy = cv2.findContours(img_gray, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
_, contours_raw, hierarchy = cv2.findContours(img_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = [i for i in contours_raw if cv2.contourArea(i) > 20]
contour_centers = []
for idx, c in enumerate(contours):
M = cv2.moments(c)
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
samp_bounds = cv2.boundingRect(c)
contour_centers.append(((cX,cY), samp_bounds))
print("0 contour centers and bounds found".format(len(contour_centers)))
contour_centers = sorted(contour_centers, key=lambda x: x[0])
return (contours, contour_centers)
conts, cents = find_contours_and_centers(img.copy())
x,y,w,h = cv2.boundingRect(conts[0])
cropped = img[y+10:y+(h-10),x+10:x+(w-10)]
cv2.imwrite("/your/path/cropped.jpg", cropped)
结果:
【讨论】:
谢谢你的回复,但是为什么绿色的“圆圈”形状那么糟糕?当我画我的圆圈时,它们看起来不错,但问题是每个圆圈有不止 1 个轮廓,这是我不想要的……理想情况下,我想删除外部矩形,这样我就可以使用RETR_EXTERNAL
,效果很好。有什么办法吗?
不确定,我刚刚下载了图像并尝试了它,也许你的分辨率更好,我的测试图像分辨率低
你问题的最后一部分是:“我怎样才能使用 RETR_EXTERNAL 并忽略外轮廓(矩形),以便它只返回圆圈?”我只是将其作为您的预期解决方案,并尝试仅返回圆圈。
好的,我明白了,但是没有更简单的方法可以使外部矩形变黑(就像背景一样),这样我就可以使用RETR_EXTERNAL
了吗?
是的,您可以使用它来返回外框的轮廓,然后您可以创建蒙版,绘制黑色轮廓以隐藏圆圈,或完全提取图像的该部分以隔离您的区域感兴趣的以上是关于Python OpenCV:在特定轮廓内绘制外部轮廓的主要内容,如果未能解决你的问题,请参考以下文章
如何使用opencv绘制轮廓内的区域? (图片是从 dxf 文件导出的)[关闭]
如何隔离轮廓内的所有内容,对其进行缩放并测试与图像的相似性?