用PythonOpenCV打造五子棋智能裁判从拍照到胜负判断的全流程实现周末和朋友下五子棋时经常为这算不算五连珠争得面红耳赤今天我们就用Python和OpenCV打造一个智能裁判系统只需拍张照片程序就能自动识别棋盘状态并判断胜负。这个项目不仅能解决实际游戏争议更是学习计算机视觉的绝佳案例。1. 环境准备与基础概念在开始编码前我们需要准备好开发环境并理解几个核心概念。这个项目适合已经掌握Python基础语法想尝试计算机视觉实践的开发者。如果你还没安装过OpenCV下面这条命令可以帮你快速搭建环境pip install opencv-python numpy matplotlib五子棋识别系统的三个关键环节棋盘定位从照片中准确找到棋盘区域棋子识别区分黑白棋子并确定它们在棋盘上的位置胜负判断检查是否存在五子连珠的情况OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉库它包含了数百种图像处理和计算机视觉算法。我们将主要使用它的以下功能图像预处理灰度转换、高斯模糊边缘检测Canny算法形状识别霍夫圆变换颜色空间转换HSV色彩空间提示实际开发中建议使用Jupyter Notebook分步测试每个环节的效果方便调试参数。2. 从照片中精准定位棋盘手机拍摄的棋盘照片往往包含背景杂物我们的第一步是从复杂背景中提取出棋盘区域。这里采用边缘检测轮廓分析的方法import cv2 import numpy as np def locate_board(image_path): # 读取图像并转换为灰度图 img cv2.imread(image_path) gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 高斯模糊降噪 blur cv2.GaussianBlur(gray, (5, 5), 0) # Canny边缘检测 edges cv2.Canny(blur, 50, 150) # 寻找轮廓 contours, _ cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 找出面积最大的轮廓假设为棋盘 max_contour max(contours, keycv2.contourArea) # 获取最小外接矩形 rect cv2.minAreaRect(max_contour) box cv2.boxPoints(rect) box np.intp(box) return img, box常见问题及解决方案问题现象可能原因解决方法找不到棋盘轮廓背景太复杂或棋盘边缘不明显调整Canny算法的阈值参数识别到多个轮廓棋盘被其他物体部分遮挡增加预处理步骤或手动选择轮廓棋盘区域不完整拍摄角度倾斜使用透视变换矫正视角注意实际应用中建议在图像中绘制识别到的轮廓进行可视化检查确保棋盘定位准确后再进行下一步。3. 棋子检测与颜色识别定位到棋盘后接下来要识别各个棋子及其颜色。五子棋棋子通常呈现明显的圆形特征我们可以利用霍夫圆变换来检测def detect_stones(img, board_box): # 提取棋盘区域简化版实际需做透视变换 gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 霍夫圆变换参数设置 circles cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, dp1, minDist25, param1100, param219, minRadius10, maxRadius20) if circles is not None: circles np.uint16(np.around(circles[0])) # 转换到HSV颜色空间便于颜色识别 hsv cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 定义黑白棋子的颜色范围 lower_black np.array([0, 0, 10]) upper_black np.array([180, 255, 90]) lower_white np.array([0, 0, 100]) upper_white np.array([180, 30, 255]) stones [] for (x, y, r) in circles: # 提取棋子区域 roi hsv[y-r:yr, x-r:xr] # 统计颜色分布 mask_black cv2.inRange(roi, lower_black, upper_black) mask_white cv2.inRange(roi, lower_white, upper_white) # 根据像素数量判断棋子颜色 if cv2.countNonZero(mask_white) 50: stones.append((white, x, y)) elif cv2.countNonZero(mask_black) 50: stones.append((black, x, y)) return stones return []霍夫圆变换参数调优指南minDist圆之间的最小距离根据棋盘格子大小调整param1Canny边缘检测的高阈值值越大检测到的边缘越少param2圆心累加器阈值值越小检测到的圆越多可能包含假圆minRadius/maxRadius根据棋子实际大小设置4. 棋盘坐标系转换与胜负判断识别出各个棋子后需要将它们映射到19×19的棋盘坐标系中然后检查是否有五子连珠def map_to_grid(stones, board_box): # 计算棋盘物理尺寸 width np.linalg.norm(board_box[0] - board_box[1]) height np.linalg.norm(board_box[1] - board_box[2]) # 计算每个格子的大小 grid_size max(width, height) / 18 # 初始化19x19棋盘 board [[0 for _ in range(19)] for _ in range(19)] for color, x, y in stones: # 计算行列索引简化版实际应考虑透视变换 col int(round((x - board_box[0][0]) / grid_size)) row int(round((y - board_box[0][1]) / grid_size)) if 0 row 19 and 0 col 19: board[row][col] 1 if color white else 2 return board def check_victory(board): directions [(0, 1), (1, 0), (1, 1), (1, -1)] for i in range(19): for j in range(19): if board[i][j] 0: continue for di, dj in directions: count 1 ni, nj i di, j dj while 0 ni 19 and 0 nj 19 and board[ni][nj] board[i][j]: count 1 ni di nj dj if count 5: return board[i][j] return 0胜负判断算法优化技巧只检查最后落子点周围的连线情况减少计算量使用位运算加速棋盘状态判断实现禁手规则如职业比赛中的三三禁手、四四禁手等5. 系统集成与用户体验优化将各个模块整合成完整的应用程序并考虑实际使用场景中的各种情况def main(image_path): # 1. 定位棋盘 img, board_box locate_board(image_path) # 2. 检测棋子 stones detect_stones(img, board_box) # 3. 映射到棋盘 board map_to_grid(stones, board_box) # 4. 判断胜负 result check_victory(board) # 可视化结果 for color, x, y in stones: cv2.circle(img, (x, y), 10, (0,255,0) if colorwhite else (0,0,255), 2) cv2.imshow(Result, img) cv2.waitKey(0) cv2.destroyAllWindows() if result 1: return 白方胜利 elif result 2: return 黑方胜利 else: return 比赛继续...提升鲁棒性的实用技巧光照条件处理使用直方图均衡化改善对比度尝试不同的颜色空间如LAB棋盘材质适应# 自适应阈值处理 gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blur cv2.GaussianBlur(gray, (5, 5), 0) thresh cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)手机拍摄角度补偿使用透视变换矫正倾斜通过特征点匹配对齐标准棋盘性能优化缓存处理结果避免重复计算使用多线程处理图像分析6. 进阶扩展方向完成基础版本后可以考虑以下增强功能多平台适配方案开发手机APP集成核心算法基于Flask搭建Web服务微信小程序版本实现AI增强功能# 使用深度学习模型提升识别准确率 model cv2.dnn.readNet(chess_piece_detector.pb) blob cv2.dnn.blobFromImage(img, 1/255., (224,224)) model.setInput(blob) output model.forward()其他创新点子自动记录棋局过程分析最佳落子位置棋局回放与分享功能联机对战模式在真实项目测试中我发现棋盘格线颜色对棋子识别影响很大——深色棋盘上的白子识别率明显高于浅色棋盘。一个实用的解决方法是先检测棋盘格线颜色然后动态调整棋子颜色判断阈值。
保姆级教程:用Python+OpenCV给五子棋拍个照,自动识别胜负(附完整代码)
发布时间:2026/6/11 13:08:21
用PythonOpenCV打造五子棋智能裁判从拍照到胜负判断的全流程实现周末和朋友下五子棋时经常为这算不算五连珠争得面红耳赤今天我们就用Python和OpenCV打造一个智能裁判系统只需拍张照片程序就能自动识别棋盘状态并判断胜负。这个项目不仅能解决实际游戏争议更是学习计算机视觉的绝佳案例。1. 环境准备与基础概念在开始编码前我们需要准备好开发环境并理解几个核心概念。这个项目适合已经掌握Python基础语法想尝试计算机视觉实践的开发者。如果你还没安装过OpenCV下面这条命令可以帮你快速搭建环境pip install opencv-python numpy matplotlib五子棋识别系统的三个关键环节棋盘定位从照片中准确找到棋盘区域棋子识别区分黑白棋子并确定它们在棋盘上的位置胜负判断检查是否存在五子连珠的情况OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉库它包含了数百种图像处理和计算机视觉算法。我们将主要使用它的以下功能图像预处理灰度转换、高斯模糊边缘检测Canny算法形状识别霍夫圆变换颜色空间转换HSV色彩空间提示实际开发中建议使用Jupyter Notebook分步测试每个环节的效果方便调试参数。2. 从照片中精准定位棋盘手机拍摄的棋盘照片往往包含背景杂物我们的第一步是从复杂背景中提取出棋盘区域。这里采用边缘检测轮廓分析的方法import cv2 import numpy as np def locate_board(image_path): # 读取图像并转换为灰度图 img cv2.imread(image_path) gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 高斯模糊降噪 blur cv2.GaussianBlur(gray, (5, 5), 0) # Canny边缘检测 edges cv2.Canny(blur, 50, 150) # 寻找轮廓 contours, _ cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 找出面积最大的轮廓假设为棋盘 max_contour max(contours, keycv2.contourArea) # 获取最小外接矩形 rect cv2.minAreaRect(max_contour) box cv2.boxPoints(rect) box np.intp(box) return img, box常见问题及解决方案问题现象可能原因解决方法找不到棋盘轮廓背景太复杂或棋盘边缘不明显调整Canny算法的阈值参数识别到多个轮廓棋盘被其他物体部分遮挡增加预处理步骤或手动选择轮廓棋盘区域不完整拍摄角度倾斜使用透视变换矫正视角注意实际应用中建议在图像中绘制识别到的轮廓进行可视化检查确保棋盘定位准确后再进行下一步。3. 棋子检测与颜色识别定位到棋盘后接下来要识别各个棋子及其颜色。五子棋棋子通常呈现明显的圆形特征我们可以利用霍夫圆变换来检测def detect_stones(img, board_box): # 提取棋盘区域简化版实际需做透视变换 gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 霍夫圆变换参数设置 circles cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, dp1, minDist25, param1100, param219, minRadius10, maxRadius20) if circles is not None: circles np.uint16(np.around(circles[0])) # 转换到HSV颜色空间便于颜色识别 hsv cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 定义黑白棋子的颜色范围 lower_black np.array([0, 0, 10]) upper_black np.array([180, 255, 90]) lower_white np.array([0, 0, 100]) upper_white np.array([180, 30, 255]) stones [] for (x, y, r) in circles: # 提取棋子区域 roi hsv[y-r:yr, x-r:xr] # 统计颜色分布 mask_black cv2.inRange(roi, lower_black, upper_black) mask_white cv2.inRange(roi, lower_white, upper_white) # 根据像素数量判断棋子颜色 if cv2.countNonZero(mask_white) 50: stones.append((white, x, y)) elif cv2.countNonZero(mask_black) 50: stones.append((black, x, y)) return stones return []霍夫圆变换参数调优指南minDist圆之间的最小距离根据棋盘格子大小调整param1Canny边缘检测的高阈值值越大检测到的边缘越少param2圆心累加器阈值值越小检测到的圆越多可能包含假圆minRadius/maxRadius根据棋子实际大小设置4. 棋盘坐标系转换与胜负判断识别出各个棋子后需要将它们映射到19×19的棋盘坐标系中然后检查是否有五子连珠def map_to_grid(stones, board_box): # 计算棋盘物理尺寸 width np.linalg.norm(board_box[0] - board_box[1]) height np.linalg.norm(board_box[1] - board_box[2]) # 计算每个格子的大小 grid_size max(width, height) / 18 # 初始化19x19棋盘 board [[0 for _ in range(19)] for _ in range(19)] for color, x, y in stones: # 计算行列索引简化版实际应考虑透视变换 col int(round((x - board_box[0][0]) / grid_size)) row int(round((y - board_box[0][1]) / grid_size)) if 0 row 19 and 0 col 19: board[row][col] 1 if color white else 2 return board def check_victory(board): directions [(0, 1), (1, 0), (1, 1), (1, -1)] for i in range(19): for j in range(19): if board[i][j] 0: continue for di, dj in directions: count 1 ni, nj i di, j dj while 0 ni 19 and 0 nj 19 and board[ni][nj] board[i][j]: count 1 ni di nj dj if count 5: return board[i][j] return 0胜负判断算法优化技巧只检查最后落子点周围的连线情况减少计算量使用位运算加速棋盘状态判断实现禁手规则如职业比赛中的三三禁手、四四禁手等5. 系统集成与用户体验优化将各个模块整合成完整的应用程序并考虑实际使用场景中的各种情况def main(image_path): # 1. 定位棋盘 img, board_box locate_board(image_path) # 2. 检测棋子 stones detect_stones(img, board_box) # 3. 映射到棋盘 board map_to_grid(stones, board_box) # 4. 判断胜负 result check_victory(board) # 可视化结果 for color, x, y in stones: cv2.circle(img, (x, y), 10, (0,255,0) if colorwhite else (0,0,255), 2) cv2.imshow(Result, img) cv2.waitKey(0) cv2.destroyAllWindows() if result 1: return 白方胜利 elif result 2: return 黑方胜利 else: return 比赛继续...提升鲁棒性的实用技巧光照条件处理使用直方图均衡化改善对比度尝试不同的颜色空间如LAB棋盘材质适应# 自适应阈值处理 gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blur cv2.GaussianBlur(gray, (5, 5), 0) thresh cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)手机拍摄角度补偿使用透视变换矫正倾斜通过特征点匹配对齐标准棋盘性能优化缓存处理结果避免重复计算使用多线程处理图像分析6. 进阶扩展方向完成基础版本后可以考虑以下增强功能多平台适配方案开发手机APP集成核心算法基于Flask搭建Web服务微信小程序版本实现AI增强功能# 使用深度学习模型提升识别准确率 model cv2.dnn.readNet(chess_piece_detector.pb) blob cv2.dnn.blobFromImage(img, 1/255., (224,224)) model.setInput(blob) output model.forward()其他创新点子自动记录棋局过程分析最佳落子位置棋局回放与分享功能联机对战模式在真实项目测试中我发现棋盘格线颜色对棋子识别影响很大——深色棋盘上的白子识别率明显高于浅色棋盘。一个实用的解决方法是先检测棋盘格线颜色然后动态调整棋子颜色判断阈值。