光流法需要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);
因為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,不帶引號的。