使用OpenCV识别空心圆和实心圆

发布于 2025-01-11 18:26:27 字数 1324 浏览 2 评论 0原文

我使用 OpenCV houghcircles 来识别所有圆(空心圆和实心圆)。以下是我的代码:

import numpy as np
import cv2

img = cv2.imread('images/32x32.png')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

bilateral = cv2.bilateralFilter(gray,10,50,50)

minDist = 30
param1 = 30
param2 = 50
minRadius = 5
maxRadius = 100

circles = cv2.HoughCircles(bilateral, cv2.HOUGH_GRADIENT, 1, minDist, param1=param1, param2=param2, minRadius=minRadius, maxRadius=maxRadius)

if circles is not None:
    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        cv2.circle(img, (i[0], i[1]), i[2], (0, 0, 255), 2)

# Show result for testing:
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

测试输入图像 1: 输入图片此处描述

测试输出图像1: 输入图片此处描述

正如你所看到的,除了少数圈子之外,我能够识别大多数圈子。我在这里缺少什么?我尝试过改变参数,但这是我能得到的最好结果。

此外,如果我使用更紧凑的圆圈,脚本不会识别任何圆圈。

输入图片此处描述

I'm using OpenCV houghcircles to identify all the circles (both hollow and filled). Follow is my code:

import numpy as np
import cv2

img = cv2.imread('images/32x32.png')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

bilateral = cv2.bilateralFilter(gray,10,50,50)

minDist = 30
param1 = 30
param2 = 50
minRadius = 5
maxRadius = 100

circles = cv2.HoughCircles(bilateral, cv2.HOUGH_GRADIENT, 1, minDist, param1=param1, param2=param2, minRadius=minRadius, maxRadius=maxRadius)

if circles is not None:
    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        cv2.circle(img, (i[0], i[1]), i[2], (0, 0, 255), 2)

# Show result for testing:
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Test input image 1:
enter image description here

Test output image1:
enter image description here

As you can see I'm able identity most of the circles except for few. What am I missing here? I've tried varying the parameters but this is the best i could get.

Also, if I use even more compact circles the script does not identify any circles whatsoever.

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

失而复得 2025-01-18 18:26:27

另一种想法是使用查找轮廓方法并使用 appox 检查轮廓是否为圆,如下所示。

import cv2

img = cv2.imread('32x32.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

inputImageCopy = img.copy()

# Find the circle blobs on the binary mask:
contours, hierarchy = cv2.findContours(gray, 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)

    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)
    
    if len(approx)>5: # check if the contour is circle
        
        # 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])

cv2.imshow("Circles", inputImageCopy)
cv2.waitKey(0)
cv2.destroyAllWindows()

输入图片此处描述

在此处输入图像描述

An alternative idea is to use find contour method and chek whether the contour is a circle using appox as below.

import cv2

img = cv2.imread('32x32.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

inputImageCopy = img.copy()

# Find the circle blobs on the binary mask:
contours, hierarchy = cv2.findContours(gray, 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)

    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)
    
    if len(approx)>5: # check if the contour is circle
        
        # 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])

cv2.imshow("Circles", inputImageCopy)
cv2.waitKey(0)
cv2.destroyAllWindows()

enter image description here

enter image description here

瑕疵 2025-01-18 18:26:27

我解决了你的问题。使用与您相同的代码。无需修改。我将值从 50 更改为 30。仅此而已。

#!/usr/bin/python39
#OpenCV 4.5.5 Raspberry Pi 3/B/4B-w/4/8GB RAM, Bullseye,v11.
#Date: 19th April, 2022

import numpy as np
import cv2

img = cv2.imread('fill_circles.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
bilateral = cv2.bilateralFilter(gray,10,50,50)

minDist = 30
param1 = 30
param2 = 30
minRadius = 5
maxRadius = 100

circles = cv2.HoughCircles(bilateral, cv2.HOUGH_GRADIENT, 1, minDist, param1=param1, param2=param2, minRadius=minRadius, maxRadius=maxRadius)

if circles is not None:
    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        cv2.circle(img, (i[0], i[1]), i[2], (0, 0, 255), 2)

cv2.imwrite('lego.png', img)
# Show result for testing:
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出:
输入图片此处描述

I solved your problem. Using same code as your. No needed to modified. I changed value from 50 to 30. That all.

#!/usr/bin/python39
#OpenCV 4.5.5 Raspberry Pi 3/B/4B-w/4/8GB RAM, Bullseye,v11.
#Date: 19th April, 2022

import numpy as np
import cv2

img = cv2.imread('fill_circles.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
bilateral = cv2.bilateralFilter(gray,10,50,50)

minDist = 30
param1 = 30
param2 = 30
minRadius = 5
maxRadius = 100

circles = cv2.HoughCircles(bilateral, cv2.HOUGH_GRADIENT, 1, minDist, param1=param1, param2=param2, minRadius=minRadius, maxRadius=maxRadius)

if circles is not None:
    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        cv2.circle(img, (i[0], i[1]), i[2], (0, 0, 255), 2)

cv2.imwrite('lego.png', img)
# Show result for testing:
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Output:
enter image description here

濫情▎り 2025-01-18 18:26:27

如果您始终可以获得(或从真实图像创建)这样的“干净”图像,则可以轻松获得网格(二维圆数组)区域的边界框。

因此,您可以知道感兴趣的矩形区域(以及网格的旋转角度,如果可以旋转)。

如果沿着矩形的轴向检查像素,您可以轻松找出排列有多少个圆以及圆的直径。
因为所有像素都是黑色的线是相邻行(或列)之间的间隙。
(将沿轴方向的像素值相加。是否为 0 告诉您该线是否经过该网格单元。)

如果需要,您可以检查每个网格中的轮廓形状 -细胞确实是圆形的。

If you can always get(or create from real image) such "clean" image, the bounding-box of the grid(2-dimensional array of circles) region can be easily obtained.

Therefore, you can know the rectangular area of interest (and the angle of rotation of the grid, if rotation is possible).

If you examine the pixels along the axial direction of the rectangle, you can easily find out how many circles are lined up and the diameter of the circle.
Because lines that all pixel are black are gaps between adjacent row(or column).
(Sum up the pixel values along the direction of the axis. Whether it is 0 or not tells you whether the line passes over the grid-cell or not.)

If necessary, you may check that the shape of the contour in each gird-cell is really circular.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文