OpenCV实现物体追踪
项目简介
通过Opencv内置函数实现物体追踪,并且部署在ROS中,实现摄像头读取。本文不涉及追踪算法的具体原理,而是针对RM中装甲板识别做出具体的实践部署。
具体项目已经部署在GitHUb:https://github.com/Phoenizard/Track-Image-InROS
追踪对象
使用opencv自带的追踪对象,需要调用一下头文件:
1 2 3
| #include <opencv2/opencv.hpp> #include <opencv2/tracking.hpp> #include <opencv2/core/ocl.hpp>
|
在OpenCV中一共有7中追踪算法,分别是BOOSTING
, MIL
, KCF
, TLD
, MEDIANFLOW
, MOSSE
, CSRT
,在使用中选择最常见的KCF
算法
声明追踪对象
使用creat()
构造
1
| yourtracker = TrackerKCF::create();
|
初始化目标
使用init(cv::Mat_flame,cv::Rect2d_object)
初始化
- Mat_flame:放入初始帧图片
- Rect2d_object:放入目标在初始帧照片中的像素矩阵
1 2
| cv::Rect2d bbox; yourtracker->init(flame, bbox);
|
更新目标
使用update(cv::Mat_flame,cv::Rect2d_object)
更新当前帧
- Mat_flame:放入当前帧
- Rect2d_object:放入上一帧目标矩形
1
| yourtracker->update(flame, bbox);
|
判断目标丢失
算法将自动通过滤波匹配目标,update()
函数在定义中为bool
类型,如果目标丢失,返回值为false
1 2
| bool ok = yourtracker->update(flame, bbox); if(!ok) cout << "Track Lost" << endl;
|
程序逻辑
在RM中,追踪算法运用于装甲板的识别和追踪中,代码逻辑如下:
代码实现
在ROS中,由于接受和发布照片在同一对象中完成,我们依然使用订阅和发布的模版对象SubPuber(自定义的对象):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| class SubPuber { private: ros::NodeHandle nodeHandle; ros::Subscriber imgSub; ros::Publisher trackobj; public: SubPuber() { imgSub = nodeHandle.subscribe("/camera/color/image_raw", 1, &SubPuber::ObjectTracker, this); trackobj = nodeHandle.advertise<sensor_msgs::Image>("/tracker", 1); } void ObjectTracker(const sensor_msgs::ImageConstPtr &frontRGBImg) { Mat image; try { image = cv_bridge::toCvShare(frontRGBImg, "bgr8")->image; } catch (cv_bridge::Exception& e) { ROS_ERROR("Could not convert to image!"); return; } sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image).toImageMsg(); trackobj.publish(*msg); } }
|
所以结合ROS::spin();
即可实现循环。具体来说,当程序运行到ros::spin()的时候,会找到订阅和发布的API,并且循环订阅和发布两个动作 [注意:不会循环代码的其他部分,仅仅是订阅和发布]。
在主程序中,创建对象和spin()
即可
1 2 3 4 5 6
| int main() { SubPuber tracker; ROS::spin(); }
|
观察代码,Initate Part
仅仅运行一遍,很适合创建追踪器,而在Program Part
可以把追踪的代码部署与此循环执行。补充代码如下:
由于作者手边没有装甲板信息,则使用ROI
交互界面,通过手动框出矩形框初始化目标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| Ptr<Tracker> tracker; cv::Rect2d bbox; int state = 0;
tracker = TrackerKCF::create();
if(state == 0){ bbox = bbox = selectROI(image, false); tracker->init(image,bbox); state = 1; }else { bool ok = tracker->update(image,bbox); if(ok) { rectangle(image, bbox, Scalar(255,0,0), 4); }else { cout << endl << "TrackLost" << endl; state = 0; } }
|