2020 8 29
不仅仅是识别那么简单
坐标变换
希望学弟们在看本文之前先把线性代数学好
1.坐标变换
其实,从物体的坐标(x,y,z)对应到图像中的坐标(x,y),经历了两次坐标变换,一共涉及到三个坐标系(分别是: 世界坐标系, 相机坐标系, 图像平面坐标系),
三者具体是啥, 相互之间怎么转换, 可以参考->相机标定
2.相机标定
了解了CV中的各种坐标系之后, 标定就是测量相机坐标系到图像平面坐标系的变换矩阵(相机矩阵), 以及衡量图像畸变的畸变矩阵, 二者合称内参, 只与相机有关.
世界坐标系到相机坐标系的变换矩阵显然与相机姿态有关, 被称为外参.
只要是将CV算法应用到实际, 都要涉及到相机标定. 具体标定代码, 可以参考:OpenCV相机标定, 当然也可以直接看我的代码.
网上大部分标定教程都是为了校正图像的畸变, 我们则是为了后续的坐标变换, 为了PnP, 在我测试过程中, 图像几乎没有畸变, 不需要校正, 提高帧率.
3.PnP(Perspective-n-Point)
PnP是一种算法,不是三极管!!!! 具体原理参考: PnP 算法原理
看看原理就好, 看看他怎么调用OpenCV的.
PnP可以求出R, T, R表示世界坐标系怎样旋转可以变为相机坐标系, T表示世界坐标系的原点需要怎样平移能与相机坐标系重合.
如果我们将世界坐标系与我们要击打的装甲板进行固连(以装甲板的中心点为世界坐标系原点, 以装甲板长方向为X周, 宽方向为Y轴, 垂直装甲板面向外为Z轴),
当然这里只是我使用的方式, 还可以是其他, 以下为具体实现, 只需算出在你定义的世界坐标系下,各个特征点的坐标即可.
此时, T便可以理解为: 在相机坐标系下的装甲板中心坐标. (重点, 下文要用到的)
4.机器人坐标系
假如我们已经准确识别到了对手, 对方没动, 而我方因为自瞄,操作手走位, 导致我方机器人姿态变换, 必然会造成敌方装甲板在图像中的位置变化,
此时, 如果你使用装甲板的像素坐标的变化对敌方装甲进行预测, 基本不可能正确.(敌方未动, 而你却觉得动了, 效果肯定不好).
引入"机器人坐标系"(瞎编的概念,不学术), 机器人初始化时!!!!!, 枪口水平向前(为Z轴), 垂直于枪管向右,向下为X轴和Y轴, 各轴方向不随机器人(pitch,yaw)而变化, 不转动仅平动.
这么定义的目的:
① 初始状态, 电控初始化, 枪口水平朝向正前方(电控给视觉发送的pitch=0,yaw=0), 机器人坐标系与摄像头坐标系几乎重合(各轴相互平行, 原点不一定重合);
② 运动时, 电控发送给视觉的pitch≠0,yaw≠0, (pitch为俯仰角), pitch和yaw就表示了摄像头坐标系到机器人坐标系的变换关系
(pitch为0时, yaw代表摄像头坐标系X与机器人坐标系X的夹角, yaw为0时, pitch表示摄像头坐标系Z与机器人坐标系Z的夹角),当时推了一下午得到如下变换矩阵:
后来发现具体推导可以参考CV中世界坐标系与相机坐标系的变换, 也可以直接用"罗德里格斯变换", 我还是菜了
使用该矩阵将PnP结果变为"机器人坐标系"下的坐标, 由于机器人坐标系不转动仅平动, 使用该坐标可以排除机器人pitch轴与yaw轴转动对预测带来的误差.
机器人平动造成的误差不应该考虑(具体为啥, 参考大学物理)
使用该方法预测敌方, 可以得到地方下一时刻的机器人坐标, 在用逆矩阵变为相机坐标, 乘相机矩阵得到像素坐标
注意事项:
进行了上述骚操作, 可以将预测结果画至图中, 无论自己动还是不动, 只要敌方不动, 预测结果就与装甲板中心重合(即与世界坐标系原点重合);
预测结果, 可能存在抖动, 与pitch, yaw, 装甲板的像素坐标测量不准有关.
5.kalman滤波
kalman虽然属于信号处理, 但OpenCV有相关函数. 具体原理吃了线代的亏,没看懂. 只会写个状态转移矩阵. 希望大家不要像我一样, 只有搞懂原理才有可能把他发挥到极致
简单说一下我怎么用kalman的. 前面说过预测存在抖动, kalman就可以解决. 你可以在预测前对输入数据(装甲的像素坐标)进性滤波, 也可以在也测后滤波,
甚至两次都滤波(我采用了两次都滤的方法)
需要能通过识别程序得知是否切换目标, 每次切换目标需要对kalman中的数据(除了状态转移矩阵)进行初始化, 否则相当于告诉滤波器"目标发生瞬移",
通常这严重违背状态转移矩阵, 会造成切换目标后的前10帧数据误差极大, 以下分别为"变换目标就初始化"(上)和"变换目标不初始化"(下),其余参数相同,
紫色为滤波后, 绿色为滤波前.
6.空气阻力
上赛季花了大量时间研究空气阻力, 最后也没搞出什么, 我使用F正比于V^2, 做了数值模拟, 并测量了实际曲线, 并不是很理想; 感兴趣的可以再试一试
随着弹丸的速度下降, 滞空时间延长, 抛物线越发明显, 空气阻力的影响加大, 如何根据目标距离, 子弹射速, 计算仰角将越来越难.
省赛尝试使用matlab拟合仰角, 子弹速度, 目标距离之间的关系, 效果不错, 建议使用
但要注意:
① 电控需要保证子弹射速稳定; 不因电量, 电压而变化; 连发速度下降不明显;
② 如果电控和结构做的特别好, 可以保证摩擦轮转速, 与子弹射速存在稳定关系, 可以直接拟合"仰角, 摩擦轮转速, 目标距离";
③ 数据越多越准确, 尽量覆盖可能使用到的范围.
7.其他
关于串口通信提一个我个人觉得好用的方法: 如果发现, 机器人枪口需要较长时间才能到达指定方向, 到达指定方向后有需要较长时间才能稳定(不抖动), 可以尝试将串口数据变为原来的3次方并乘一定系数, 保证正负号的同时, 放大较远时的偏移量, 缩小较近时的偏移量.