【OpenCV】如何优雅地让机器人帮你玩打地鼠游戏(计算机视觉小项目)

上学期《计算机视觉》课的project题目,我们组使用OpenCV配合实验室的Delta并联机器人实现了一个简单的打地鼠游戏的物理外挂。

说是外挂,其实效果和人工操作起来还是有差距的。

废话不多说,先上效果展示:
https://www.bilibili.com/video/av44728617

项目代码链接:https://github.com/chenyr0021/WhacAMole


OpenCV版本:3.2.0
运行平台:win10,Visual Studio 2015
游戏来源:iPad AppStore

【OpenCV】如何优雅地让机器人帮你玩打地鼠游戏(计算机视觉小项目)_第1张图片


整个系统的框架如下图:
【OpenCV】如何优雅地让机器人帮你玩打地鼠游戏(计算机视觉小项目)_第2张图片

1、相机标定

标定程序是从网上找到的,参见
https://blog.csdn.net/hust_bochu_xuchao/article/details/51838732
在这里我把代码稍作改动,封装成一个标定函数,方便在我的主程序调用。
将标定好的数据包括内外参数和畸变参数保存到xml文件里,以后再使用同一个摄像头就不用再次标定了。

2、预处理

预处理部分主要是裁剪,二值化,寻找iPad轮廓及投影变换。

  • 裁剪主要是把使图像中的iPad轮廓更加突出,便于后面的轮廓提取。
frame = src_frame(Rect(Point(150,150),Point(550,380)));
  • 因为iPad颜色比较鲜亮,背景相对单一,所以二值化使用的方法是RGB颜色筛选,调用的函数是OpenCV inRange()函数。其他方法例如灰度图直接二值化、使用HSV的V通道二值化都对环境光照鲁棒性不强,使用Canny算子提取边缘的效果也不太好。
    下面两张图是V空间的二值化和颜色过滤二值化的对比。
    【OpenCV】如何优雅地让机器人帮你玩打地鼠游戏(计算机视觉小项目)_第3张图片
    【OpenCV】如何优雅地让机器人帮你玩打地鼠游戏(计算机视觉小项目)_第4张图片
  • 轮廓查找使用findContours()函数,按面积筛选出iPad的内边框,拟合成四边形,提取角点,这个区域设为ROI。
//寻找、筛选轮廓
vector< vector<cv::Point> > contours_list;
vector< vector<cv::Point> > contours_sublist;
findContours(binary_frame, contours_list, RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
vector<Point> corner;
for (int i = 0; i < contours_list.size(); i++)
{
	if (contourArea(contours_list[i]) > 20000)
		contours_sublist.push_back(contours_list[i]);
}
//筛选面积大于20000中最小的
int min_area = 640*480;
for (int i = 0; i < contours_sublist.size(); i++)
{
	if (contourArea(contours_sublist[i]) < min_area)
	{
		min_area = contourArea(contours_sublist[i]);
		//cout <<"min_area: "<< min_area << endl;
		corner = contours_sublist[i];
	}
	//drawContours(frame_to_show, contours_sublist, i, Scalar(255), 8);
}
  • 我们希望最终将摄像头提取到的图像转化为类似游戏截图的比较方正的图像。这个过程主要通过投影变换实现。
    现在已知我们期望得到的图像大小为400*300(iPad屏幕比例为4:3),那么角点就可以得到,ROI区域的四个角点坐标也已知,可以计算对应的投影变换矩阵。
Point2f corner_dst[4] = {Point2f(0, 0), 
						 Point2f(400, 0),
						 Point2f(400, 300), 
						 Point2f(0, 300)};
//计算投影变换矩阵
Mat transfer_mat = getPerspectiveTransform(corner_dst, corner_src);

PS:这里应当注意两组角点的顺序应当一致

最后一道工序就是直方图均衡化了,变换后的效果图差不多就是这个样子:

【OpenCV】如何优雅地让机器人帮你玩打地鼠游戏(计算机视觉小项目)_第5张图片
太丑了不忍直视emmmm…

3、识别

到这一步,基本就可以进行模板匹配了。从上图里面选个幸运儿,截个图下来就是一个模板了。

但是只用一个模板的话可能效果不太好,毕竟图像本身比较糊,而且这些位置的地鼠亮度什么的不太一致。

我们采用的方法就是把所有的地鼠都做个模板,一一匹配,哪个值最高就选哪个。这样虽然牺牲了一些时间,但是效果会提升很多。

当然如果有其他的方法把图像处理的更清楚就更好了,不过本菜鸡没想到哈哈。

识别的代码就比较简单了,注意阈值的设置需要调试。

到这里,视觉的部分就全部结束了。

*串口

地鼠已经识别出来了,具体的打击操作还需要专业人士——Delta机器人来完成。

Delta机器人是隔壁实验室的三轴并联机器人,本身比较大,视频演示中并没有拍到它的全貌。用到这个项目上的确有点小题大作了,嗯。

这里使用串口通讯的方式向机器人的上位机发送地鼠的位置,9个地鼠分别编号1~9。根据地鼠的像素坐标确定其编号。

windows的串口操作本菜鸡也不是很懂,因此参照了
https://blog.csdn.net/zmdsjtu/article/details/78539681
这里不再赘述。

最后

全部代码已上传至GitHub,链接在开头。

整个课程设计做了大概两周,感谢 琪宝宝A+少女真真姐 的辛苦付出~

你可能感兴趣的:(OpenCV)