OpenCV21(金字塔LK光流演算法)
阿新 • • 發佈:2019-02-06
最好的教程,就是看Blog,然後最後一定要回歸書本。
一、LK演算法提到了三個假設
(高深:就是用你認識的字寫你看不懂的東西。辦法:多看幾遍,查閱Blog上接地氣的說法)
1.灰度不變
解釋一下:假設有一段博爾特跑過的視訊,相鄰兩幀上,博爾特的頭的灰度是不變的。
好像是廢話,其實不然。博爾特的頭,確切的來講,要說他頭上的某一畫素點。在不同幀間,座標是變化的。但是我們的假設提出來,首先我們認為這個點,在相鄰幀之間的對應點的灰度值是不變的。
2.時間連續
解釋一下:相鄰幀間,博爾特頭移動的很慢很慢很慢。
順便提一下書上的公式,最後結論v = It / Ix ;補充一下過程:
3.空間一致性
解釋一下:這一幀相鄰的兩個畫素,下一幀還相鄰。
二維的推導沒看明白,歡迎交流。
二、金字塔LK
在大多數情況下,以上的3個假設都是很難滿足的。物體運動的速度一般是很快速的,所以考慮到適用性,提出了金字塔LK。
什麼意思呢,應為金字塔是對圖形進行降取樣的(也就是影象越處理越小),所以一個大範圍的運動就可以在一個較小的範圍內檢測到了,滿足了以上3個條件。
大致就是這樣,有了感性認識,再好好看書吧。下面來看程式碼,最好執行一下。
三、程式碼
取自書上的原始碼。考慮到現在3.0的Mat的寫法越來越多,這個IplImage結構體,估計要被淘汰了。不過,還是先放上這個版本。(opencv249+vs2012)
// 光流.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include "cv.h" #include "cxcore.h" #include "highgui.h" const int MAX_CORNERS = 500; int _tmain(int argc, _TCHAR* argv[]) { IplImage* imgA = cvLoadImage("1.bmp",CV_LOAD_IMAGE_GRAYSCALE); IplImage* imgB = cvLoadImage("2.bmp",CV_LOAD_IMAGE_GRAYSCALE); CvSize img_sz = cvGetSize( imgA ); int win_size = 10; IplImage* imgC = cvCreateImage(cvGetSize(imgA),IPL_DEPTH_8U,3); cvZero(imgC); 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); cvFindCornerSubPix(imgA,cornersA,corner_count,cvSize(win_size,win_size),cvSize(-1,-1),cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03) ); char feature_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(imgA,imgB,pyrA,pyrB,cornersA,cornersB,corner_count,cvSize(win_size,win_size),5,feature_found,feature_errors, cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, .3),0); for(int i=0; i<corner_count; i++) { if( feature_found[i] == 0 || feature_errors[i]>550 ) { printf("Error is %f\n",feature_errors[i]); continue; } printf("Got it!\n"); CvPoint p1 = cvPoint(cvRound( cornersA[i].x),cvRound( cornersA[i].y)); CvPoint p2 = cvPoint(cvRound( cornersB[i].x),cvRound( cornersB[i].y)); cvLine(imgC,p1,p2,CV_RGB(255,255,255),1); } cvShowImage("1",imgA); cvShowImage("2",imgB); cvShowImage("3",imgC); cvWaitKey(0); return 0; }