国际象棋棋盘图像识别异常:重复识别g8而非目标f6的问题排查
解决国际象棋绿色方块重复识别的问题
我明白你现在遇到的麻烦:明明要找第二个绿色方块f6,结果pos_loop函数老是返回已经识别过的g8位置。咱们来一步步拆解问题,找到修复方案。
首先看代码里的核心逻辑错误
你的条件判断完全写反了!两个绿色标记(g8和f6)是相同尺寸的,但你现在的代码里写的是:
if p1.height != h.height and p1.width != h.width and p1 != previous_white and p1 != previous_green:
这相当于在找尺寸完全不同的元素,和你的需求完全相反!而且直接用p1 != previous_green这种方式比较pyautogui的Box对象也不靠谱——即使坐标完全一样,不同的对象实例也会返回True,根本起不到排除已识别位置的作用。
修正后的代码思路
- 先修正路径:Windows路径要用双反斜杠或者原始字符串,避免转义字符报错
- 优先搜索绿色背景的标记(毕竟你要找的是第二个绿色方块)
- 通过坐标对比排除第一个已识别的位置,替代不可靠的对象比较
- 去掉容易导致状态混乱的全局变量,改用函数参数传递已识别位置
修正后的代码:
import pyautogui def pos_loop(first_pos): # first_pos是已经正确识别的第一个绿色方块位置(g8) # 先收集所有绿色背景的匹配结果 green_matches = list(pyautogui.locateAllOnScreen(r"C:\Users\Admin\Desktop\chesspic\small_on_green.png")) # 遍历结果,排除和first_pos完全重合的位置 for match in green_matches: if not (match.left == first_pos.left and match.top == first_pos.top and match.width == first_pos.width and match.height == first_pos.height): return match # 如果没找到绿色匹配,再按原逻辑搜索白色背景的(按需保留) white_matches = list(pyautogui.locateAllOnScreen(r"C:\Users\Admin\Desktop\chesspic\small_on_white.png")) for match in white_matches: if not (match.left == first_pos.left and match.top == first_pos.top and match.width == first_pos.width and match.height == first_pos.height): return match return None
额外优化建议
- 提高识别精度:如果还是有误识别,可以加上
confidence参数(需要先安装opencv-python),过滤相似度低的匹配:
green_matches = list(pyautogui.locateAllOnScreen(r"C:\Users\Admin\Desktop\chesspic\small_on_green.png", confidence=0.8))
- 棋盘间距校验:国际象棋棋盘格子是等距的,你可以计算两个位置的像素距离,确保它们符合棋盘格子的间距,彻底避免返回同一位置:
import math def get_pos_distance(pos1, pos2): return math.hypot(pos2.left - pos1.left, pos2.top - pos1.top) # 在返回match前加上距离判断(数值根据你的截图调整) min_valid_distance = 50 if get_pos_distance(first_pos, match) > min_valid_distance: return match
- 彻底抛弃全局变量:全局变量很容易在多次调用函数时导致状态混乱,用函数参数传递状态会更可靠、更易维护。
原代码出错的根本原因
- 尺寸判断写反,导致本该匹配的f6被过滤,反而错误返回了全局变量里的g8
- 对象直接比较的方式无效,无法正确排除已识别的位置
- 先搜索白色背景标记的逻辑,可能优先匹配到错误结果
试试上面的修正方案,应该能解决你的重复识别问题!
内容的提问来源于stack exchange,提问作者Raicha




