HoughCircles 圆检测不起作用?

HoughCircles circle detection not working?

我一直在尝试编写一个程序来检测屏幕上的圆圈。

This is my screen before code processing

正如您在图片中看到的,代码应检测到三个圆圈。我正在使用 OpenCV 库中的 HoughCircles 函数来完成此任务。我的代码如下。

ss = gui.screenshot()

img = cv2.cvtColor(np.array(ss), cv2.COLOR_RGB2BGR)
output = img.copy()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.2, 100)

if circles is not None:
    print("circles found", len(circles))

    circles = np.round(circles[0, :]).astype("int")

    for (x, y, r) in circles:

        cv2.circle(output, (x, y), r, (0, 255, 0), 4)
        cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)

    cv2.imshow("output", np.hstack([gray, output]))
    cv2.waitKey(0)

cv2.imshow("output", gray)
cv2.waitKey(0)

我先截图我的屏幕。然后,我将其转换为用于 opencv。

但是,此代码未检测到第一张图片中显示的屏幕截图的任何圆圈。我知道这一点是因为当 运行 时,我的程序不会打印“找到圆圈”。此外,为了表明我一直在截屏并 运行 将它们适当地灰度化,我从代码的最后两行截取了这张图片。

picture in a gray scale

为了证明我的代码可以与其他圆形图片一起使用,这里有一张普通圆形的图片:

before detection

after detection

任何帮助将不胜感激!

这些是适合我的 houghCircles 参数。在尝试找到圆圈之前,您还应该考虑 运行 图像上的高斯模糊。

我不是 houghCircles 的超级粉丝。我发现它真的很挑剔,而且我不喜欢它所做的很多事情都隐藏在函数内部。它使调整主要是反复试验。这些参数适用于这个特定的图像,但我不会指望它在不同的光照条件下或不同的颜色下继续工作。

import cv2
import numpy as np

# load image
img = cv2.imread("spheres.png");

# grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY);
gray = cv2.GaussianBlur(gray,(5,5),0);

# circles
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, dp = 1, minDist = 100, param1=65, param2=20, minRadius=20, maxRadius=50)

# draw circles
if circles is not None:
    # round to ints
    circles = np.uint16(np.around(circles));
    for circle in circles[0, :]:
        # unpack and draw
        x, y, radius = circle;
        center = (x,y);
        cv2.circle(img, center, radius, (255, 0, 255), 3);

# show
cv2.imshow("Image", img);
cv2.imshow("Gray", gray);
cv2.waitKey(0);

这是一种不使用霍夫变换来检测圆的替代解决方案。由于您的输入图像与感兴趣的斑点具有非常明显的 蓝色色调 ,因此您可以尝试根据它们的 HSV 值创建分割掩码。然后,使用圆检测 contours 近似值 每个 contour。最后一步可以使用 cv2.minEnclosingCircle 实现,顾名思义,它可以计算 contour.

最小封闭圆

让我们看看代码:

# image path
path = "D://opencvImages//"
fileName = "XUzFw.png"

# Reading an image in default mode:
inputImage = cv2.imread(path + fileName)
# Create a deep copy of the input for results:
inputImageCopy = inputImage.copy()

# Convert the image to the HSV color space:
hsvImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2HSV)

# Set the HSV values:
lowRange = np.array([78, 0, 158])
uppRange = np.array([125, 255, 255])

# Create the HSV mask
mask = cv2.inRange(hsvImage, lowRange, uppRange)

这会生成以下分割掩码:

如您所见,唯一剩下的斑点是圆圈。现在,让我们计算 contours 并找到 最小外接圆 :

# Find the circle blobs on the binary mask:
contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Use a list to store the center and radius of the target circles:
detectedCircles = []

# Look for the outer contours:
for i, c in enumerate(contours):

    # Approximate the contour to a circle:
    (x, y), radius = cv2.minEnclosingCircle(c)

    # Compute the center and radius:
    center = (int(x), int(y))
    radius = int(radius)

    # Draw the circles:
    cv2.circle(inputImageCopy, center, radius, (0, 0, 255), 2)

    # Store the center and radius:
    detectedCircles.append([center, radius])

# Let's see the results:
cv2.namedWindow("Circles", cv2.WINDOW_NORMAL)
cv2.imshow("Circles", inputImageCopy)
cv2.waitKey(0)

这是检测结果:

此外,您可以查看 detectedCircles 列表中存储的数据:

# Check out the detected circles:
for i in range(len(detectedCircles)):
    # Get circle data:
    center, r = detectedCircles[i]
    # Print it:
    print("i: "+str(i)+" x: "+str(center[0])+" y: "+str(center[1])+" r: "+str(r))

产生:

i: 0 x: 395 y: 391 r: 35
i: 1 x: 221 y: 391 r: 36
i: 2 x: 567 y: 304 r: 35