本科毕设就是利用开源DSO代码做的,运行了TUM单目数据集,EuRoC数据集,TUM-RGBD数据集。前段时间看了ORB-SLAM2的track线程,感觉ORB的代码比DSO的代码逻辑更清晰,可读性更强。虽然自己之前做毕设的时候梳理过DSO的代码流程,但是现在已经忘了好多,感觉还是有必要再重新梳理一遍。为了加深自己的理解,打算利用博客记录一下。
对于运行不同的数据集(主要区别是光度校准文件),DSO所需参数会不一样,在这里以运行TUM单目数据集为例。另外有个坑提醒一下:运行DSO时,数据集文件的路径下必须要有一个times.txt文件,里面的内容是图像名称,时间戳,曝光时间(可以没有),如果没有这个文件,那么DSO输出的位姿估计文件里面是空白的。
- 运行参数
for(int i=1; i<argc;i++)
parseArgument(argv[i]); //利用此函数读取参数
void parseArgument(char* arg) //参数设置
{
if(1==sscanf(arg,"files=%s",buf))
{
source = buf;
printf("loading data from %s!\n", source.c_str());
return;
}
if(1==sscanf(arg,"calib=%s",buf))
{
calib = buf;
printf("loading calibration from %s!\n", calib.c_str());
return;
}
if(1==sscanf(arg,"vignette=%s",buf))
{
vignette = buf;
printf("loading vignette from %s!\n", vignette.c_str());
return;
}
if(1==sscanf(arg,"gamma=%s",buf))
{
gammaCalib = buf;
printf("loading gammaCalib from %s!\n", gammaCalib.c_str());
return;
}
}
参数(只是一部分,其他感觉不重要) | 意义 |
---|---|
preset= | 是否强制实时执行 |
mode= | 是否进行光度校准 |
files= | 图像文件 ,source |
calib= | 相机内参 calib |
vignette= | 渐晕图 vignette |
gamma= | 响应函数校准 gammaCalib |
/文件读取
ImageFolderReader* reader = new ImageFolderReader(source,calib, gammaCalib, vignette);
ImageFolderReader(std::string path, std::string calibFile, std::string gammaFile, std::string vignetteFile)
{
this->path = path;
this->calibfile = calibFile;
#if HAS_ZIPLIB
ziparchive=0;
databuffer=0;
#endif
isZipped = (path.length()>4 && path.substr(path.length()-4) == ".zip");
if(isZipped) //解压图片文件
{
#if HAS_ZIPLIB
int ziperror=0;
ziparchive = zip_open(path.c_str(), ZIP_RDONLY, &ziperror);
if(ziperror!=0)
{
printf("ERROR %d reading archive %s!\n", ziperror, path.c_str());
exit(1);
}
files.clear();
int numEntries = zip_get_num_entries(ziparchive, 0); //图片数量
for(int k=0;k<numEntries;k++)
{
const char* name = zip_get_name(ziparchive, k, ZIP_FL_ENC_STRICT);
std::string nstr = std::string(name);
if(nstr == "." || nstr == "..") continue;
files.push_back(name);
}
printf("got %d entries and %d files!\n", numEntries, (int)files.size());
std::sort(files.begin(), files.end());
#else
printf("ERROR: cannot read .zip archive, as compile without ziplib!\n");
exit(1);
#endif
}
else
getdir (path, files);//如果没压缩,直接读取
undistort = Undistort::getUndistorterForFile(calibFile, gammaFile, vignetteFile); //读取去畸变文件,包括内参,伽玛,渐晕。
widthOrg = undistort->getOriginalSize()[0]; //内参文件第二行:原始图像大小
heightOrg = undistort->getOriginalSize()[1];
width=undistort->getSize()[0]; //内参文件第四行:输出图像大小
height=undistort->getSize()[1];
// load timestamps if possible.
loadTimestamps(); //加载时间戳,需要有times.txt文件
printf("ImageFolderReader: got %d files in %s!\n", (int)files.size(), path.c_str());
}
///图像帧处理
for(int ii=0;ii<(int)idsToPlay.size(); ii++)
{
if(preload)
img = preloadedImages[ii];
else
img = reader->getImage(i); //图像进行光度校准的入口
//图像帧处理入口
if(!skipFrame) fullSystem->addActiveFrame(img, i); //此处的img进行了G的映射,以及乘了渐晕因子
}
void FullSystem::addActiveFrame( ImageAndExposure* image, int id )
{
if(isLost) return;
boost::unique_lock<boost::mutex> lock(trackMutex);
// =========================== add into allFrameHistory =========================
FrameHessian* fh = new FrameHessian();
FrameShell* shell = new FrameShell();
shell->camToWorld = SE3(); // no lock required, as fh is not used anywhere yet.
shell->aff_g2l = AffLight(0,0);
shell->marginalizedAt = shell->id = allFrameHistory.size();
shell->timestamp = image->timestamp;
shell->incoming_id = id;
fh->shell = shell;
allFrameHistory.push_back(shell);
// =========================== make Images / derivatives etc. =========================
fh->ab_exposure = image->exposure_time;
fh->makeImages(image->image, &Hcalib);
if(!initialized)
{
// use initializer!
if(coarseInitializer->frameID<0) // first frame set. fh is kept by coarseInitializer.
{
coarseInitializer->setFirst(&Hcalib, fh);
}
else if(coarseInitializer->trackFrame(fh, outputWrapper)) // if SNAPPED
{
initializeFromInitializer(fh);
lock.unlock();
deliverTrackedFrame(fh, true);
}
else
{
// if still initializing
fh->shell->poseValid = false;
delete fh;
}
return;
}
else // do front-end operation.
{
// =========================== SWAP tracking reference?. =========================
if(coarseTracker_forNewKF->refFrameID > coarseTracker->refFrameID)
{
boost::unique_lock<boost::mutex> crlock(coarseTrackerSwapMutex);
CoarseTracker* tmp = coarseTracker; coarseTracker=coarseTracker_forNewKF; coarseTracker_forNewKF=tmp;
}
Vec4 tres = trackNewCoarse(fh);
if(!std::isfinite((double)tres[0]) || !std::isfinite((double)tres[1]) || !std::isfinite((double)tres[2]) || !std::isfinite((double)tres[3]))
{
printf("Initial Tracking failed: LOST!\n");
isLost=true;
return;
}
bool needToMakeKF = false;
if(setting_keyframesPerSecond > 0)
{
needToMakeKF = allFrameHistory.size()== 1 ||
(fh->shell->timestamp - allKeyFramesHistory.back()->timestamp) > 0.95f/setting_keyframesPerSecond;
}
else
{
Vec2 refToFh=AffLight::fromToVecExposure(coarseTracker->lastRef->ab_exposure, fh->ab_exposure,
coarseTracker->lastRef_aff_g2l, fh->shell->aff_g2l);
// BRIGHTNESS CHECK
needToMakeKF = allFrameHistory.size()== 1 ||
setting_kfGlobalWeight*setting_maxShiftWeightT * sqrtf((double)tres[1]) / (wG[0]+hG[0]) +
setting_kfGlobalWeight*setting_maxShiftWeightR * sqrtf((double)tres[2]) / (wG[0]+hG[0]) +
setting_kfGlobalWeight*setting_maxShiftWeightRT * sqrtf((double)tres[3]) / (wG[0]+hG[0]) +
setting_kfGlobalWeight*setting_maxAffineWeight * fabs(logf((float)refToFh[0])) > 1 ||
2*coarseTracker->firstCoarseRMSE < tres[0];
}
for(IOWrap::Output3DWrapper* ow : outputWrapper)
ow->publishCamPose(fh->shell, &Hcalib);
lock.unlock();
deliverTrackedFrame(fh, needToMakeKF);
return;
}
}