Optical_Flow(5)

  
  
//Pyramid L-K Optical Flow example
//
#include <opencv\highgui.h>
#include <opencv\cv.h>
#include <stdio.h>


const int MAX_CORNERS = 500 ;
int main ( int argc , char ** argv ) {


IplImage * imgA = cvLoadImage ( "OpticalFlow0.jpg" , CV_LOAD_IMAGE_GRAYSCALE );
IplImage * imgB = cvLoadImage ( "OpticalFlow1.jpg" , CV_LOAD_IMAGE_GRAYSCALE );
CvSize img_sz = cvGetSize ( imgA );
int win_size = 10 ;
IplImage * imgC = cvLoadImage ( "OpticalFlow1.jpg" , CV_LOAD_IMAGE_UNCHANGED );


//The first thing we need to do is get the features we want to track
IplImage * eig_image = cvCreateImage ( img_sz , IPL_DEPTH_32F , 1 );
IplImage * tmp_image = cvCreateImage ( img_sz , IPL_DEPTH_32F , 1 );
int corner_count = MAX_CORNERS ;
CvPoint2D32f * cornersA = new CvPoint2D32f [ MAX_CORNERS ];
cvGoodFeaturesToTrack (
imgA ,
eig_image ,
tmp_image ,
cornersA ,
& corner_count ,
0.01 ,
5.0 ,
0 ,
3 ,
0 ,
0.04
);
cvFindCornerSubPix (
imgA ,
cornersA ,
corner_count ,
cvSize ( win_size , win_size ),
cvSize ( - 1 , - 1 ),
cvTermCriteria ( CV_TERMCRIT_ITER | CV_TERMCRIT_EPS , 20 , 0.03 )
);


char features_found [ MAX_CORNERS ];
float feature_errors [ MAX_CORNERS ];
CvSize pyr_sz = cvSize ( imgA -> width + 8 , imgB -> height / 3 );
IplImage * pyrA = cvCreateImage ( pyr_sz , IPL_DEPTH_32F , 1 );
IplImage * pyrB = cvCreateImage ( pyr_sz , IPL_DEPTH_32F , 1 );
CvPoint2D32f * cornersB = new CvPoint2D32f [ MAX_CORNERS ];
cvCalcOpticalFlowPyrLK ( //Call Lucate Kanade algorithm
imgA ,
imgB ,
pyrA ,
pyrB ,
cornersA ,
cornersB ,
corner_count ,
cvSize ( win_size , win_size ),
5 ,
features_found ,
feature_errors ,
cvTermCriteria ( CV_TERMCRIT_ITER | CV_TERMCRIT_EPS , 20 , .3 ),
0
);


for ( int i = 0 ; i < corner_count ; i ++ ) {
if ( features_found [ i ] == 0 || feature_errors [ i ] > 550 ) {
printf ( "Error is %f/n" , feature_errors [ i ]);
continue ;
}
printf ( "Got it/n" );
CvPoint p0 = cvPoint (
cvRound ( cornersA [ i ]. x ),
cvRound ( cornersA [ i ]. y )
);
CvPoint p1 = cvPoint (
cvRound ( cornersB [ i ]. x ),
cvRound ( cornersB [ i ]. y )
);
cvLine ( imgC , p0 , p1 , CV_RGB ( 255 , 0 , 0 ), 2 );
}
cvNamedWindow ( "ImageA" , 0 );
cvNamedWindow ( "ImageB" , 0 );
cvNamedWindow ( "LKpyr_OpticalFlow" , 0 );
cvShowImage ( "ImageA" , imgA );
cvShowImage ( "ImageB" , imgB );
cvShowImage ( "LKpyr_OpticalFlow" , imgC );
cvWaitKey ( 0 );
return 0 ;
}


代码中用到的几个函数

1)cvGoodFeaturesToTrack   确定图像的强角点

  1. void cvGoodFeaturesToTrack(  
  2. const CvArr* image //(8,1) or (32,1) (8-bit ,single-channel) (floating-point 32-bit,single-channel)  
  3. CvArr* eigImage,//(32,1)  
  4. CvArr* tempImage //(32,1)  
  5. CvPoint2D32f* corners  
  6. int* cornerCount  
  7. double qualityLevel  
  8. double minDistance  
  9. const CvArr* mask=NULL  
  10. int blockSize=3  
  11. int useHarris=0  
  12. double k=0.04 );  

