基于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
相关产品推荐
相关产品推荐

