打开 CV 平凡圆检测——如何获得最小二乘法而不是轮廓?

use*_*521 6 python opencv image-processing hough-transform

我的目标是从显微镜准确测量孔的直径。工作流程是:拍摄图像、拟合过程、拟合、以像素为单位将半径转换为毫米、写入 csv

倾斜的霍夫圆

这是用于测量孔直径的图像处理脚本的输出。我遇到了一个问题,我的圆拟合似乎优先匹配轮廓而不是最小二乘法之类的方法。

我或者在这样的事情中平均了许多拟合:

许多适合平均

我的问题是我喜欢快速扫描以确保圆形适合。权衡是我拥有的合身越多,合身就越真实,我拥有的越少,就越容易确保数字正确。我的圈子并不总是像这个圈子那样漂亮和圆,所以这对我很重要。

如果您能看一下并告诉我如何在 5 个圆的数量级上执行更多的最小二乘法,这是我的脚本拟合圆。我不想使用最小圆检测,因为流体正在流过这个孔,所以我希望它更像一个水力直径——谢谢!

(thresh, blackAndWhiteImage0) = cv2.threshold(img0, 100, 255, cv2.THRESH_BINARY) #make black + white 
median0 = cv2.medianBlur(blackAndWhiteImage0, 151) #get rid of noise 
circles0 = cv2.HoughCircles(median0,cv2.HOUGH_GRADIENT,1,minDist=5,param1= 25, param2=10, minRadius=min_radius_small,maxRadius=max_radius_small) #fit circles to image
Run Code Online (Sandbox Code Playgroud)

fmw*_*w42 5

这是拟合圆的另一种方法,即使用连接组件从二值图像中获取等效圆心和半径,并使用 Python/OpenCV/Skimage 从中绘制圆。

输入:

在此输入图像描述

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)
Run Code Online (Sandbox Code Playgroud)


结果显示轮廓(绿色)与圆形拟合(红色)相比:

在此输入图像描述

圆半径和中心:

radius = 117.6142467296168   center = 220.2169911178609 , 150.26823599797507
Run Code Online (Sandbox Code Playgroud)



可以使用 Scipy 获得最小二乘拟合方法(轮廓点和圆之间)。例如,参见:

https://gist.github.com/lorenzoriano/6799568

https://docs.scipy.org/doc/scipy/reference/ generated/scipy.optimize.curve_fit.html