如何用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
相关产品推荐
相关产品推荐

