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

基于OpenCV的棋盘棋子检测失败问题求助

棋盘棋子检测失败问题排查

问题描述

尝试在棋盘图像中检测指定棋子:
棋盘图像:棋盘图像
待检测棋子图像:待检测棋子
该棋子尺寸为59x83,理论上可被检测,但实际未识别出正确位置,当前检测结果:检测结果图

附上实现代码:

import cv2
import numpy as np

# Load the chess board and chess piece images
img_board = cv2.imread('ccom.png')
img_piece = cv2.imread('bbis.png')

# Convert both images to grayscale
img_board_gray = cv2.cvtColor(img_board, cv2.COLOR_BGR2GRAY)
img_piece_gray = cv2.cvtColor(img_piece, cv2.COLOR_BGR2GRAY)

# Apply morphological operations to extract the chess piece from the board
kernel = np.ones((5, 5), np.uint8)
img_piece_mask = cv2.erode(img_piece_gray, kernel, iterations=1)
img_piece_mask = cv2.dilate(img_piece_mask, kernel, iterations=1)

# Find the matching location on the board
result = cv2.matchTemplate(img_board_gray, img_piece_mask, cv2.TM_SQDIFF)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)

# Draw a rectangle around the matching location
top_left = min_loc
bottom_right = (top_left[0] + img_piece.shape[1], top_left[1] + img_piece.shape[0])
cv2.rectangle(img_board, top_left, bottom_right, (0, 0, 255), 2)

# Show the result
cv2.imshow('Result', img_board)
cv2.waitKey(0)
cv2.destroyAllWindows()

问题原因分析

  • 形态学操作破坏核心特征:你用了5x5的核做腐蚀+膨胀,这个尺寸对59x83的棋子来说太大,直接把棋子的纹理、边缘细节磨平了,导致模板和棋盘上的棋子特征完全不匹配。
  • 匹配方法与阈值缺失:TM_SQDIFF对亮度、细微差异敏感度高,且你没做阈值过滤,很容易把噪声区域误判为匹配点。
  • 未处理亮度差异:棋盘上的棋子和单独的棋子图像存在亮度、对比度差异,直接转灰度匹配会进一步放大这种差异。

修正方案

方案1:移除多余预处理,用归一化匹配

直接保留棋子原始灰度特征,改用鲁棒性更强的匹配方法并添加阈值过滤:

import cv2
import numpy as np

img_board = cv2.imread('ccom.png')
img_piece = cv2.imread('bbis.png')

img_board_gray = cv2.cvtColor(img_board, cv2.COLOR_BGR2GRAY)
img_piece_gray = cv2.cvtColor(img_piece, cv2.COLOR_BGR2GRAY)

# 移除形态学操作,用归一化相关系数匹配
result = cv2.matchTemplate(img_board_gray, img_piece_gray, cv2.TM_CCOEFF_NORMED)
# 设置匹配阈值,过滤低匹配度结果
threshold = 0.8
locations = np.where(result >= threshold)

# 绘制所有符合条件的匹配框
for pt in zip(*locations[::-1]):
    bottom_right = (pt[0] + img_piece.shape[1], pt[1] + img_piece.shape[0])
    cv2.rectangle(img_board, pt, bottom_right, (0, 255, 0), 2)

cv2.imshow('Result', img_board)
cv2.waitKey(0)
cv2.destroyAllWindows()

方案2:可选优化——边缘特征匹配

如果棋盘有较多噪声,可改用边缘特征做匹配,进一步提升鲁棒性:

# 替换灰度转换为边缘检测
img_board_gray = cv2.Canny(cv2.cvtColor(img_board, cv2.COLOR_BGR2GRAY), 50, 150)
img_piece_gray = cv2.Canny(cv2.cvtColor(img_piece, cv2.COLOR_BGR2GRAY), 50, 150)

# 后续匹配逻辑同方案1
result = cv2.matchTemplate(img_board_gray, img_piece_gray, cv2.TM_CCOEFF_NORMED)
threshold = 0.7
locations = np.where(result >= threshold)
# ...(绘制代码省略)

关键调整点

  • 用TM_CCOEFF_NORMED替代TM_SQDIFF,该方法对亮度变化鲁棒性更强,匹配值越接近1说明匹配度越高。
  • 添加阈值过滤,避免噪声干扰。
  • 保留棋子原始特征,不要做过度的形态学操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 22:50:23