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

如何用Python实现自动连点器?数字与圆点识别难题求解

针对连线游戏自动完成的数字与圆点识别优化方案

我完全懂你现在的困扰——用pytesseract处理这种连线游戏的数字和圆点,确实容易翻车,毕竟它更擅长常规的大文本识别,而不是这种和圆形元素混在一起的小数字。下面我给你一套针对性的解决方案,一步步来解决问题:

一、先做图像预处理(关键第一步)

原始图像里可能有背景干扰、颜色噪点,直接丢给pytesseract肯定识别不准。先做几步预处理,把图像“清理干净”:

  • 灰度化:去掉颜色干扰,简化计算
  • 自适应二值化:把图像转成黑白,突出数字和圆点的轮廓
  • 形态学去噪:去掉小的杂点,避免干扰识别
import cv2
import numpy as np

# 读取图像
img = cv2.imread('data/2.png')
# 转灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 自适应二值化(适合光照不均的场景)
thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
# 形态学开运算,去除小噪声
kernel = np.ones((2,2), np.uint8)
cleaned_img = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=1)

二、分开处理圆点和数字

圆点是规则的圆形,数字是不规则字符,分开检测能避免互相干扰:

1. 用霍夫圆变换检测圆点

霍夫圆变换是专门检测圆形元素的工具,比通用OCR靠谱多了:

# 检测圆点(参数需要根据你的图像调整,多试几次)
circles = cv2.HoughCircles(
    gray, 
    cv2.HOUGH_GRADIENT, 
    dp=1.2,  # 累加器分辨率与图像分辨率的比值
    minDist=20,  # 两个圆点之间的最小距离
    param1=50,  # Canny边缘检测的高阈值
    param2=30,  # 累加器阈值,值越小检测到的圆越多
    minRadius=5,  # 圆点最小半径
    maxRadius=15  # 圆点最大半径
)

# 提取所有圆点的圆心坐标
dot_coords = []
if circles is not None:
    circles = np.uint16(np.around(circles))
    for circle in circles[0, :]:
        center_x, center_y = circle[0], circle[1]
        dot_coords.append((center_x, center_y))
        # 可选:画出检测到的圆点,验证效果
        cv2.circle(img, (center_x, center_y), circle[2], (0, 255, 0), 2)

2. 优化pytesseract的数字识别

针对小数字,我们给pytesseract加一些限制,让它只专注于数字识别:

from PIL import Image
import pytesseract
from pytesseract import Output

# 用预处理后的干净图像识别数字,指定配置参数
ocr_data = pytesseract.image_to_data(
    cleaned_img,
    output_type=Output.DICT,
    # --psm 10:单字符识别模式;白名单只留数字,减少错误识别
    config='--psm 10 --oem 3 -c tessedit_char_whitelist=0123456789'
)

# 提取有效的数字及其中心坐标
number_details = []
total_items = len(ocr_data['level'])
for i in range(total_items):
    text = ocr_data['text'][i].strip()
    # 只保留纯数字的结果
    if text and text.isdigit():
        x, y, w, h = ocr_data['left'][i], ocr_data['top'][i], ocr_data['width'][i], ocr_data['height'][i]
        # 计算数字区域的中心,方便后续匹配圆点
        num_center = (x + w//2, y + h//2)
        number_details.append({
            'number': int(text),
            'center': num_center,
            'bbox': (x, y, w, h)
        })
        # 可选:画出数字的 bounding box,验证效果
        cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)

三、关联数字与对应的圆点

数字通常在圆点旁边,我们可以通过计算距离,把每个数字匹配到最近的圆点:

# 建立数字到圆点的映射
number_to_dot = {}
for num_info in number_details:
    num_center = num_info['center']
    # 计算当前数字到所有圆点的欧氏距离
    distances = [np.linalg.norm(np.array(num_center) - np.array(dot)) for dot in dot_coords]
    # 找到最近的圆点
    closest_dot_idx = np.argmin(distances)
    closest_dot = dot_coords[closest_dot_idx]
    number_to_dot[num_info['number']] = closest_dot
    # 可选:画出数字到圆点的连线,验证匹配是否正确
    cv2.line(img, num_center, closest_dot, (0, 0, 255), 2)

# 现在你就得到了{数字: 圆点坐标}的映射表
print("数字与圆点映射:", number_to_dot)

四、按顺序连线完成图案

最后按照数字从小到大的顺序,依次连接对应的圆点即可:

# 按数字排序
sorted_numbers = sorted(number_to_dot.keys())
# 依次连线
for i in range(len(sorted_numbers)-1):
    start_point = number_to_dot[sorted_numbers[i]]
    end_point = number_to_dot[sorted_numbers[i+1]]
    # 画粗一点的线,让结果更明显
    cv2.line(img, start_point, end_point, (255, 0, 0), 3)

# 保存最终的连线结果
cv2.imwrite('connected_pattern.png', img)

额外小提示

  • 霍夫圆的参数(比如minDist、minRadius)需要根据你的图像实际尺寸调整,多试几次就能找到最合适的数值
  • 如果数字和圆点重叠严重,可以先检测圆点,然后把圆点区域从图像中涂黑,再识别数字,避免干扰
  • 如果pytesseract还是不够准,可以考虑训练一个简单的CNN数字识别模型——针对这种固定风格的小数字,自定义模型的识别率会比通用OCR高很多

内容的提问来源于stack exchange,提问作者Peter Zhu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:23:17