- 要在较为混乱的条件下稳定输出目标角度
- 快速移动目标的识别
- 摄像头读取图像
- 对图像进行预处理
- 识别目标装甲
- 通过决策,选出最佳目标(若存在多个候选目标)
- 对目标进行追踪
- 角度解算发送给stm32:Yaw + Pitch
- opencv3.4.1
- cmake
- gcc/g++
- Ubuntu 18.04
- 函数原型
Mat findContourInEnemyColor(Mat *frame, color col,
vector<RotatedRect> *rotateRects, vector<vector<Point>> *points)
把相机的曝光值调的尽量低一些。三颜色通道分离,取绿色与目标颜色两个通道。
各自确定阈值,二值化图像。需要剔除一些细小的连通区域,先进行开运算,然后进行闭运算。
最后得到两幅二值化图像:绿色通道上阈值与目标颜色通道上的阈值后的图像。把两个二值图像相与(&),使得轮廓的边沿更加光滑。再把相与后的图像进行滤波处理,这里我用了高斯滤波。
然后确定连通区域。这里用了opencv自带的findContours()
函数,之后得到连通区域的向量vector
。
这个向量里的每一个连通区域意味着一个灯条或者满足改阈值限定的发光斑点。
由于步兵的装甲板与水平面的角度都是近似垂直的,加了一个限定条件,就是与地面的夹角近似为垂直,不能太大,太大的直接排除掉。判断角度这个主要用到了pca降维,结算出每一个连通区域与水平面的夹角(0~180)。60-120的连通区域予以保留。
构成每一个连通区域的点的数量不能太低,我最低限定在了15个。将满足所有条件的‘灯条’保存起来。
这里的限定条件主要有:
- 两个灯条的角度需小于一定值
- 两个灯条的中心点位置的坐标的y值相减不能超过一定值
- 每个灯条的宽度与高度限定在一个区间,不能太大或太小
- 两个灯条围成的旋转矩形宽高比要符合装甲板的实际尺寸。检测的宽高比与实际的宽高比相减需小于一定值
- 两个灯条的高度与宽度要相似,不能差太多 实现的函数分别是
vector<myRect> make_allArma(vector<RotatedRect> *all, Mat image, vector<vector<Point>> *points)
bool patchArmaFom_model_vector(RotatedRect *left, RotatedRect *right, Mat binayImag)
已经得到了相互关联的灯条了,每一对都代表着可能的装甲板。我们需要决策出最佳目标。写了一个得分函数,计算每个区域的得分情况。通过排序,选出最佳得分区域,输出为一个矩形作为检测的最终目标。
得分由以下因素组成:
- 角度差值:差值小则得分高(主要)
- 中心点差值: 偏差小则得分高(主要)
- 两个灯条宽高,形态上的差值:偏差小则得分高
- 左右灯柱中心点的连线与水平线之间的角度值 越小越好
- 偏离垂直方向角度绝对值 越小越好
计算之后,就可以选择最符合的了。
这里我用了官方开源的程序,通过AngleSolverFactory
类的实例化对象的getAngle()
方法进行解算。
将上一步解算的角度发送给stm32控制云台。注意云台控制需要进行滤波。
- 采用机器学习的方式进行检测
- 采用更高级的追踪器进行追踪如KCF
- 角度解算精度有待提高
- 提高侧面的检测成功率