目标检测光流法(二):opencv下的光流L-K算法
2015-10-07 21:24
459 查看
后续将简单介绍光流法的一些简单实现包,包括opencv下的光流算法与matlab下的光流算法。该节主要介绍opencv下的光流实现。
Opencv的光流实现由好几个方法可以(也就是说有好几个函数可以用),每个函数当然也对应着不同的原理,那么它的效果以及算法的速度等等就会有一些差别。主要包括以下几种:
calcOpticalFlowPyrLK
calcOpticalFlowFarneback
calcOpticalFlowBM
calcOpticalFlowHS
calcOpticalFlowSF
参见opencv文档介绍
这里先简单介绍下calcOpticalFlowPyrLK函数
calcOpticalFlowPyrLK函数使用形式:
calcOpticalFlowPyrLK(prevImg,nextImg,prevPts,nextPts,status,err)
这个函数还有一些可选参数,一大堆,详细的说明可以看opencv介绍:
这里只是贴出了主要的几个输入输出:
prevImg:就是你需要输入计算光流的前一帧图像
nextImg就是下一帧图像(可以看到一次光流就是在两针图像之间找不同)。
prevPts是前一帧图像中的特征点,这个特征点必须自己去找,所以在使用calcOpticalFlowPyrLK函数的时候,前面需要有一个找特征点的操作,那么一般就是找图像的角点,就是一个像素点与周围像素点都不同的那个点,这个角点特征点的寻找,opencv也提供夜歌函数:goodFeatureToTrack()(后面再介绍这个函数)。那么关于特征点有没有其他的方式呢?肯定是有的而且还很多吧。
nextPts参数就是计算特征点在第二幅图像中的新的位置,然后输出。特征点的新位置可能变化了,也可能没有变化,那么这种状态就存放在后一个参数status中。err就是新旧两个特征点位置的误差了,也是一个输出矩阵。
其他参数默认吧。
关于特征角点检测函数goodFeatureToTrack()
goodFeaturesToTrack(image,corners,maxCorners,qualityLevel,minDistance)
函数的参数:
image输入图像;
corners输出的特征点系列,每一个元素就是一个特征点的位置。
maxCorners规定的特征点最大数目,比如一副图像你可以找到很多特征点,但是只是取前maxCorners个具有最大特征的那些点作为最后的特征点,至于怎么判断哪些点的特征更好了,opencv自有一个机制,随便一个方法,比如计算一下这个点与周围一定领域的点的灰度相差求和,认为这个和越大的那些点是不是越属于特征点。
qualityLevel是一个特征点的取到水平,其实也是控制特征点的选取的,看结果适当选取吧。
minDistance是特征点与点之间的最小距离,一般我们如果想特征点尽量分散一些,太密集了肯定不好,那么我们可以通过这个参数。
比如说一个例子如下:
修改下 int maxCout = 100;//定义最大个数
double minDis = 10;//定义最小距离
下面通过这种特征点来以及L-K光流法来检测两幅相邻帧图像之间的移动点。首先自己准备两幅图吧,图中要有运动的目标才好,然后我们就这两幅图简单的看下里面的运动目标的特征点的运动吧,一个简单程序如下:
我的这两幅树叶图是存在这一些变化的,尤其树存在的地方,由于需要动态的来回切换着看才能看出变化,所以这里不太好显示这两幅图的变化,这里吧他们相差的图做出来如下:
可以看到的是越白的地方就是存在着不一致,也就是存在着明显运动的地方。和上面角点检测的还是有点符合的。
当然,我这可能只是连续两帧运动情况下的跟踪的特征点,如果是一个视频(连续的很多帧),那么把每两帧之间的运动点连接起来,就可以发现运动的物体的整个轨迹了。像网上博客有人做过的贴几个:
Opencv学习笔记(九)光流法
Opencv的光流实现由好几个方法可以(也就是说有好几个函数可以用),每个函数当然也对应着不同的原理,那么它的效果以及算法的速度等等就会有一些差别。主要包括以下几种:
calcOpticalFlowPyrLK
calcOpticalFlowFarneback
calcOpticalFlowBM
calcOpticalFlowHS
calcOpticalFlowSF
参见opencv文档介绍
这里先简单介绍下calcOpticalFlowPyrLK函数
calcOpticalFlowPyrLK函数使用形式:
calcOpticalFlowPyrLK(prevImg,nextImg,prevPts,nextPts,status,err)
这个函数还有一些可选参数,一大堆,详细的说明可以看opencv介绍:
这里只是贴出了主要的几个输入输出:
prevImg:就是你需要输入计算光流的前一帧图像
nextImg就是下一帧图像(可以看到一次光流就是在两针图像之间找不同)。
prevPts是前一帧图像中的特征点,这个特征点必须自己去找,所以在使用calcOpticalFlowPyrLK函数的时候,前面需要有一个找特征点的操作,那么一般就是找图像的角点,就是一个像素点与周围像素点都不同的那个点,这个角点特征点的寻找,opencv也提供夜歌函数:goodFeatureToTrack()(后面再介绍这个函数)。那么关于特征点有没有其他的方式呢?肯定是有的而且还很多吧。
nextPts参数就是计算特征点在第二幅图像中的新的位置,然后输出。特征点的新位置可能变化了,也可能没有变化,那么这种状态就存放在后一个参数status中。err就是新旧两个特征点位置的误差了,也是一个输出矩阵。
其他参数默认吧。
关于特征角点检测函数goodFeatureToTrack()
goodFeaturesToTrack(image,corners,maxCorners,qualityLevel,minDistance)
函数的参数:
image输入图像;
corners输出的特征点系列,每一个元素就是一个特征点的位置。
maxCorners规定的特征点最大数目,比如一副图像你可以找到很多特征点,但是只是取前maxCorners个具有最大特征的那些点作为最后的特征点,至于怎么判断哪些点的特征更好了,opencv自有一个机制,随便一个方法,比如计算一下这个点与周围一定领域的点的灰度相差求和,认为这个和越大的那些点是不是越属于特征点。
qualityLevel是一个特征点的取到水平,其实也是控制特征点的选取的,看结果适当选取吧。
minDistance是特征点与点之间的最小距离,一般我们如果想特征点尽量分散一些,太密集了肯定不好,那么我们可以通过这个参数。
比如说一个例子如下:
[code]#include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> using namespace std; using namespace cv; int main() { Mat I1; Mat I2; vector<Point2f> features; int maxCout = 50;//定义最大个数 double minDis = 20;//定义最小距离 double qLevel = 0.01;//定义质量水平 I1 = imread("I1.jpg",0);//读取为灰度图像 goodFeaturesToTrack(I1,features,maxCout,qLevel,minDis); for(int i=0;i<features.size();i++) { //将特征点画一个小圆出来--粗细为2 circle(I1,features[i],3,Scalar(255),2); } imshow("features",I1); waitKey(0); return 0; }
修改下 int maxCout = 100;//定义最大个数
double minDis = 10;//定义最小距离
下面通过这种特征点来以及L-K光流法来检测两幅相邻帧图像之间的移动点。首先自己准备两幅图吧,图中要有运动的目标才好,然后我们就这两幅图简单的看下里面的运动目标的特征点的运动吧,一个简单程序如下:
[code]#include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/video/video.hpp> #include <opencv2/core/core.hpp> #include <opencv2/imgproc/types_c.h> #include <iostream> #include <cstdio> using namespace std; using namespace cv; int main() { Mat I1; Mat I2; vector<Point2f> features; vector<Point2f> features_after; vector<uchar> status; vector<float> err; int maxCout = 300;//定义最大个数 double minDis = 10;//定义最小距离 double qLevel = 0.01;//定义质量水平 //读取两个图像---相邻帧 I1 = imread("I1.jpg",0);//读取为灰度图像 I2 = imread("I2.jpg",0); //检测第一帧的特征点 goodFeaturesToTrack(I1,features,maxCout,qLevel,minDis); //计算出第二帧的特征点 calcOpticalFlowPyrLK(I1,I2,features,features_after,status,err); //判别哪些属于运动的特征点 int k = 0; for(int i=0;i<features_after.size();i++) { //状态要是1,并且坐标要移动下的那些点 if(status[i]&&((abs(features[i].x-features_after[i].x)+ abs(features[i].y-features_after[i].y))>4)) { features_after[k++] = features_after[i]; } } features_after.resize(k);//截取 cout<<k<<endl; for(int i=0;i<features_after.size();i++) { //将特征点画一个小圆出来--粗细为2 circle(I1,features_after[i],3,Scalar(255),2); } imshow("features",I1); waitKey(0); return 0; }
我的这两幅树叶图是存在这一些变化的,尤其树存在的地方,由于需要动态的来回切换着看才能看出变化,所以这里不太好显示这两幅图的变化,这里吧他们相差的图做出来如下:
可以看到的是越白的地方就是存在着不一致,也就是存在着明显运动的地方。和上面角点检测的还是有点符合的。
当然,我这可能只是连续两帧运动情况下的跟踪的特征点,如果是一个视频(连续的很多帧),那么把每两帧之间的运动点连接起来,就可以发现运动的物体的整个轨迹了。像网上博客有人做过的贴几个:
Opencv学习笔记(九)光流法
相关文章推荐
- linux下mysql字符集配置
- shell常用命令
- centos6.6搭建tomcat
- UVA_679: Dropping Balls
- nginx与php的通信方式
- nginx防盗链配置与负载均衡
- 双目视觉学习总结(2)——立体标定
- 管道命令
- Linux下安装eclipse的C/C++集成开发环境
- nginx网站重定向,日志切割
- nginx实现用户认证访问页面
- apache2.2以后,每次升级系统,比如Yosemite 或者 EL Capitan版本 apache都要重新配置
- Core Data异常: model used to open the store is incompatible with the one used to create the store
- linux下mysql的root密码忘记解决方
- Redhat Linux下开启telnet服务
- Docker中apache-tomcat启动慢的问题
- 搭建Git Server - Centos+Gitosis
- 公司网站首页遇到的问题
- linux编程总结
- linux下查看和添加PATH环境变量