由于24年电赛E题要求做一个装置能够放置棋子且能覆盖棋盘与棋格范围,因此选择市面上售卖的写字机结构,包含双X轴步进电机,Y轴步进电机以及Z轴步进电机,使用LINUX板卡和TC264组成上下位机系统,由串口进行通讯,传递棋盘内所有关键点坐标
由于本开源方案使用的是LINUX板卡作为上位机而非像大多数队伍一样选择使用OpenMV与K210等嵌入式摄像头方案,因此本工程使用OpenCV库进行机器视觉编写,工程架构加入了状态机用于多模式的切换
使用OpenCV内置的边缘检测函数以及轮廓检测函数进行棋盘识别,先用 Sobel算子
进行图像的边缘提取,使得边缘特征较为明显后进行高斯模糊以及图形学开运算使棋盘边缘变得更为平滑,方便 findContours函数
进行轮廓检测。
对于棋盘的序号问题,本方案使用向量法进行判断,先用 RotatedRect类
中的 angle
成员获取目前矩形的角度、通过 center
成员获取矩形中心坐标和通过 points函数
获取矩形四角点坐标,以此为基础判断棋盘格是逆时针旋转还是顺时针旋转,从而对 angle
的角度进行解算,并由解算后的角度计算出一个参考向量,
将通过遍历将棋盘格中心与九宫格九个中心点分别构成的向量与参考向量的内积与外积判断出向量相较于参考向量的空间位置,以此判断出棋盘格的序号
在棋盘格外划定 ROI区域
并对图像进行色彩空间转换,由 BGR
转为 HSV
图像,使颜色能够更好的分离,通过 SWAN/tool
路径下的 HSV_tool
获取所需的黑白双色二值化阈值,用这两个阈值分离出黑白两色即棋子颜色,再使用 findContours函数
进行轮廓检测,若轮廓中心在 ROI区域
内则其为所需的棋子,记录其坐标
对于人机对弈,本方案采用 MinMax算法
,即 极小化极大值算法
通过递归将所有可能行进行遍历,使用决策树以及估值函数选定最优路径,这是一种深度优先的树形图搜索算法。对于具体原理,网上资料较多,不再赘述
使用 USB-TTL模块
进行上下位机通讯,具体通信协议为:
帧头1:0xa0
帧头2:0xa1
帧尾:0xa2
上位机 -> 下位机:
- 帧头1 帧头2 坐标序号(int32) 坐标x(int32) 坐标y(int32) 帧尾
- 帧头1 帧头2 棋盘序号1(uint8) 棋盘序号2(uint8) 帧尾
下位机 -> 上位机:
- 帧头1 帧头2 模式(uint8) 装置棋色(uint8) 帧尾
上位机 -> 下位机
的两种通信协议分别用于
-
传递九宫格与棋子坐标
-
传递下棋阶段的棋盘序号
由于题6要求将人为移动的棋子移回老位置,因此通讯协议2采用了两个序号,考虑与题4、5的兼容性,若玩家未进行作弊行为,则棋盘序号2默认发送 0xff
.
下位机基本上是接收上位机讯息并进行操作的,因此没啥好说的
步进电机能够固定转一定微小的角度,在不丢步的情况下能做到极高的准确度,下位机需要对发给步进电机的脉冲进行计数,以此记录步长,由于棋盘是一个二维坐标系,因此通过对X轴和Y轴的步长进行积聚以及确认好初始位置就可以进行坐标系建立从而达成全局控制了
- 由于本工程下位机部分不是本人负责,且因为下位机步进电机控制写的有点问题导致每次步进电机控制函数后需要有延时操作
- 上位机的摄像头可以选择畸变更小的,防止图像坐标经换算后与装置坐标差距过大导致棋子压线,也可以使用去畸变算法,但经本人实测,效果并不理想,可能是因为标定板不够大吧