OpenCV:使单个圆适合图像(在Python中)

时间:2019-04-10 22:06:09

标签: python opencv computer-vision

我有这样的图像:

enter image description here

我需要使椭圆适合深色区域(请注意:必须是椭圆,而不是圆形)。在OpenCV中执行此操作的最佳方法是什么?到目前为止,我的第一步是对其应用自适应(Otsu)阈值,结果是:

enter image description here

但是我不确定从那里去哪里。我正在用Python编写应用程序,但更多的是我正在寻找的算法设计。

根据回复/评论进行编辑:

好的,所以我已经尝试了形态。基于OpenCV documentation,我对其进行了3次迭代“关闭”操作(先膨胀,然后腐蚀),以去除小颗粒,结果是:

enter image description here

然后,为了将其扩展回更接近原始形状,我进行了3次迭代“打开”操作(侵蚀,然后膨胀),结果为:

enter image description here

在这里,我进行了Canny边缘检测,结果是:

enter image description here

现在,我在上面使用了findContours,但是遇到了问题。它沿边缘发现了数十个轮廓,每个轮廓沿圆周有一小段。这意味着,即使我采用最大尺寸的轮廓,它也只能代表圆周的10%,不足以精确地拟合椭圆。这就是为什么@ Demi-Lune提出的其他问题对我不起作用的原因。它们都具有非常干净,锋利的边缘,findContours找到了一个不错的单一轮廓,该轮廓覆盖了每种形状的整个压电体,但是对于我的凌乱图像而言,不会发生这种情况。那么,从这里拟合椭圆的最佳方法是什么?

3 个答案:

答案 0 :(得分:1)

为什么不先执行“关闭”然后执行“打开”操作以清除所有混乱情况。

原始图片:

Raw image

大津:

Otsu

关闭+打开;都具有7x7内核;现在的二进制图像既漂亮又干净。

Close + Open

仅检测到一个轮廓:

One contour

椭圆为:(请不要使图像为圆形,所以椭圆应为圆形)

Ellipse

答案 1 :(得分:1)

如果对象为圆形,则使用cv2.minEnclosingCircle是好的。否则,您可以使用cv2.fitEllipse在对象周围找到最合适的椭圆。记住要在黑色背景下找到带有白色物体的轮廓。

import cv2
import numpy as np

img = cv2.imread("1.jpg")

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_,thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
thresh = cv2.bitwise_not(thresh)

element = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(5, 5))

morph_img = thresh.copy()
cv2.morphologyEx(src=thresh, op=cv2.MORPH_CLOSE, kernel=element, dst=morph_img)

contours,_ = cv2.findContours(morph_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

areas = [cv2.contourArea(c) for c in contours]
sorted_areas = np.sort(areas)

#bounding box (red)
cnt=contours[areas.index(sorted_areas[-1])] #the biggest contour
r = cv2.boundingRect(cnt)
cv2.rectangle(img,(r[0],r[1]),(r[0]+r[2],r[1]+r[3]),(0,0,255),2)

#min circle (green)
(x,y),radius = cv2.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
cv2.circle(img,center,radius,(0,255,0),2)

#fit ellipse (blue)
ellipse = cv2.fitEllipse(cnt)
cv2.ellipse(img,ellipse,(255,0,0),2)


cv2.imshow("morph_img",morph_img)
cv2.imshow("img", img)
cv2.waitKey()

enter image description here enter image description here

答案 2 :(得分:0)

在对图像应用自适应阈值之后,可以使用morphological operationscv2.erode()cv2.dilate()使图像平滑。通过执行这些操作,您将能够隔离主圆图像并去除细小噪音。接下来,您可以使用cv2.findContours()并过滤最大尺寸的轮廓,从而在图像中找到圆。这将为您提供边界框坐标,您可以在其中找到圆心。有了中心坐标后,就可以适合日食了。