<p>这里是另一种拟合圆的方法,通过使用连接的组件从二进制图像中获取等效的圆心和半径,并使用Python/OpenCV/Skimage从中绘制圆</p>
<p>输入:</p>
<p><a href="https://i.stack.imgur.com/PkWqv.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/PkWqv.png" alt="enter image description here"/></a></p>
<pre><code>import cv2
import numpy as np
from skimage import measure
# load image and set the bounds
img = cv2.imread("dark_circle.png")
# convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# blur
blur = cv2.GaussianBlur(gray, (3,3), 0)
# threshold
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# apply morphology open with a circular shaped kernel
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
binary = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
# find contour and draw on input (for comparison with circle)
cnts = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
c = cnts[0]
result = img.copy()
cv2.drawContours(result, [c], -1, (0, 255, 0), 1)
# find radius and center of equivalent circle from binary image and draw circle
# see https://scikit-image.org/docs/dev/api/skimage.measure.html#skimage.measure.regionprops
# Note: this should be the same as getting the centroid and area=cv2.CC_STAT_AREA from cv2.connectedComponentsWithStats and computing radius = 0.5*sqrt(4*area/pi) or approximately from the area of the contour and computed centroid via image moments.
regions = measure.regionprops(binary)
circle = regions[0]
yc, xc = circle.centroid
radius = circle.equivalent_diameter / 2.0
print("radius =",radius, " center =",xc,",",yc)
xx = int(round(xc))
yy = int(round(yc))
rr = int(round(radius))
cv2.circle(result, (xx,yy), rr, (0, 0, 255), 1)
# write result to disk
cv2.imwrite("dark_circle_fit.png", result)
# display it
cv2.imshow("image", img)
cv2.imshow("thresh", thresh)
cv2.imshow("binary", binary)
cv2.imshow("result", result)
cv2.waitKey(0)
</code></pre>
<p><br/>
显示轮廓(绿色)与圆拟合(红色)比较的结果:</p>
<p><a href="https://i.stack.imgur.com/t1Hgm.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/t1Hgm.png" alt="enter image description here"/></a></p>
<p>圆半径和圆心:</p>
<pre><code>radius = 117.6142467296168 center = 220.2169911178609 , 150.26823599797507
</code></pre>
<p><br/>
<br/>
<strong>可以使用Scipy获得(轮廓点和圆之间)最小二乘拟合方法。例如,请参见:</p>
<p><a href="https://gist.github.com/lorenzoriano/6799568" rel="nofollow noreferrer">https://gist.github.com/lorenzoriano/6799568</a></p>
<p><a href="https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html" rel="nofollow noreferrer">https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html</a></p>