我想使椭圆适合图片中部分损坏的物体。 (这里的图片只是用于说明的简化示例!)
椭圆形物体损坏的图像
这样做
def sort(n):
return n.size
Image = cv2.imread('acA2500/1.jpg', cv2.IMREAD_GRAYSCALE)
#otsu binarization
_, binary = cv2.threshold(Image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
#invert binary image for opencv findContours
inverse_binary = cv2.bitwise_not(binary)
#find contours
contours, _ = cv2.findContours(inverse_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
#sort contours by length
largest_contours = sorted(contours, key=sort, reverse=True)
#fit ellipse
contour = largest_contours[0]
ellipse = cv2.fitEllipseDirect(contour)
我得到的结果并不令人满意。
Result of cv2.findContours and cv2.fitEllipse
因此,我构建了此循环以消除不在椭圆上的轮廓点。
contour = largest_contours[0]
newcontour = np.zeros([1, 1, 2])
newcontour = newcontour.astype(int)
for coordinate in contour:
if coordinate[0][0] < 600:
newcontour = np.insert(newcontour, 0, coordinate, 0)
newellipse = cv2.fitEllipse(newcontour)
得到这个结果,很好。
Result after trimming the contour points
问题是,我必须在短时间内进行很多此类调整。到目前为止,这还没有达到期望的速度。
是否有更好/更快/更精细的方法来修剪轮廓点?由于我没有太多的编码经验,所以很高兴在这里找到帮助:-)
编辑:
我编辑了示例图片,因此很显然,很遗憾cv2.minEnclosingCircle
方法无效。
现在这些图片也说明了为什么对轮廓进行排序。在我的真实代码中,我将一个椭圆拟合到三个最长的轮廓上,然后再看我想在另一个例程中使用哪个椭圆。
如果我不修剪轮廓并手动选择cv2.fitEllipse
的轮廓,则代码需要大约0.5s
。使用轮廓修整和三次cv2.fitEllipse
,大约需要2s
。可能只需要1s
答案 0 :(得分:2)
如果对象是圆形,则可以在轮廓上使用cv2.minEnclosingCircle
来捕获它。
#!/usr/bin/python3
# 2019/02/13 08:50 (CST)
# https://stackoverflow.com/a/54661012/3547485
import cv2
img = cv2.imread('test.jpg')
## Convert to grayscale and threshed it
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
th, threshed = cv2.threshold(gray, 100, 255, cv2.THRESH_OTSU|cv2.THRESH_BINARY_INV)
## Find the max outers contour
cnts = cv2.findContours(threshed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]
cv2.drawContours(img, cnts, -1, (255, 0, 0), 2, cv2.LINE_AA)
## Use minEnclosingCircle
(cx,cy),r = cv2.minEnclosingCircle(cnts[0])
cv2.circle(img, (int(cx), int(cy)), int(r), (0, 255, 0), 1, cv2.LINE_AA)
## This it
cv2.imwrite("dst.jpg", img)
这是我的结果。