39 #include <opencv2/imgproc/imgproc.hpp> 40 #include <opencv2/imgproc/types_c.h> 41 #if CV_MAJOR_VERSION >= 3 42 #include <opencv2/videoio/videoio_c.h> 49 #include <pcl/common/io.h> 64 _rectifyImages(
false),
67 _depthScaleFactor(1.0
f),
72 _scanLocalTransform(
Transform::getIdentity()),
74 _scanDownsampleStep(1),
77 _scanNormalsRadius(0),
78 _scanForceGroundNormalsUp(
false),
79 _depthFromScan(
false),
80 _depthFromScanFillHoles(1),
81 _depthFromScanFillHolesFromBorder(
false),
82 _filenamesAreTimestamps(
false),
83 _syncImageRateWithStamps(
true),
85 _groundTruthFormat(0),
86 _maxPoseTimeDiff(0.02),
92 Camera(imageRate, localTransform),
158 UWARN(
"Directory is empty \"%s\"",
_path.c_str());
179 if(!_scanDir->isValid())
185 else if(_scanDir->getFileNames().size() == 0)
193 UERROR(
"Scan and image directories should be the same size \"%s\"(%d) vs \"%s\"(%d)",
195 (int)_scanDir->getFileNames().size(),
208 UINFO(
"calibration folder=%s name=%s", calibrationFolder.c_str(), cameraName.c_str());
209 if(!calibrationFolder.empty() && !cameraName.empty())
211 if(!
_model.
load(calibrationFolder, cameraName))
213 UWARN(
"Missing calibration files for camera \"%s\" in \"%s\" folder, you should calibrate the camera!",
214 cameraName.c_str(), calibrationFolder.c_str());
218 UINFO(
"Camera parameters: fx=%f fy=%f cx=%f cy=%f",
230 UERROR(
"Parameter \"rectifyImages\" is set, but no camera model is loaded or valid.");
243 for(std::list<std::string>::const_iterator iter=filenames.begin(); iter!=filenames.end(); ++iter)
247 std::list<std::string> list =
uSplit(*iter,
'.');
248 if(list.size() == 3 || list.size() == 2)
254 std::list<std::string> numberList =
uSplitNumChar(list.front());
255 for(std::list<std::string>::iterator iter=numberList.begin(); iter!=numberList.end(); ++iter)
259 std::string decimals;
261 if(iter->length()>10)
263 decimals = iter->substr(10, iter->size()-10);
264 sec = iter->substr(0, 10);
288 UERROR(
"Conversion filename to timestamp failed! (filename=%s)", iter->c_str());
294 UERROR(
"The stamps count is not the same as the images (%d vs %d)! " 295 "Converting filenames to timestamps is activated.",
308 std::getline(file, str);
310 if(str.empty() || str.at(0) ==
'#' || str.at(0) ==
'%')
315 std::list<std::string> strList =
uSplit(str,
' ');
316 std::string stampStr = strList.front();
317 if(strList.size() == 2)
321 std::string millisecStr = strList.back();
322 while(millisecStr.size() < 6)
324 millisecStr =
"0" + millisecStr;
326 stampStr = stampStr+
'.'+millisecStr;
335 UERROR(
"The stamps count (%d) is not the same as the images (%d)! Please remove " 336 "the timestamps file path if you don't want to use them (current file path=%s).",
359 bool CameraImages::readPoses(std::list<Transform> & outputPoses, std::list<double> & inOutStamps,
const std::string & filePath,
int format,
double maxTimeDiff)
const 362 std::map<int, Transform> poses;
363 std::map<int, double> stamps;
366 UERROR(
"Cannot read pose file \"%s\".", filePath.c_str());
369 else if((format != 1 && format != 5 && format != 6 && format != 7 && format != 9) && poses.size() != this->
imagesCount())
371 UERROR(
"The pose count is not the same as the images (%d vs %d)! Please remove " 372 "the pose file path if you don't want to use it (current file path=%s).",
373 (
int)poses.size(), this->
imagesCount(), filePath.c_str());
376 else if((format == 1 || format == 5 || format == 6 || format == 7 || format == 9) && inOutStamps.size() == 0)
378 UERROR(
"When using RGBD-SLAM, GPS, MALAGA, ST LUCIA and EuRoC MAV formats, images must have timestamps!");
381 else if(format == 1 || format == 5 || format == 6 || format == 7 || format == 9)
386 std::map<double, int> stampsToIds;
387 for(std::map<int, double>::iterator iter=stamps.begin(); iter!=stamps.end(); ++iter)
389 stampsToIds.insert(std::make_pair(iter->second, iter->first));
391 std::vector<double> values =
uValues(stamps);
394 for(std::list<double>::iterator ster=inOutStamps.begin(); ster!=inOutStamps.end(); ++ster)
397 std::map<double, int>::iterator endIter = stampsToIds.lower_bound(*ster);
399 if(endIter != stampsToIds.end())
401 if(endIter->first == *ster)
403 pose = poses.at(endIter->second);
405 else if(endIter != stampsToIds.begin())
408 std::map<double, int>::iterator beginIter = endIter;
410 double stampBeg = beginIter->first;
411 double stampEnd = endIter->first;
412 UASSERT(stampEnd > stampBeg && *ster>stampBeg && *ster < stampEnd);
413 if(fabs(*ster-stampEnd) > maxTimeDiff || fabs(*ster-stampBeg) > maxTimeDiff)
417 UWARN(
"Cannot interpolate pose for stamp %f between %f and %f (> maximum time diff of %f sec)",
428 float t = (*ster - stampBeg) / (stampEnd-stampBeg);
429 Transform & ta = poses.at(beginIter->second);
430 Transform & tb = poses.at(endIter->second);
439 if(pose.
isNull() && !warned)
441 UDEBUG(
"Pose not found for stamp %f", *ster);
443 outputPoses.push_back(pose);
445 if(validPoses != (
int)inOutStamps.size())
447 UWARN(
"%d valid poses of %d stamps", validPoses, (
int)inOutStamps.size());
454 if(inOutStamps.size() == 0 && stamps.size() == poses.size())
458 else if(format==8 && inOutStamps.size() == 0 && stamps.size()>0 && stamps.size() != poses.size())
460 UERROR(
"With Karlsruhe format, timestamps (%d) and poses (%d) should match!", (
int)stamps.size(), (int)poses.size());
464 UASSERT_MSG(outputPoses.size() == inOutStamps.size(),
uFormat(
"%d vs %d", (
int)outputPoses.size(), (int)inOutStamps.size()).c_str());
493 return std::vector<std::string>();
505 else if(sleepTime < 0)
509 UWARN(
"CameraImages: Cannot read images as fast as their timestamps (target delay=%fs, capture time=%fs). Disable " 510 "source image rate or disable synchronization of capture time with timestamps.",
515 UWARN(
"CameraImages: Cannot read images as fast as their timestamps (target delay=%fs, capture time=%fs).",
534 cv::Mat depthFromScan;
546 std::string imageFilePath;
547 std::string scanFilePath;
562 if(scanFileNames.size())
594 std::string fileName;
596 if(!fileName.empty())
598 imageFilePath =
_path + fileName;
621 imageFilePath =
_path + fileName;
646 if(!fileName.empty())
657 if(!imageFilePath.empty())
661 #if CV_MAJOR_VERSION >2 || (CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4) 662 img = cv::imread(imageFilePath.c_str(), cv::IMREAD_UNCHANGED);
664 img = cv::imread(imageFilePath.c_str(), -1);
666 UDEBUG(
"width=%d, height=%d, channels=%d, elementSize=%d, total=%d",
667 img.cols, img.rows, img.channels(), img.elemSize(), img.total());
671 if(img.type() != CV_16UC1 && img.type() != CV_32FC1)
673 UERROR(
"Depth is on and the loaded image has not a format supported (file = \"%s\", type=%d). " 674 "Formats supported are 16 bits 1 channel (mm) and 32 bits 1 channel (m).",
675 imageFilePath.c_str(), img.type());
686 #if CV_MAJOR_VERSION < 3 688 if(img.depth() != CV_8U)
691 UWARN(
"Cannot read the image correctly, falling back to old OpenCV C interface...");
692 IplImage * i = cvLoadImage(imageFilePath.c_str());
693 img = cv::Mat(i,
true);
699 UWARN(
"Conversion from 4 channels to 3 channels (file=%s)", imageFilePath.c_str());
701 cv::cvtColor(img, out, CV_BGRA2BGR);
706 cv::Mat debayeredImg;
709 cv::cvtColor(img, debayeredImg, CV_BayerBG2BGR +
_bayerMode);
712 catch(
const cv::Exception &
e)
714 UWARN(
"Error debayering images: \"%s\". Please set bayer mode to -1 if images are not bayered!", e.what());
726 if(!scanFilePath.empty())
731 UDEBUG(
"Loaded scan=%d points", (
int)scan.
size());
734 UDEBUG(
"Computing depth from scan...");
737 UWARN(
"Depth from laser scan: Camera model should be valid.");
741 UWARN(
"Depth from laser scan: Loading already a depth image.");
759 UWARN(
"Directory is not set, camera must be initialized.");
770 if(info && !odometryPose.
isNull())
789 Camera(imageRate, localTransform),
792 _usbDevice(usbDevice)
798 const std::string & filePath,
802 Camera(imageRate, localTransform),
847 unsigned int guid = (
unsigned int)
_capture.get(CV_CAP_PROP_GUID);
848 if (guid != 0 && guid != 0xffffffff)
855 if(!calibrationFolder.empty() && !
_guid.empty())
859 UWARN(
"Missing calibration files for camera \"%s\" in \"%s\" folder, you should calibrate the camera!",
860 _guid.c_str(), calibrationFolder.c_str());
864 UINFO(
"Camera parameters: fx=%f fy=%f cx=%f cy=%f",
874 UERROR(
"Parameter \"rectifyImages\" is set, but no camera model is loaded or valid.");
915 UERROR(
"Camera has been disconnected!");
920 ULOGGER_WARN(
"The camera must be initialized before requesting an image.");
void setLocalTransform(const Transform &transform)
std::list< Transform > groundTruth_
Transform _scanLocalTransform
virtual SensorData captureImage(CameraInfo *info=0)
void setImageSize(const cv::Size &size)
std::string _groundTruthPath
cv::VideoCapture _capture
std::string _lastFileName
const cv::Mat & data() const
const std::string & name() const
double UTILITE_EXP uStr2Double(const std::string &str)
GLM_FUNC_DECL genType sec(genType const &angle)
const std::list< std::string > & getFileNames() const
const Transform & getLocalTransform() const
int uStrNumCmp(const std::string &a, const std::string &b)
virtual SensorData captureImage(CameraInfo *info=0)
GLM_FUNC_DECL genType e()
std::list< V > uValuesList(const std::multimap< K, V > &mm)
bool _scanForceGroundNormalsUp
unsigned int imagesCount() const
Some conversion functions.
virtual std::string getSerial() const
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_EXP laserScanToPointCloud(const LaserScan &laserScan, const Transform &transform=Transform())
std::list< std::string > uSplit(const std::string &str, char separator= ' ')
#define UASSERT(condition)
virtual bool isCalibrated() const
Wrappers of STL for convenient functions.
virtual bool isCalibrated() const
std::list< double > _stamps
bool load(const std::string &directory, const std::string &cameraName)
CameraVideo(int usbDevice=0, bool rectifyImages=false, float imageRate=0, const Transform &localTransform=Transform::getIdentity())
std::string _odometryPath
#define ULOGGER_DEBUG(...)
void setPath(const std::string &path, const std::string &extensions="")
#define UASSERT_MSG(condition, msg_str)
int _depthFromScanFillHoles
std::string _lastScanFileName
bool readPoses(std::list< Transform > &outputPoses, std::list< double > &stamps, const std::string &filePath, int format, double maxTimeDiff) const
bool isValidForRectification() const
Transform localTransform() const
std::list< std::string > uSplitNumChar(const std::string &str)
bool uIsNumber(const std::string &str)
std::vector< std::string > filenames() const
std::list< Transform > odometry_
bool _depthFromScanFillHolesFromBorder
cv::Mat rectifyImage(const cv::Mat &raw, int interpolation=cv::INTER_LINEAR) const
void uSleep(unsigned int ms)
std::vector< V > uListToVector(const std::list< V > &list)
bool isValidForProjection() const
float getImageRate() const
std::vector< V > uValues(const std::multimap< K, V > &mm)
bool _syncImageRateWithStamps
std::string getNextFileName()
std::string _timestampsPath
bool RTABMAP_EXP importPoses(const std::string &filePath, int format, std::map< int, Transform > &poses, std::multimap< int, Link > *constraints=0, std::map< int, double > *stamps=0)
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
virtual std::string getSerial() const
#define ULOGGER_WARN(...)
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
void RTABMAP_EXP fillProjectedCloudHoles(cv::Mat &depthRegistered, bool verticalDirection, bool fillToBorder)
cv::Mat RTABMAP_EXP projectCloudToCamera(const cv::Size &imageSize, const cv::Mat &cameraMatrixK, const cv::Mat &laserScan, const rtabmap::Transform &cameraTransform)
void setGroundTruth(const Transform &pose)
bool _filenamesAreTimestamps
LaserScan RTABMAP_EXP commonFiltering(const LaserScan &scan, int downsamplingStep, float rangeMin=0.0f, float rangeMax=0.0f, float voxelSize=0.0f, int normalK=0, float normalRadius=0.0f, bool forceGroundNormalsUp=false)
#define ULOGGER_ERROR(...)
LaserScan RTABMAP_EXP loadScan(const std::string &path)
std::string UTILITE_EXP uFormat(const char *fmt,...)
void setName(const std::string &name)
const Transform & localTransform() const