博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Lucas–Kanade 方法
阅读量:4149 次
发布时间:2019-05-25

本文共 5799 字,大约阅读时间需要 19 分钟。

光流跟踪源代码

// OpticalFlow1.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include "opencv2/opencv.hpp"#include 
#include
using namespace std;using namespace cv;class FrameProcessor;//帧处理基类class FrameProcessor{ public: virtual void process(Mat &input,Mat &ouput)=0;};//特征跟踪类,继承自帧处理基类class FeatureTracker : public FrameProcessor{ Mat gray; //当前灰度图 Mat gray_prev; //之前的灰度图 vector
points[2]; //前后两帧的特征点 vector
initial; //初始特征点 vector
features; //检测到的特征 int max_count; //要跟踪特征的最大数目 double qlevel; //特征检测的指标 double minDist; //特征点之间最小容忍距离 vector
status; //特征跟踪状态 vector
err; //跟踪时的错误public: FeatureTracker():max_count(500),qlevel(0.01),minDist(10.){} void process(Mat &frame,Mat &output){ //得到灰度图 cvtColor (frame,gray,CV_BGR2GRAY); frame.copyTo (output); //特征点太少了,重新检测特征点 if(addNewPoint()){ detectFeaturePoint (); //插入检测到的特征点 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); } //根据前后两帧灰度图估计前一帧特征点在当前帧的位置 //默认窗口是15*15 calcOpticalFlowPyrLK ( gray_prev,//前一帧灰度图 gray,//当前帧灰度图 points[0],//前一帧特征点位置 points[1],//当前帧特征点位置 status,//特征点被成功跟踪的标志 err);//前一帧特征点点小区域和当前特征点小区域间的差,根据差的大小可删除那些运动变化剧烈的点 int k = 0; //去除那些未移动的特征点 for(int i=0;i
2); } //画特征点 void handleTrackedPoint(Mat &frame,Mat &output){ for(int i=0;i
images; //迭代器public: VideoProcessor() : callIt(true),delay(0),fnumber(0),stop(false),digits(0),frameToStop(-1){} //设置图像处理函数 void setFrameProcessor(void (*process)(Mat &,Mat &)){ frameprocessor = 0; this->process = process; CallProcess (); } //打开视频 bool setInput(string filename){ fnumber = 0; //若已打开,释放重新打开 caputure.release (); return caputure.open (filename); } //设置输入视频播放窗口 void displayInput(string wn){ WindowNameInput = wn; namedWindow (WindowNameInput); } //设置输出视频播放窗口 void displayOutput(string wn){ WindowNameOutput = wn; namedWindow (WindowNameOutput); } //销毁窗口 void dontDisplay(){ destroyWindow (WindowNameInput); destroyWindow (WindowNameOutput); WindowNameInput.clear (); WindowNameOutput.clear (); } //启动 void run(){ Mat frame; Mat output; if(!isOpened()) return; stop = false; while(!isStopped()){ //读取下一帧 if(!readNextFrame(frame)) break; if(WindowNameInput.length ()!=0) imshow (WindowNameInput,frame); //处理该帧 if(callIt){ if(process) process(frame,output); else if(frameprocessor) frameprocessor->process (frame,output); } else{ output = frame; } if(Outputfile.length ()){ cvtColor (output,output,CV_GRAY2BGR); writeNextFrame (output); } if(WindowNameOutput.length ()!=0) imshow (WindowNameOutput,output); //按键暂停,继续按键继续 if(delay>=0&&waitKey (delay)>=0) waitKey(0); //到达指定暂停键,退出 if(frameToStop>=0&&getFrameNumber()==frameToStop) stopIt(); } } //暂停键置位 void stopIt(){ stop = true; } //查询暂停标志位 bool isStopped(){ return stop; } //返回视频打开标志 bool isOpened(){ return caputure.isOpened ()||!images.empty (); } //设置延时 void setDelay(int d){ delay = d; } //读取下一帧 bool readNextFrame(Mat &frame){ if(images.size ()==0) return caputure.read (frame); else{ if(itImg!=images.end()){ frame = imread (*itImg); itImg++; return frame.data?1:0; } else return false; } } void CallProcess(){ callIt = true; } void dontCallProcess(){ callIt = false; } //设置停止帧 void stopAtFrameNo(long frame){ frameToStop = frame; } // 获得当前帧的位置 long getFrameNumber(){ long fnumber = static_cast
(caputure.get ((CV_CAP_PROP_POS_FRAMES))); return fnumber; } //获得帧大小 Size getFrameSize() { if (images.size()==0) { // 从视频流获得帧大小 int w= static_cast
(caputure.get(CV_CAP_PROP_FRAME_WIDTH)); int h= static_cast
(caputure.get(CV_CAP_PROP_FRAME_HEIGHT)); return Size(w,h); } else { //从图像获得帧大小 cv::Mat tmp= cv::imread(images[0]); return (tmp.data)?(tmp.size()):(Size(0,0)); } } //获取帧率 double getFrameRate(){ return caputure.get(CV_CAP_PROP_FPS); } vector
::const_iterator itImg; bool setInput (const vector
&imgs){ fnumber = 0; caputure.release (); images = imgs; itImg = images.begin (); return true; } void setFrameProcessor(FrameProcessor *frameprocessor){ process = 0; this->frameprocessor = frameprocessor; CallProcess (); } //获得编码类型 int getCodec(char codec[4]) { if (images.size()!=0) return -1; union { // 数据结构4-char int value; char code[4]; } returned; //获得编码值 returned.value= static_cast
( caputure.get(CV_CAP_PROP_FOURCC)); // get the 4 characters codec[0]= returned.code[0]; codec[1]= returned.code[1]; codec[2]= returned.code[2]; codec[3]= returned.code[3]; return returned.value; } bool setOutput(const string &filename,int codec = 0,double framerate = 0.0,bool isColor = true){ //设置文件名 Outputfile = filename; //清空扩展名 extension.clear (); //设置帧率 if(framerate ==0.0){ framerate = getFrameRate (); } //获取输入原视频的编码方式 char c[4]; if(codec==0){ codec = getCodec(c); } return writer.open(Outputfile, codec, framerate, getFrameSize(), isColor); } //输出视频帧到图片fileme+currentIndex.ext,如filename001.jpg bool setOutput (const string &filename,//路径 const string &ext,//扩展名 int numberOfDigits=3,//数字位数 int startIndex=0 ){//起始索引 if(numberOfDigits<0) return false; Outputfile = filename; extension = ext; digits = numberOfDigits; currentIndex = startIndex; return true; } //写下一帧 void writeNextFrame(Mat &frame){ //如果扩展名不为空,写到图片文件中 if(extension.length ()){ stringstream ss; ss<
<
<
<
<

参考:

1.http://blog.sina.com.cn/s/blog_50363a7901011215.html

2.http://blog.csdn.net/hitwengqi

3.http://blog.csdn.net/zht9961020/article/details/7045528

4.http://wsyjwps1983.blog.163.com/blog/static/680090012010820105422557/

5.http://www.pudn.com/downloads370/sourcecode/graph/detail1603390.html

6.http://blog.csdn.net/moc062066/article/details/6636106

7.http://baike.baidu.com/link?url=dZimvYcgXb-agU8v0Mo8LBHlJHojPd_eRs7ErmDBDEPGWfaUe60dXcY1_cHW9s2Tx-4NcygnhOqcxk6bhDv6aq

你可能感兴趣的文章
LeetCode 219:Contains Duplicate II
查看>>
LeetCode 144: Binary Tree Preorder Traversal
查看>>
LeetCode 94:Binary Tree Inorder Traversal(中序遍历)
查看>>
LeetCode 106:Construct Binary Tree from Postorder and Inorder Traversal
查看>>
LeetCode 137:Single Number II
查看>>
LeetCode 8:String to Integer (atoi)
查看>>
LeetCode 03: Longest Substring Without Repeating Characters
查看>>
LeetCode 4: Median of Two Sorted Arrays
查看>>
LeetCode 7: Reverse Integer
查看>>
LeetCode 9: Palindrome Number
查看>>
LeetCode 10: Regular Expression Matching
查看>>
LeetCode 56:Merge Intervals
查看>>
LeetCode 18: 4Sum
查看>>
LeetCode 19: Remove Nth Node From End of List
查看>>
LeetCode 20: Valid Parentheses
查看>>
LeetCode 27:Remove Element
查看>>
LeetCode 28:Implement strStr()
查看>>
LeetCode 44:Wildcard Matching
查看>>
LeetCode 83:Remove Duplicates from Sorted List
查看>>
LeetCode 86 Partition List
查看>>