参数解析:
image:输入图像,8-位或浮点32-比特,单通道
eig_image:临时浮点32-位图像,尺寸与输入图像一致
temp_image:另外一个临时图像,格式与尺寸与 eig_image 一致
corners:输出参数,检测到的角点
corner_count:输出参数,检测到的角点数目
quality_level:最大最小特征值的乘法因子。定义可接受图像角点的最小质量因子。
min_distance:限制因子。得到的角点的最小距离。使用 Euclidian 距离
mask:ROI:感兴趣区域。函数在ROI中计算角点,如果 mask 为 NULL,则选择整个图像
该函数 cvGoodFeaturesToTrack 在图像中寻找具有大特征值的角点。首先用cvCornerMinEigenVal 计算输入图像的每一个像素点的最小特征值,并将结果存储到变量 eig_image 中。然后进行非最大值抑制(仅保留3x3邻域中的局部最大值)。下一步将最小特征值小于 quality_level?max(eig_image(x,y)) 排除掉。最后,函数确保所有发现的角点之间具有足够的距离,(最强的角点第一个保留,然后检查新的角点与已有角点之间的距离大于 min_distance )。


2)cvFindCornerSubPix  用于发现亚像素精度的角点位置
void cvFindCornerSubPix(
const CvArr* image,
CvPoint2D32f* corners,
int count,
CvSize win,
CvSize zero_zone,
CvTermCriteria criteria
);
输入图像image是8位通道的灰度图像。corners为整数值的像素位置,corners设定了角点的初始位置。count为需要计算的角点数目。win指定了等式产生的窗口的尺寸。输入参数zero_zone定义了一个禁区(与win相似,但通常比win小),这个区域在方程组以及自相关矩阵中不被考虑。如果不需要这样一个禁区,则zero_zone应设置为cvSize(-1,-1)。最后一个参数为用户定义的迭代终止条件。迭代过程的终止条件可以是最大迭代次数CV_TERMCRIT_ITER类型,或者是设定的精度CV_TERMCRIT_EPS类型(或者是两者的组合)。终止条件的设置在极大程度上影响最终得到的亚像素值的精度。例如,指定0.10,则求得的亚像素级精度为像素的十分之一。


3)void cvCalcOpticalFlowPyrLK( const CvArr* prev, const CvArr* curr, CvArr* prev_pyr, CvArr* curr_pyr, 
const CvPoint2D32f* prev_features, CvPoint2D32f* curr_features, int count, CvSize win_size,
 int level, char* status, float* track_error, CvTermCriteria criteria, int flags ) 
prev  //在时间 t 的第一帧
curr  //在时间 t + dt 的第二帧
prev_pyr
//第一帧的金字塔缓存. 如果指针非 NULL , 则缓存必须有足够的空间来存储金字塔从层 1 到层 #level 的内容。尺寸 (image_width+8)*image_height/3 比特足够了
curr_pyr  //与 prev_pyr 类似, 用于第二帧
prev_features  //需要发现光流的点集
curr_features  //包含新计算出来的位置的 点集
count  //特征点的数目
win_size  //每个金字塔层的搜索窗口尺寸
level  //最大的金字塔层数。如果为 0 , 不使用金字塔 (即金字塔为单层), 如果为 1 , 使用两层,下面依次类推。
status  //数组。如果对应特征的光流被发现,数组中的每一个元素都被设置为 1, 否则设置为 0。
error  //双精度数组,包含原始图像碎片与移动点之间的差。为可选参数,可以是 NULL .
criteria  //准则,指定在每个金字塔层,为某点寻找光流的迭代过程的终止条件。
flags  //其它选项:
CV_LKFLOW_PYR_A_READY , 在调用之前,第一帧的金字塔已经准备好
CV_LKFLOW_PYR_B_READY , 在调用之前,第二帧的金字塔已经准备好
CV_LKFLOW_INITIAL_GUESSES , 在调用之前,数组 B 包含特征的初始坐标

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值