光流法須要include<opencv2/video/tracking.hpp>,用到列表,因此要include<list><vector>
1.讀取文件
定義圖像存儲路徑用string
string path_dataset=argv[1];
associate文件地址
string associate_file=path_dataset+"/associate.txt";
讀取associate_file.
ifstream fin(associate_file);ide
由於associate文件的每一行分別是time_color,color,time_depth,depth.因此定義這4個路徑,方便以後讀取深度圖和彩色圖。
string rgb_file,depth_file,time_rgb,time_depth,
弄個for循環。而後把fin的每一行分別賦值。
for(int index=0;index<100;index++)
fin>>time_rgb>>rgb_file>>time_depth>>depth_file;
有路徑了,就讀取吧。深度圖讀的時候要加-1.
color=cv::read(path_dataset+"/"+rgb_file);
depth=cv::read(path_dataset+"/"+depth_file,-1);
只對第一個圖像提取特徵。而後對第一幅圖像提取的特徵進行追蹤。
if(index==0)
執行
vector<cv::KeyPoint> kps;
cv::Ptr<cv::FastFeatureDetector> detector=cv::FastFeatureDector::create();
detector->detect(color,kps)
因爲這裏提取的kps是cv::KeyPoint形式,須要把每個特徵點都變成Point2f形式。因此
for(auto kp:kps)
keypoints.push_back(kp.pt);
這裏的keypoints的類型爲list<cv::Point2f>,方便以後刪除。
取完特徵點以後last_color=color;
中間若是color.data或者depth.date有一個爲空指針,直接從頭開始執行。
2.追蹤特徵點
定義兩個特徵點形式,一個是next_keypoints,一個是prev_keypoints.一個表示以後的,一個表示先前的。都是vector<cv::Point2f>形式。
先前的特徵點表示的是從以前循環獲得的特徵點。第一次就是提取到的全部特徵點。
定義status和errot.類型分別爲vector<unsiged char> 和vector<float>
把last_color,color,prev_keypoints,next_keypoints,status,error依次放到函數cv::calcOpticalFlowPyrLK函數中,能夠返回next_keypoints,status,error.
若是index==1,的話,這裏,last_color=color,也就是說兩個是相等的。
3.把跟丟的點刪掉
int i=0.
for(auto iter=keypoints.begin();iter!=keypoints.endl;i++)
若是status對應的第i個值是0,應該說明這個特徵點跟丟了。那麼iter=keypoints.erase(iter);
erase是擦除函數。
keypoints這裏是個列表,因此begin是它的第一個元素。
若是第1個元素爲0,那麼iter原來是keypoints的第一個元素,Iter等於keypoints擦除iter這個元素以後的列表。而後跳到for循環,而後iter爲第1個元素,可是由於keypoints的第一元素被擦除了,因此第一個元素已經換了,若是status[2]!=0,指針iter爲next_keypoints[i]的第i個元素。iter+1.因此i是一直加的。
這裏擦除以後,能夠獲得下個圖還剩多少特徵點。
添加了cv::waitKey(0),這個的意思是每次循環後暫停,按任意鍵繼續。
3.畫圖
cv::Mat img_show=color.clone();
畫的圖片也是一個矩陣。
要把每個特徵點都用cv::circle表示一下。
for(auto kp:keypoints)
cv::circle(img_show,kp,10,cv::Scalar(0,240,0),1)
展現用cv::imshow就能夠了。
而後last_color=color.
cv後面的函數都是第一個字母小寫,換字符大寫。
例如cv::calcOptical..,cv::waitKey(0)
fin直接associate_file,不帶引號的。函數