Python 如何使用cv2.Minareact(cnt)获得多轮廓图像上唯一的最小面积矩形?
我只想使用一个矩形覆盖此图像中的圆: 并使用cv2.minareact(cnt)获得此结果: 这张图片似乎被分成多个部分。可能是因为在这个图像的边缘有一些断点。你能告诉我如何只用一个矩形来覆盖我图像的这个圆吗?多谢各位 这是我的代码:Python 如何使用cv2.Minareact(cnt)获得多轮廓图像上唯一的最小面积矩形?,python,opencv,image-processing,contour,opencv-contour,Python,Opencv,Image Processing,Contour,Opencv Contour,我只想使用一个矩形覆盖此图像中的圆: 并使用cv2.minareact(cnt)获得此结果: 这张图片似乎被分成多个部分。可能是因为在这个图像的边缘有一些断点。你能告诉我如何只用一个矩形来覆盖我图像的这个圆吗?多谢各位 这是我的代码: def draw_min_rect_circle(img, cnts): # conts = contours img = np.copy(img) for cnt in cnts: x, y, w, h = cv2.bou
def draw_min_rect_circle(img, cnts): # conts = contours
img = np.copy(img)
for cnt in cnts:
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) # blue
min_rect = cv2.minAreaRect(cnt) # min_area_rectangle
min_rect = np.int0(cv2.boxPoints(min_rect))
cv2.drawContours(img, [min_rect], 0, (0, 255, 0), 2) # green
(x, y), radius = cv2.minEnclosingCircle(cnt)
center, radius = (int(x), int(y)), int(radius) # center and radius of minimum enclosing circle
img = cv2.circle(img, center, radius, (0, 0, 255), 2) # red
return img
您需要做的是,您需要通过合并轮廓从图像中以某种方式仅获得1个轮廓,这有点困难,因此,如果您只希望在所有轮廓周围使用封闭矩形,您可以这样做
def draw_min_rect_circle(img, cnts): # conts = contours
img = np.copy(img)
x1,y1 = np.inf
x2,y2 = 0
for cnt in cnts:
x, y, w, h = cv2.boundingRect(cnt)
if x > x1:
x1=x
if y > y1:
y1=y
if x2 < x+w
x2 = x+w
if y2 < y+h
y2 = y+h
w = x2 - x1
h = y2 - y1
r = math.sqrt((w*w) + (h*h)) / 2
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
cv2.circle(img, (x1+w/2,y1+h/2), r, (0, 0, 255), 2)
def draw_min_rect_圆(img,cnts):#conts=轮廓
img=np.copy(img)
x1,y1=np.inf
x2,y2=0
对于cnt中的cnt:
x、 y,w,h=cv2.boundingRect(cnt)
如果x>x1:
x1=x
如果y>y1:
y1=y
如果x2
您可能使用cv2.findContours()
搜索轮廓,并在其中迭代以在图像上绘制矩形。问题是,你的图像没有一条相连的线组成圆圈,而是有许多虚线
轮廓是连接所有连续点(沿边界)的曲线,具有相同的颜色或强度(OpenCV文档)
所以为了得到更好的结果,你应该在搜索轮廓之前先准备好你的图像。可以使用各种工具对图像进行预处理(可以搜索OpenCV文档)。在本例中,我将尝试使用一个小内核执行名为“关闭”的过程。闭合是膨胀,接着是像素侵蚀。它可以帮助将您的小轮廓连接到一个大轮廓(圆)。然后,您可以选择最大的一个并绘制一个边框
例如:
输入图像:
结果:
执行关闭操作后的图像:
希望能有帮助。干杯 可以将所有轮廓合并为一个轮廓,因为它们只是描述轮廓的点坐标的numpy数组。您可以使用np.concatenate(等高线),cv2.minareact函数似乎并不关心新数组中的点是否连续。在我的例子中,这比使用关闭函数效果更好,因为我有更复杂的对象。如果你愿意,你可以试试,很简单。您的函数应该是这样的:
def draw_min_rect_circle(img, cnts): # conts = contours
img = np.copy(img)
join_cnts = np.concatenate(cnts)
x, y, w, h = cv2.boundingRect(join_cnts)
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) # blue
min_rect = cv2.minAreaRect(join_cnts) # min_area_rectangle
min_rect = np.int0(cv2.boxPoints(min_rect))
cv2.drawContours(img, [min_rect], 0, (0, 255, 0), 2) # green
(x, y), radius = cv2.minEnclosingCircle(join_cnts)
center, radius = (int(x), int(y)), int(radius) # center and radius of minimum enclosing circle
img = cv2.circle(img, center, radius, (0, 0, 255), 2) # red
return img
当然,人们可以在提供的二进制图像上找到解决方案,但我认为,如果您提供原始输入图像会更好,因为您的问题可能有更好的整体解决方案。这是一个很好的解决方案。通过闭合轮廓然后迭代寻找最大值来消除噪声的方法很简单,但非常有效。简单的解决方案,如果有效的话,在我的经验中是最好的解决方案。很高兴它起了作用。@kavko谢谢你的帮助!你的解决方案有效。这真是一个伟大的解决方案!
def draw_min_rect_circle(img, cnts): # conts = contours
img = np.copy(img)
join_cnts = np.concatenate(cnts)
x, y, w, h = cv2.boundingRect(join_cnts)
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) # blue
min_rect = cv2.minAreaRect(join_cnts) # min_area_rectangle
min_rect = np.int0(cv2.boxPoints(min_rect))
cv2.drawContours(img, [min_rect], 0, (0, 255, 0), 2) # green
(x, y), radius = cv2.minEnclosingCircle(join_cnts)
center, radius = (int(x), int(y)), int(radius) # center and radius of minimum enclosing circle
img = cv2.circle(img, center, radius, (0, 0, 255), 2) # red
return img