《OpenCV2 计算机视觉编程手册》视频处理二

本文结合上文《OpenCV2 计算机视觉编码手册》视频处理一的基础上,添加视频跟踪类,来对视频中运动对象进行跟踪。


1. 添加特征跟踪类

#ifndef FTRACKER
#define FTRACKER

#include "head.h"
#include "videoprocessor.h"
#include <opencv2/video/tracking.hpp>
#include <opencv2/features2d/features2d.hpp>

class FeatureTracker : public FrameProcessor 
{	
private:
	cv::Mat gray;			            // 当前灰度图像
	cv::Mat gray_prev;		            // 前一个灰度图像
	std::vector<cv::Point2f> points[2]; // 两幅图像跟踪特征 0->1
	std::vector<cv::Point2f> initial;   // 跟踪点的初始化
	std::vector<cv::Point2f> features;  // 检测到的特征
	int max_count;	                    // 需要跟踪的最大特征数目
	double qlevel;                      // 特征检测中的质量等级
	double minDist;                     // 两特征点之间的最小距离
	std::vector<uchar> status;          // 跟踪的特征状态
    std::vector<float> err;             // 跟踪错误

public:
	// 构造函数
	FeatureTracker() : max_count(500), qlevel(0.01), minDist(10.) {}
	
	// 处理方法
	void process(cv:: Mat &frame, cv:: Mat &output) 
	{
		cv::cvtColor(frame, gray, CV_BGR2GRAY);  // 转换为灰度图像
		frame.copyTo(output);

		// 1. 如果需要添加新的特征点
		if(addNewPoints())
		{
			detectFeaturePoints();                                            // 检测特征点
			points[0].insert(points[0].end(),features.begin(),features.end());// 添加检测的特征到当前跟踪的特征
			initial.insert(initial.end(),features.begin(),features.end());
		}
		
		// 对应视频序列中的第一幅图像
		if(gray_prev.empty())
           gray.copyTo(gray_prev);
            
		// 2.跟踪特征
		cv::calcOpticalFlowPyrLK(gray_prev, gray, // 两幅连续图像
			points[0],                            // 图1中的输入点坐标
			points[1],                            // 图2中的输出点坐标
			status,                               // 跟踪成功
			err);                                 // 跟踪失败
           
		// 2. 遍历所有跟踪点进行筛选
		int k=0;
		for( int i= 0; i < points[1].size(); i++ ) 
		{
			// 是否需要保留该跟踪点?
			if (acceptTrackedPoint(i)) 
			{
				// 保留该跟踪点到vector
				initial[k]= initial[i];
				points[1][k++] = points[1][i];
			}
		}

		// 去除不成功点
        points[1].resize(k);
		initial.resize(k);

		// 3. 处理接受的跟踪点
		handleTrackedPoints(frame, output);

		// 4. 当前的点和图像变为它之前的点和图像
		std::swap(points[1], points[0]);
        cv::swap(gray_prev, gray);
	}

	// 特征点检测
	void detectFeaturePoints() 
	{	// 检测特征
		cv::goodFeaturesToTrack(gray, // 图像
			features,   // 检测到的特征
			max_count,  // 特征的最大数目
			qlevel,     // 质量等级
			minDist);   // 两个特征之间的最小距离
	}

	// 决定是否添加新点
	bool addNewPoints()
	{
		// 如果点的数量太少
		return points[0].size()<=10;
	}

	// 决定哪些点应该跟踪
	bool acceptTrackedPoint(int i)
	{
		return status[i] &&
			// 如果它移动了
			(abs(points[0][i].x-points[1][i].x)+
			(abs(points[0][i].y-points[1][i].y))>2);
	}

	// 处理当前跟踪点
	void handleTrackedPoints(cv:: Mat &frame, cv:: Mat &output) 
	{
		// 遍历所有跟踪点
		for(int i= 0; i < points[1].size(); i++ ) 
		{
			// 绘制直线和圆
		    cv::line(output, 
				initial[i],            // 初始位置
				points[1][i],          // 新位置
				cv::Scalar(255,255,255)// 白色
				);

			cv::circle(output,          // 输出图像
				points[1][i],           // 圆心
				3,                      // 半径
				cv::Scalar(255,255,255),// 白色
				-1                      // 负数表示填充圆圈, 整数表示线条厚度
				);
		}
	}
};

#endif

2. main函数

#include "featuretracker.h"

int main()
{
	VideoProcessor processor;                           // 创建一个视频处理实例
	FeatureTracker tracker;                             // 创建一个特征跟踪实例
	processor.setInput("../bike.avi");                  // 打开视频文件
	processor.setFrameProcessor(&tracker);              // 设置帧处理器为一个特征跟踪实例tracker
	processor.displayOutput("Tracked Features");        // 声明跟踪特征显示窗口
	processor.setDelay(1000./processor.getFrameRate()); // 设置视频播放帧率为原始帧率
	processor.run();                                    // 开始处理
	cv::waitKey();                                      // 等待按键响应

	return 0;
}










  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Digital2Slave

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值