2020 8 18
RM 2020赛季已经结束,本文主要讲解OpenCV识别程序
讲解RM视觉部分(一) 英雄 步兵 哨兵的通用OpenCV(Open Computer Vision 开源计算机视觉)部分
学弟们在看该部分代码之前,应该 ①熟悉《OpenCV3编程入门》(毛星云版)的前8章,(熟悉:要么你能背诵,
要么可以在5秒之内在找到你想要的函数);
②知道计算机视觉所涉及到的几大坐标系(世界坐标系,相机坐标系,图像平面坐标系....)
https://blog.csdn.net/weizhangyjs/article/details/81020177
(能看懂即可,我的代码里涉及到坐标系变换,PnP里也涉及到坐标系变换)
③除上述,你还必须掌握的OpenCV:PnP, kalman滤波
④当然,C++还是得会,C++多线程要会
⑤会看别的学校的代码,可以在github上找到
1.调试工具
由于经常需要调试程序,输出一些变量啊,看一些变量的变化情况啊,所以把常用的那几个封装在一起
Debug
反正没人喜欢看字,就看图吧,当然还有一些宏定义方便调用
JLink
主要用来显示一些变量的变化情况,一般用于调kalman滤波的参数,我搞的太花里胡哨了,所以调用的时候会极大降低识别速度,慎用
2.步入正题
↑ 以上为原图, 减小光圈,降低曝光有利识别, 降低曝光至刚好可以看清数字
2.1识别灯条
开始RM视觉的编写后,你会发现你永远离不开灯条识别、灯条匹配,以下都是我们的方法,仅供参考,你们可以写出更好的
灯条识别的基本步骤: 二值化->边缘检测->最小包围图形->筛选
(一)二值化:找出图片中敌方的颜色
你们一定会听到"一定要优化灯条匹配的条件,节约时间,因为那里有两层for"这类的话.
两层for的时间复杂度为O(n^2),比较耗时, 其实还有一个地方有两层for---二值化
二值化,你必须遍历每一个像素点,如果把图像看成二维数组,将用两重for遍历,
在640*480的图像中这一步的耗时将多于灯条匹配. 所以我直接遍历所有像素,筛选出目标颜色(函数Contours TargetFind::getContours)
相比于有些学校使用的"先转灰度图,在阈值化(找到亮的区域),再选出想要的颜色"这种方法要快2ms左右
同时,使用
当然,还有更好的方法可以提高识别速率
(二)边缘检测:找到灯条的轮廓方便后续匹配
边缘检测基本就是调用书里的函数,在这里不多讲,你至少要知道每个参数的意义
(三)最小包围图形
为啥这里说的是最小包围图形, 因为我尝试过最小包围矩形,和椭圆拟合(cv::fitEllipse椭圆拟合),
椭圆效果略好一点点(不是很明显),当然建议你们都尝试一下,可能是我参数没调好.
这里一定要注意!!!!!!!!!一定要了解opencv中旋转矩形的表示方法,因为你会发现:有时两个相互平行的旋转矩形,角度相差90度.
(四)识别条件
识别灯条的条件一般为:长宽,面积,角度; 相关阈值还是要自己调
2.2灯条匹配(装甲板识别)
两重for循环遍历灯条的两两组合, 找到符合条件的组合(装甲)
这里列举以下, 我用到的条件:
①灯条大小接近;
②角度接近
③错配度(函数 malposition)较小(这里我参考了上海交大的代码)
④面积和距离满足比值条件
这些条件可以识别交近距离内(3m之内),大部分装甲板
以下是子午用的方法:
三维的装甲板四个特征点通过坐标变换可以得到图像中的特征点. 子午通过计算变换矩阵,判断是否为装甲板