《视觉SLAM十四讲精品总结》9:直接法和光流法

内容:

二者关系

光流法

直接法

一、二者关系

引出原因:关键点和描述子计算非常耗时,可以保留特征点,使用光流法跟踪特征点运动。

关系:光流法描述像素在图像中运动直接法利用相机运动模型计算特征点在下一时刻图像中位置。

使用条件:直接法利用图像的像素灰度信息计算相机运动,需要场景中存在明暗变化。

二、LK光流法

光流法常用来跟踪角点的运动。之后用跟踪的特征点,用ICP、PnP或对极几何估计相机运动。

适用场景:要求相机运动缓慢,采集频率高

调用函数calcOpticalFlowPyrLK

void cv::calcOpticalFlowPyrLK(InputArray prevImg,nextImg,prevPts,nextPts,
OutputArray status,err,
Size winSize = Size(21, 21),int maxLevel = 3,
TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01),
int flags = 0,double 	minEigThreshold = 1e-4 
)	

 1、对第一帧提取FAST特征点存到keypoints中(list类型,之后还会删除)

2、对其他帧用LK跟踪特征点

3.  更新keypoints列表,从prev_keypoints到next_keypoints

 4. 画出 keypoints出为圆圈

int main(int argc, char** argv)
{
	string path_to_dataset = argv[1];
	string associate_file = path_to_dataset + "/associate.txt";
	//读入txt文本到fin中
	ifstream fin(associate_file);

	string rgb_file, depth_file, time_rgb, time_depth;
	// 因为要删除跟踪失败的点,keypoints使用list,元素类型是Point2f,坐标
	// 逐帧操作的将color承接为last_color,然后color读取新的图
	list< cv::Point2f > keypoints;      
	cv::Mat color, depth, last_color;

	for (int index = 0; index<100; index++)
	{
		//读入颜色和深度图像
		fin >> time_rgb >> rgb_file >> time_depth >> depth_file;
		color = cv::imread(path_to_dataset + "/" + rgb_file);
		depth = cv::imread(path_to_dataset + "/" + depth_file, -1);
		// 1. 对第一帧提取FAST特征点存到keypoints中
		if (index == 0)
		{
			vector<cv::KeyPoint> kps;
			cv::Ptr<cv::FastFeatureDetector> detector = cv::FastFeatureDetector::create();
			detector->detect(color, kps);
			for (auto kp : kps)
				keypoints.push_back(kp.pt);
			last_color = color;
			continue;
		}
		//实际只有10张图,后面10-99没有数据所以一直continue掉,index秒到99
		if (color.data == nullptr || depth.data == nullptr)
			continue;
		// 2. 对其他帧用LK跟踪特征点
		vector<cv::Point2f> next_keypoints;
		vector<cv::Point2f> prev_keypoints;
		for (auto kp : keypoints)
			prev_keypoints.push_back(kp);
		//调用calcOpticalFlowPyrLK函数
		//status匹配状态,匹配上赋1,否则赋0;
		vector<unsigned char> status;
		vector<float> error;
		cv::calcOpticalFlowPyrLK(last_color, color, prev_keypoints, next_keypoints, status, error);

		// 3. 更新keypoints列表,从prev_keypoints到next_keypoints
		int i = 0;
		for (auto iter = keypoints.begin(); iter != keypoints.end(); i++)
		{
			//跟丢了删除,iter保持当前位置,不会++,但i会++;
			//跟踪失败,next_keypoints中数据被跳过
			if (status[i] == 0)
			{
				iter = keypoints.erase(iter);
				continue;
			}
			//跟踪上的好点,才会让iter指向,
			*iter = next_keypoints[i];
			iter++;
		}
		cout << "tracked keypoints: " << keypoints.size() << endl;
		if (keypoints.size() == 0)
		{
			cout << "all keypoints are lost." << endl;
			break;
		}
		// 4. 画出 keypoints出为圆圈
		cv::Mat img_show = color.clone();
		for (auto kp : keypoints)
			cv::circle(img_show, kp, 10, cv::Scalar(0, 240, 0)
  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值