int main(int argc, char **argv)
{
if(argc != 4)
{
cerr << endl << "Usage: ./mono_kitti path_to_vocabulary path_to_settings path_to_sequence" << endl;
return 1;
}
// Retrieve paths to images
vector<string> vstrImageFilenames;
vector<double> vTimestamps;
//讲单目数据集图片(也就是Frames)load进来,argv[3]是Frame的路径
LoadImages(string(argv[3]), vstrImageFilenames, vTimestamps);
int nImages = vstrImageFilenames.size();
// Create SLAM system. It initializes all system threads and gets ready to process frames.
//argv[1]为vocfile 里边存储的是词汇
//argv[2]为settingfile 里边存储摄像机校准和畸变参数和ORB相关参数
//这里创建了System类型的SLAM对象,SLAM构造函数中初始化了系统所有线程和相关参数,代码留待后边详细分析
ORB_SLAM2::System SLAM(argv[1],argv[2],ORB_SLAM2::System::MONOCULAR,true);
// Vector for tracking time statistics
vector<float> vTimesTrack;
vTimesTrack.resize(nImages);
cout << endl << "-------" << endl;
cout << "Start processing sequence ..." << endl;
cout << "Images in the sequence: " << nImages << endl << endl;
cv::Mat im;
// Main loop 主循环代码,循环读取一帧一帧的图片
for(int ni=0; ni<nImages; ni++)
{
// Read image from file 读取图片
im = cv::imread(vstrImageFilenames[ni],CV_LOAD_IMAGE_UNCHANGED);
//读取时间戳
double tframe = vTimestamps[ni];
if(im.empty())
{
cerr << endl << "Failed to load image at: " << vstrImageFilenames[ni] << endl;
return 1;
}
#ifdef COMPILEDWITHC11
std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
#else
std::chrono::monotonic_clock::time_point t1 = std::chrono::monotonic_clock::now();
#endif
// Pass the image to the SLAM system
//将图片传给SLAM系统。TrackMonocular讲图片传给Tracking,其实Tracking就是系统的主线程。这里传入的im引起了系统的一系列操作
SLAM.TrackMonocular(im,tframe);
#ifdef COMPILEDWITHC11
std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
#else
std::chrono::monotonic_clock::time_point t2 = std::chrono::monotonic_clock::now();
#endif
double ttrack= std::chrono::duration_cast<std::chrono::duration<double> >(t2 - t1).count();
vTimesTrack[ni]=ttrack;
// Wait to load the next frame
double T=0;
if(ni<nImages-1)
T = vTimestamps[ni+1]-tframe;
else if(ni>0)
T = tframe-vTimestamps[ni-1];
if(ttrack<T)
usleep((T-ttrack)*1e6);
}
// Stop all threads 关闭SLAM系统,也就关闭了系统中的几个线程
SLAM.Shutdown();
// Tracking time statistics
sort(vTimesTrack.begin(),vTimesTrack.end());
float totaltime = 0;
for(int ni=0; ni<nImages; ni++)
{
totaltime+=vTimesTrack[ni];
}
cout << "-------" << endl << endl;
cout << "median tracking time: " << vTimesTrack[nImages/2] << endl;
cout << "mean tracking time: " << totaltime/nImages << endl;
// Save camera trajectory
// 整个SLAM系统运行完后,计算出来的是相机的运行轨迹,系统退出时保存相机轨迹
SLAM.SaveKeyFrameTrajectoryTUM("KeyFrameTrajectory.txt");
return 0;
}
/**
* 读入一帧帧的图像数据和时间戳数据
* strPathToSequence 为入参,表示image文件存储的路径
* vstrImageFilenames 为出参,存储获取image文件列表的具体路径
* vTimestamps 为出参, 存储和每一个image文件对应的时间戳
*
*/
void LoadImages(const string &strPathToSequence, vector<string> &vstrImageFilenames, vector<double> &vTimestamps)
{
ifstream fTimes;
string strPathTimeFile = strPathToSequence + "/times.txt";
fTimes.open(strPathTimeFile.c_str());
while(!fTimes.eof())
{
string s;
getline(fTimes,s);
if(!s.empty())
{
stringstream ss;
ss << s;
double t;
ss >> t;
//vTimestamps中存入了所有的时间戳
vTimestamps.push_back(t);
}
}
//组装mono_kitti数据集中image_0目录的路径
string strPrefixLeft = strPathToSequence + "/image_0/";
const int nTimes = vTimestamps.size();
vstrImageFilenames.resize(nTimes);
for(int i=0; i<nTimes; i++)
{
stringstream ss;
//std::setw :需要填充多少个字符,默认填充的字符为' '空格
//std::setfill:设置std::setw将填充什么样的字符,如:std::setfill('*')
//ss总共为6位,i之外的前边几位用0来填充,得到的结果为000001 000099之类
ss << setfill('0') << setw(6) << i;
vstrImageFilenames[i] = strPrefixLeft + ss.str() + ".png";
}
}
参考:https://blog.csdn.net/moyu123456789/article/details/90180635