You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python修正代码以准确识别并统计图像中的彩色大圆圈

问题:准确统计图像中大彩色圆圈数量(排除小圆圈)

需分析包含多色圆圈的图像,仅统计大圆圈,排除每个大圆圈左上角的小圆圈。现有基于OpenCV和NumPy的检测代码结果错误:统计红色15个、蓝色10个、绿色1个,且可视化结果误识别了小圆圈,需修正代码以实现精准统计。

相关图像

原始图像
检测结果图像

原始代码

import cv2
import numpy as np

def count_colored_circles(image_path):
    # Load image
    image = cv2.imread(image_path)
    if image is None:
        print("Error: Unable to load image.")
        return

    # Convert image to grayscale
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Apply Gaussian blur to reduce noise and improve circle detection
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)

    # Detect circles
    circles = cv2.HoughCircles(blurred, cv2.HOUGH_GRADIENT, dp=1, minDist=1,
                               param1=50, param2=30, minRadius=20, maxRadius=40)

    if circles is not None:
        circles = np.uint16(np.around(circles))
        counts = {'red': 0, 'blue': 0, 'green': 0}
        for circle in circles[0, :]:
            # Extract region of interest (ROI) for each circle
            x, y, radius = circle
            roi = image[max(0, y-radius):min(y+radius, image.shape[0]), max(0, x-radius):min(x+radius, image.shape[1])]
            # Calculate the average color in the ROI
            avg_color = np.mean(roi, axis=(0, 1))
            # Determine the color category based on the average color
            if avg_color[2] > avg_color[0] and avg_color[2] > avg_color[1]:
                color = 'red'
            elif avg_color[0] > avg_color[1] and avg_color[0] > avg_color[2]:
                color = 'blue'
            else:
                color = 'green'
            # Increment count for the detected color
            counts[color] += 1

        # Print counts of each color
        print("Counts of each color:")
        for color, count in counts.items():
            print(f"{color}: {count}")

        # Visualize detected circles (optional)
        for circle in circles[0, :]:
            x, y, radius = circle
            cv2.circle(image, (x, y), radius, (0, 255, 0), 2)

        cv2.imshow('Detected Circles', image)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    else:
        print("No circles detected.")

# Provide the absolute path to the image file
image_path = "D:/TBL9.PNG"  # Replace "your_image.jpg" with the actual image filename
count_colored_circles(image_path)

问题分析

  • 霍夫圆检测参数不合理:minDist=1过小,导致算法检测到大量紧邻大圆圈的小圆圈;minRadius和maxRadius范围未精准匹配大圆圈尺寸,小圆圈也被纳入检测范围。
  • 颜色判断逻辑有缺陷:直接取整个圆圈ROI的平均颜色,小圆圈的颜色会干扰大圆圈的颜色判断,导致统计错误。

修正方案

  1. 调整霍夫圆检测参数:
    • 增大minDist至大圆圈直径的一半以上(如60),确保仅检测彼此间距足够的大圆圈
    • 精准设置minRadius和maxRadius(如30-40),过滤小圆圈
    • 提高param2阈值(如35),减少弱检测结果
  2. 优化颜色判断:
    • 取圆圈中心区域(而非整个ROI)的颜色平均值,避免小圆圈干扰
    • 增加颜色差值阈值,提升颜色分类的准确性

修正后的代码

import cv2
import numpy as np

def count_colored_circles(image_path):
    # 加载图像
    image = cv2.imread(image_path)
    if image is None:
        print("Error: 无法加载图像。")
        return

    # 转换为灰度图
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # 高斯模糊去噪
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)

    # 检测大圆圈:调整参数过滤小圆圈
    circles = cv2.HoughCircles(blurred, cv2.HOUGH_GRADIENT, dp=1, minDist=60,
                               param1=50, param2=35, minRadius=30, maxRadius=40)

    if circles is not None:
        circles = np.uint16(np.around(circles))
        counts = {'red': 0, 'blue': 0, 'green': 0}
        for circle in circles[0, :]:
            x, y, radius = circle
            # 取圆圈中心区域(避免小圆圈干扰)
            center_size = radius // 2
            roi = image[y-center_size:y+center_size, x-center_size:x+center_size]
            avg_color = np.mean(roi, axis=(0, 1))
            # 优化颜色判断:增加差值阈值
            b, g, r = avg_color
            if r > g + 20 and r > b + 20:
                color = 'red'
            elif b > g + 20 and b > r + 20:
                color = 'blue'
            elif g > r + 20 and g > b + 20:
                color = 'green'
            else:
                # 无法明确分类的跳过(可选)
                continue
            counts[color] += 1

        # 输出统计结果
        print("各颜色圆圈数量:")
        for color, count in counts.items():
            print(f"{color}: {count}")

        # 可视化检测结果
        for circle in circles[0, :]:
            x, y, radius = circle
            cv2.circle(image, (x, y), radius, (0, 255, 0), 2)

        cv2.imshow('检测到的大圆圈', image)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    else:
        print("未检测到圆圈。")

# 图像路径
image_path = "D:/TBL9.PNG"
count_colored_circles(image_path)

内容的提问来源于stack exchange,提问作者Mazhar Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 22:10:55