光流法学习

一、光流法的简介     

       当前移动摄像头下目标的检测是目标检测领域一个重要的热点,而光流法是进行移动摄像头下目标检测的一个重要工具。光流的概念是Gibson1950年首先提出来的。它是空间运动物体在观察成像平面上的像素运动的瞬时速度,是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系,从而计算出相邻帧之间物体的运动信息的一种方法。光流是由于场景中前景目标本身的移动、相机的运动,或者两者的共同运动所产生的。计算光流的方法有:

 (1)基于区域或者基于特征的匹配方法;

 (2)基于频域的方法;

 (3)基于梯度的方法;

    光流是空间运动物体在观测成像平面上的像素运动的“瞬间速度”。光流的研究是利用图像序列中的像素强度数据的时域变化和相关性来确定各自像素位置的“运动”,研究光流场的目的就是为了从图片序列中近似得到不能直接得到的运动场。

    光流法的假设前提:

   (1)亮度恒定:随着时间的变换,相邻帧间图像的亮度不发生变化;

   (2)相邻帧之间物体的运动比较“微小”:这样灰度才能对位置求导;

   (3)保持空间一致性;即,邻近的像素点具有相同的运动,速度一致;

    标注:运动场-物体在三维真实世界中的运动;  光流场-运动场在二维图像平面上的投影。

          

二、光流的计算:

    

三、光流法的程序:

   1、C++程序

#include "stdafx.h"
#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;

const int MAX_CORNERS = 500;
const double pi = 3.14159265358979323846;

int _tmain(int argc, _TCHAR* argv[])
{
	
	string imgname1 = "person1.jpg";
	string imgname2 = "person2.jpg";

	Mat img1,img2,img1_gray,img2_gray;
	img1 = imread(imgname1);
	img2 = imread(imgname2);

	cvtColor(img1,img1_gray,CV_RGB2GRAY);
	cvtColor(img2,img2_gray,CV_RGB2GRAY);

	namedWindow("Result",CV_WINDOW_AUTOSIZE);
	imshow("Result",img1_gray);
	//-------Shi-Tomasi角点算法参数定义
	int number_of_features = MAX_CORNERS;
	double qualityLevel = 0.01;
	double minDistance = 5.0;
	int blockSize = 3;
	bool useHarrisDetector = false;
	double k = 0.04; 

	vector<KeyPoint> keypoint1;
	GoodFeaturesToTrackDetector detector(number_of_features,qualityLevel,minDistance,blockSize,useHarrisDetector,k);
	detector.detect(img1_gray,keypoint1);
	
	Size optical_flow_window = Size(3,3);
	CvTermCriteria criteria = cvTermCriteria( CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03 );

	vector<Point2f> prePt,nextPt;
	for (int i=0; i<keypoint1.size(); i++)
	{
		prePt.push_back(keypoint1[i].pt);
	}


	//------金字塔Lucas-Kanande光流法
	Mat found_feature;
	Mat feature_error;
	calcOpticalFlowPyrLK(img1_gray,img2_gray,prePt,nextPt,found_feature,feature_error,Size(3,3),5,criteria,0,1e-4);
	
	for (int i=0; i<MAX_CORNERS; i++)
	{
		if (found_feature.at<bool>(i,0)==0)
			continue;
		int line_thickness;
		line_thickness = 0.5;
		CvScalar line_color; 
		line_color = CV_RGB(0,255,0);

		Point p,q;
		p.x = (int)prePt[i].x;
		p.y = (int)prePt[i].y;
		q.x = (int)nextPt[i].x;
		q.y = (int)nextPt[i].y;

		double angle;
		angle = atan2( (double)p.y - q.y, (double)p.x - q.x);
		double hypotenuse;
		hypotenuse = sqrt((double)(p.y - q.y)*(p.y - q.y) + (double)(p.x - q.x)*(p.x - q.x));

		q.x = (int)(p.x - 3 * hypotenuse * cos(angle));
		q.y = (int)(p.y - 3 * hypotenuse * sin(angle));

		line(img1, p, q, line_color, line_thickness, CV_AA,0);

		p.x = (int)(q.x + 9 * cos(angle + pi/4));
		p.y = (int)(q.y + 9 * sin(angle + pi/4));
		line(img1, p, q, line_color, line_thickness, CV_AA, 0);
		p.x = (int)(q.x + 9 * cos(angle - pi / 4));
	    p.y = (int)(q.y + 9 * sin(angle - pi / 4));
	    line(img1, p, q, line_color, line_thickness, CV_AA, 0);
	}

	namedWindow("光流图",CV_WINDOW_AUTOSIZE);
	imshow("光流图",img1);
    
	waitKey(0);
	return 0;
}


   

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值