cvGoodFeaturesToTrack函数中count参数,虽然是输出参数,表示特征点的数目,但是这个初值设置至关重要。设置为0时,代码运行会错误。设置为1时,没有特征点输出,一般设置为最大特征点数目。(原因不明白)
cvGoodFeaturesToTrack,http://blog.csdn.net/moc062066/article/details/6634120,和
cvFindCornerSubPix,http://blog.csdn.net/moc062066/article/details/6634961
两个函数的基础,接下来就是在视频中检测光流(optical flow),经常用的函数是cvCalcOpticalFlowPyrLK,函数说明如下;
prev First frame, at time t //取t时刻为第一帧
curr Second frame, at time t + dt //第二帧出现在 t + dt时刻
prevPyr Buffer for the pyramid for the first frame. If the pointer is not NULL , the buffer must
have a sufficient size to store the pyramid from level 1 to level level ; the total size of
(image width+8)*image height/3 bytes is sufficient
//第一帧的图像金字塔的缓存之处。如果该指针不为空,该buffer必须有足够的空间来存储从第1层到第level 层的图像金字塔;prevPyr指针所指的图像/矩阵的大小为(image width+8)* (image height/3) 就足够了。
currPyr Similar to prevPyr, used for the second frame //同上
prevFeatures Array of points for which the flow needs to be found //在数组中定义(当前帧中的)那些点是要在(下一帧)检测的
currFeatures Array of 2D points containing the calculated new positions of the input features
in the second image
//一个二维的点数组,用于存放输入的特征(就是prevFeatures)在第二帧中的新位置
count Number of feature points//特征点的数目
winSize Size of the search window of each pyramid level //每一层金字塔所有的搜索窗口的大小
level Maximal pyramid level number. If 0 , pyramids are not used (single level), if 1 , two levels
are used, etc
//最多有多少层金字塔。如果是0,就不用图像金字塔,如果是1,就有两层,以此类推。
status Array. Every element of the array is set to 1 if the flow for the corresponding feature has
been found, 0 otherwise
//是一个数组,对应点在第二帧中找到,那该位置就值为1,找不到就值为0.
track error Array of double numbers containing the difference between patches around the
original and moved points. Optional parameter; can be NULL
criteria Specifies when the iteration process of finding the flow for each point on each pyramid
level should be stopped
flags Miscellaneous flags:
CV LKFLOWPyr A READY pyramid for the first frame is precalculated before the call
CV LKFLOWPyr B READY pyramid for the second frame is precalculated before the call
CV LKFLOW INITIAL GUESSES array B contains initial coordinates of features before the
function call
cvCalcOpticalFlowPyrLK函数中最后一个标志位,FLAG在视频处理中很重要。要提高速度,不重复计算金字塔,这里需要设置FLAG.即保存前一帧的金字塔数据和特征点,做为下一帧的初始帧。
下面一段代码为视频处理,设置FLAG
int CMotionOptic::OpticalFlow()
{
CvPoint2D32f *m_pPreConners1 = new CvPoint2D32f[MAX_CONNERS];
CvPoint2D32f *m_pCurConners1 = new CvPoint2D32f[MAX_CONNERS];
char aFeatureFound[MAX_CONNERS];
float aTrackErrors[MAX_CONNERS];
IplImage* m_pPyrCurImg1 = cvCreateImage(cvSize(m_iWidth,m_iHeight), IPL_DEPTH_32F,1);
IplImage *m_pPyrPreImg1 = cvCreateImage(cvSize(m_iWidth,m_iHeight), IPL_DEPTH_32F,1);
//int m_iConnersCnt1 = MAX_CONNERS;
if(1 == m_iStartFrameCnt)
{
cvGoodFeaturesToTrack(m_pPreImg,m_pEigImg,m_pTmpImg,m_pPreConners,&m_iConnersCnt,0.01,5.0,0,3,0,0.04);
cvFindCornerSubPix(m_pPreImg,m_pPreConners,m_iConnersCnt,cvSize(10,10),cvSize(-1,-1),
cvTermCriteria(CV_TERMCRIT_EPS|CV_TERMCRIT_ITER, 200,0.03));
cvCalcOpticalFlowPyrLK(m_pPreImg, m_pCurImg, m_pPyrPreImg, m_pPyrCurImg, m_pPreConners,
m_pCurConners,m_iConnersCnt,cvSize(10,10),5,aFeatureFound,aTrackErrors,
cvTermCriteria(CV_TERMCRIT_EPS|CV_TERMCRIT_ITER, 200, 0.03),0);
}
else
{
cvCalcOpticalFlowPyrLK(m_pPreImg, m_pCurImg, m_pPyrPreImg, m_pPyrCurImg, m_pPreConners,
m_pCurConners,m_iConnersCnt,cvSize(10,10),5,aFeatureFound,aTrackErrors,
cvTermCriteria(CV_TERMCRIT_EPS|CV_TERMCRIT_ITER, 200, 0.03),CV_LKFLOW_PYR_A_READY);
}
for(int iLoop = 0;iLoop < m_iConnersCnt; iLoop++)
{
if((0 == aFeatureFound[iLoop])||(aTrackErrors[iLoop] > 550))
{
printf("Error is %f",aTrackErrors[iLoop]);
continue;
}
CvPoint pt0 = cvPoint(cvRound(m_pPreConners[iLoop].x), cvRound(m_pPreConners[iLoop].y));
CvPoint pt1 = cvPoint(cvRound(m_pCurConners[iLoop].x), cvRound(m_pCurConners[iLoop].y));
if((abs(pt0.x - pt1.x) >= 1)||(abs(pt0.y - pt1.y) >= 1))
{
cvLine(m_pCurImg,pt0,pt1,cvScalar(255,0,0),2);
cvLine(m_pPreImg,pt0,pt1,cvScalar(255,0,0),2);
}
}
cvShowImage("PreOptica", m_pPreImg);
cvShowImage("CurOptica", m_pCurImg);
memcpy(m_pPyrPreImg->imageData, m_pPyrCurImg->imageData, (m_iWidth+8)*(m_iHeight/3)*4);
memcpy(m_pPreConners, m_pCurConners, m_iConnersCnt*sizeof(CvPoint2D32f));
return 0;
}