机器学习实践系列之6 - OpenCV实战光流

       光流(optical flow)是运动物体运动带来的像素变化,表示 像素空间的运动速度,直观也可以理解为 光的流动。一般而言,光流是由于场景中前景目标本身的移动、相机的运动,或者两者的共同运动所产生的。

       光流是通过 像素在时域上的变化来计算的,通过相邻帧之间的相关性来找到上一帧跟当前帧之间的对应关系。

       光流分为 稀疏光流稠密光流


• 稀疏光流

       所谓 稀疏光流,是指 金字塔Lucas-Kanade 方法(简称 LK 方法),算法分为两步:

1. 通过 goodFeaturesToTrack() 来寻找角点,也就是稀疏的概念;

2. 针对获得的两组Corner角点,通过 calcOpticalFlowPyrLK() 来 进行跟踪 Match。

    这一步是LK光流的关键,里面用到了复杂的多尺度特征(金字塔),此处不再展开,大家可以看OpenCV源码。

       相对于稠密光流, 稀疏光流 只需要对关键点进行计算,计算量较小,经常被用于 图像配准目标跟踪

       下图是 特征点检测 goodFeaturesToTrack 光流计算 calcOpticalFlowPyrLK 效果(代码会在最后给出):

        机器学习实践系列之6 - OpenCV实战光流_第1张图片

        机器学习实践系列之6 - OpenCV实战光流_第2张图片


• 稠密光流

       稠密光流 需要针对整副图计算像素偏移量(PS:确实够稠密的),可以对整幅图进行像素级别的配准,其效果要优于 稀疏光流,在某些要求比较高的场合下有应用,可以参考 Facebook 开源的 Surround360 VR全景相机。

       稠密光流 的缺点在于计算量较大(机器好,任性的朋友可以忽略)。

       OpenCV的 稠密光流 计算采用 Gunnar Farnebak算法,对应函数为calcOpticalFlowFarneback(),效果:

        机器学习实践系列之6 - OpenCV实战光流_第3张图片


       Ok,主要的两种光流法都讲过了,如果不需要深入研究的话(偏工程的童鞋就喜欢这个,哈哈:)),应该够了,看代码吧:

#include 
#include "opencv2/video/tracking.hpp"
#include "opencv2/highgui/highgui.hpp"

#pragma comment(lib,"opencv_core2410.lib")
#pragma comment(lib,"opencv_highgui2410.lib")
#pragma comment(lib,"opencv_video2410d.lib")
#pragma comment(lib,"opencv_imgproc2410.lib")
#pragma comment(lib,"opencv_features2d2410.lib")

#define MAX_CORNERS 1000

using namespace std;
using namespace cv;

int main(int argc, char* argv[])
{
	// 初始化载入图片
	vector imgs,grayImgs;

	Mat img = imread("11.jpg"); imgs.push_back(img);
	img = imread("22.jpg");     imgs.push_back(img);

	for(size_t i=0; i vecCorners[2];
	double qualityLevel = 0.01;//or 0.01  
	double minDistance = 10;
	goodFeaturesToTrack(grayImgs[0], vecCorners[0], MAX_CORNERS, qualityLevel, minDistance); 

	//// 角点显示测试
	//for(size_t i=0; i status;
	vector err;

	// 稀疏光流
	calcOpticalFlowPyrLK(imgs[0], imgs[1], vecCorners[0], vecCorners[1], status, err, cvSize(21,21),3, termcrit, 0, 0.001);
	for(size_t i=0; i(y, x);
			line(imgs[0], Point(x, y), Point(cvRound(x+fxy.x), cvRound(y+fxy.y)), CV_RGB(0,255,0));
			//circle(imgs[0], Point(x,y), 2, CV_RGB(255, 0, 0), -1);
		}
	}
	imshow("Farneback",imgs[0]);

	cvWaitKey(1);
	system("pause");
	return 0;
}

你可能感兴趣的:(机器学习,计算机视觉)