在OpenCV中检测圆圈

问题描述 投票:0回答:1

虽然我意识到OpenCV的HoughCircles没有“一刀切”的设置,但我找到一个合理的参数集时遇到了一些麻烦。

我的输入图像是下面的照片,其中包含一些非常明显的大黑圈,以及它周围的一些噪音:

Original input photo

我尝试使用p1p2参数,尝试准确地获得检测到的四个黑色圆圈(并且可选地,磁带在顶部滚动 - 这不是必需的,但我不介意它是否匹配)。

import numpy as np
import cv2

gray = frame = cv2.imread('testframe2.png')

gray = cv2.cvtColor(gray, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray,(5,5),0)
# gray = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 5, 2)

p1 = 200
p2 = 55

while True:
    out = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)

    circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 10, param1=p1, param2=p2, minRadius=10, maxRadius=0)

    if circles is not None:
        for (x, y, r) in circles[0]:
            cv2.rectangle(out, (int(x - r), int(y - r)), (int(x + r), int(y + r)), (255, 0, 0))
            cv2.putText(out, "r = %d" % int(r), (int(x + r), int(y)), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (255, 0, 0))

    cv2.putText(out, "p: (%d, %d)" % (p1, p2), (0, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 4)
    cv2.imshow('debug', out)

    if cv2.waitKey(0) & 0xFF == ord('x'):
        break
    elif cv2.waitKey(0) & 0xFF == ord('q'):
        p1 += 5
    elif cv2.waitKey(0) & 0xFF == ord('a'):
        p1 -= 5
    elif cv2.waitKey(0) & 0xFF == ord('w'):
        p2 += 5
    elif cv2.waitKey(0) & 0xFF == ord('s'):
        p2 -= 5

cv2.destroyAllWindows()

我能做的最好的事情就是多次检测大圆圈而不是小圆圈,或者得到很多误报:

Best parameter setting: detects big circle multiple times but not the small one

我已经阅读了F **手册,但它对我没有帮助:我如何在某种程度上可靠地检测圆圈,除此图像中的圆圈外什么都没有?

opencv image-recognition hough-transform
1个回答
0
投票

使用HoughCircles参数进行了一些手动调整,但这给出了您正在寻找的结果。我使用的OpenCV Wrapper library简化了一些事情。

import cv2
import opencv_wrapper as cvw
import numpy as np

frame = cv2.imread("tape.png")

gray = cvw.bgr2gray(frame)
thresh = cvw.threshold_otsu(gray, inverse=True)
opened = cvw.morph_open(thresh, 9)

circles = cv2.HoughCircles(
    opened, cv2.HOUGH_GRADIENT, 1, 10, param1=100, param2=17, minRadius=5, maxRadius=-1
)

if circles is not None:
    circles = np.around(circles).astype(int)
    for circle in circles[0]:
        cv2.floodFill(thresh, None, (circle[0], circle[1]), 155)

only_circles = thresh.copy()
only_circles[only_circles != 155] = 0

contours = cvw.find_external_contours(only_circles)
cvw.draw_contours(frame, contours, (255, 0, 255), thickness=2)

cv2.imwrite("tape_result.png", frame)

我使用HoughCircles找到中心,正如documentation笔记中所建议的那样。

然后我用floodFill来填充圆圈。请注意,最左边的圆圈非常靠近边缘。如果图像模糊,洪水填充将进入背景。

披露:我是OpenCV Wrapper的作者。尚未添加Hough Circles和洪水填充。

© www.soinside.com 2019 - 2024. All rights reserved.