OpenCV是一个广泛用于图像处理、机器视觉领域的C++库。近期接到一个室内飞行器定位的需求,大概是在天花板上有一个摄像头,下方是一些无人机,要如何在摄像头采集的图像中定位到这些无人机?(一开始我直接想到的是使用人脸检测,在无人机上贴人脸,然后对其进行检测,但或许有点太骚了?)于是我想到了使用二维码进行定位,并写了个程序测试了一下,效果还算不错。
思路
二维码的检测与定位
二维码检测有非常多的库可供使用,我尝试了使用OpenCV里的ObjDetect内置的二维码识别,结果效果很糟糕,所以就换用了ZBar,效果不错。
二维码的跟踪
如果对每一帧图像都只使用检测的方法,那么在二维码离得比较远的情况下,检测就会失效。因此,需要编写一个逻辑,在检测算法无法检测到二维码的情况下,换用目标跟踪算法进行跟踪。
实现
我将以上思路使用C++进行了实现,并封装成了类,方便进行调用,效果不错。项目使用了Qt的qmake进行开发,需要用Qt Creator打开项目。如果需要使用其中封装好的类,只需将QRDetectorAndTracker取出即可。
项目源码:
https://github.com/huanghaozi/QRDetectorAndTracker
效果:
其中方框为绿色时表示正在使用目标跟踪算法,为蓝色时表示正在使用检测算法。
扩展
多目标跟踪
已集成至原程序,Github已更新
使用说明
加入包含文件及链接库依赖
1. 首先需要将opencv和zlib文件夹复制到自己的项目目录下
2. 需要在项目的Include Path中加入opencv/include、zlib/include
3. 需要将opencv/bin、zlib/bin下的dll文件加入项目的动态链接库中,或直接将其复制到与exe相同的目录下
包含头文件
需要将该Repo中的QRDetectorAndTracker.cpp及QRDetectorAndTracker.h文件加入自己的项目中
在需要用到的地方添加
#include "QRDetectorAndTracker.h"
类的结构
变量
//默认从摄像头获取图像
std::vector<int> x, y; //二维码的坐标,考虑到存在多个二维码,所以用容器
cv::Mat pic; //含有方框标记的输出图像,执行drawBound后此变量才有内容
std::vector<bool> xyAvailable; //是否识别到二维码,即坐标是否可用
std::vector<std::string> qrChars; //二维码的内容,考虑到存在多个二维码,所以用容器
函数
void detect(); //检测函数,将从摄像头读取一帧图像并检测,将检测的坐标、内容存入上述变量中
void drawBound(); //在检测到二维码的位置画个方框,存入pic变量中
void showPic(cv::String s); //显示图像窗口,其中参数s为窗口标题
示例
//初始化
QRDetectorAndTracker qr;
while(1) //主循环
{
//检测坐标
qr.detect();
//绘制方框并显示
qr.drawBound();
qr.showPic("Window");
//输出坐标,遍历xyAvailable
for(int i=0;i<std::distance(qr.xyAvailable.begin(), qr.xyAvailable.end());i++)
{
if(qr.xyAvailable[i]) //若坐标可用则输出
std::cout << qr.qrChars[i] << ": " << qr.x[i] << ", " << qr.y[i] << std::endl;
}
//循环延时,不加会卡死
if(cv::waitKey(1)==27)
break;
}