123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- /**
- * This file is part of ORB-SLAM3
- *
- * Copyright (C) 2017-2021 Carlos Campos, Richard Elvira, Juan J. Gómez Rodríguez, José M.M. Montiel and Juan D. Tardós, University of Zaragoza.
- * Copyright (C) 2014-2016 Raúl Mur-Artal, José M.M. Montiel and Juan D. Tardós, University of Zaragoza.
- *
- * ORB-SLAM3 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * ORB-SLAM3 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with ORB-SLAM3.
- * If not, see <http://www.gnu.org/licenses/>.
- */
- #include "FrameDrawer.h"
- #include "Tracking.h"
- #include <opencv2/core/core.hpp>
- #include <opencv2/highgui/highgui.hpp>
- #include<mutex>
- namespace ORB_SLAM3
- {
- FrameDrawer::FrameDrawer(Atlas* pAtlas):both(false),mpAtlas(pAtlas)
- {
- mState=Tracking::SYSTEM_NOT_READY;
- mIm = cv::Mat(480,640,CV_8UC3, cv::Scalar(0,0,0));
- mImRight = cv::Mat(480,640,CV_8UC3, cv::Scalar(0,0,0));
- }
- cv::Mat FrameDrawer::DrawFrame(float imageScale)
- {
- cv::Mat im;
- vector<cv::KeyPoint> vIniKeys; // Initialization: KeyPoints in reference frame
- vector<int> vMatches; // Initialization: correspondeces with reference keypoints
- vector<cv::KeyPoint> vCurrentKeys; // KeyPoints in current frame
- vector<bool> vbVO, vbMap; // Tracked MapPoints in current frame
- vector<pair<cv::Point2f, cv::Point2f> > vTracks;
- int state; // Tracking state
- vector<float> vCurrentDepth;
- float thDepth;
- Frame currentFrame;
- vector<MapPoint*> vpLocalMap;
- vector<cv::KeyPoint> vMatchesKeys;
- vector<MapPoint*> vpMatchedMPs;
- vector<cv::KeyPoint> vOutlierKeys;
- vector<MapPoint*> vpOutlierMPs;
- map<long unsigned int, cv::Point2f> mProjectPoints;
- map<long unsigned int, cv::Point2f> mMatchedInImage;
- cv::Scalar standardColor(0,255,0);
- cv::Scalar odometryColor(255,0,0);
- //Copy variables within scoped mutex
- {
- unique_lock<mutex> lock(mMutex);
- state=mState;
- if(mState==Tracking::SYSTEM_NOT_READY)
- mState=Tracking::NO_IMAGES_YET;
- mIm.copyTo(im);
- if(mState==Tracking::NOT_INITIALIZED)
- {
- vCurrentKeys = mvCurrentKeys;
- vIniKeys = mvIniKeys;
- vMatches = mvIniMatches;
- vTracks = mvTracks;
- }
- else if(mState==Tracking::OK)
- {
- vCurrentKeys = mvCurrentKeys;
- vbVO = mvbVO;
- vbMap = mvbMap;
- currentFrame = mCurrentFrame;
- vpLocalMap = mvpLocalMap;
- vMatchesKeys = mvMatchedKeys;
- vpMatchedMPs = mvpMatchedMPs;
- vOutlierKeys = mvOutlierKeys;
- vpOutlierMPs = mvpOutlierMPs;
- mProjectPoints = mmProjectPoints;
- mMatchedInImage = mmMatchedInImage;
- vCurrentDepth = mvCurrentDepth;
- thDepth = mThDepth;
- }
- else if(mState==Tracking::LOST)
- {
- vCurrentKeys = mvCurrentKeys;
- }
- }
- if(imageScale != 1.f)
- {
- int imWidth = im.cols / imageScale;
- int imHeight = im.rows / imageScale;
- cv::resize(im, im, cv::Size(imWidth, imHeight));
- }
- if(im.channels()<3) //this should be always true
- cvtColor(im,im,cv::COLOR_GRAY2BGR);
- //Draw
- if(state==Tracking::NOT_INITIALIZED)
- {
- for(unsigned int i=0; i<vMatches.size(); i++)
- {
- if(vMatches[i]>=0)
- {
- cv::Point2f pt1,pt2;
- if(imageScale != 1.f)
- {
- pt1 = vIniKeys[i].pt / imageScale;
- pt2 = vCurrentKeys[vMatches[i]].pt / imageScale;
- }
- else
- {
- pt1 = vIniKeys[i].pt;
- pt2 = vCurrentKeys[vMatches[i]].pt;
- }
- cv::line(im,pt1,pt2,standardColor);
- }
- }
- for(vector<pair<cv::Point2f, cv::Point2f> >::iterator it=vTracks.begin(); it!=vTracks.end(); it++)
- {
- cv::Point2f pt1,pt2;
- if(imageScale != 1.f)
- {
- pt1 = (*it).first / imageScale;
- pt2 = (*it).second / imageScale;
- }
- else
- {
- pt1 = (*it).first;
- pt2 = (*it).second;
- }
- cv::line(im,pt1,pt2, standardColor,5);
- }
- }
- else if(state==Tracking::OK) //TRACKING
- {
- mnTracked=0;
- mnTrackedVO=0;
- const float r = 5;
- int n = vCurrentKeys.size();
- for(int i=0;i<n;i++)
- {
- if(vbVO[i] || vbMap[i])
- {
- cv::Point2f pt1,pt2;
- cv::Point2f point;
- if(imageScale != 1.f)
- {
- point = vCurrentKeys[i].pt / imageScale;
- float px = vCurrentKeys[i].pt.x / imageScale;
- float py = vCurrentKeys[i].pt.y / imageScale;
- pt1.x=px-r;
- pt1.y=py-r;
- pt2.x=px+r;
- pt2.y=py+r;
- }
- else
- {
- point = vCurrentKeys[i].pt;
- pt1.x=vCurrentKeys[i].pt.x-r;
- pt1.y=vCurrentKeys[i].pt.y-r;
- pt2.x=vCurrentKeys[i].pt.x+r;
- pt2.y=vCurrentKeys[i].pt.y+r;
- }
- // This is a match to a MapPoint in the map
- if(vbMap[i])
- {
- cv::rectangle(im,pt1,pt2,standardColor);
- cv::circle(im,point,2,standardColor,-1);
- mnTracked++;
- }
- else // This is match to a "visual odometry" MapPoint created in the last frame
- {
- cv::rectangle(im,pt1,pt2,odometryColor);
- cv::circle(im,point,2,odometryColor,-1);
- mnTrackedVO++;
- }
- }
- }
- }
- cv::Mat imWithInfo;
- DrawTextInfo(im,state, imWithInfo);
- return imWithInfo;
- }
- cv::Mat FrameDrawer::DrawRightFrame(float imageScale)
- {
- cv::Mat im;
- vector<cv::KeyPoint> vIniKeys; // Initialization: KeyPoints in reference frame
- vector<int> vMatches; // Initialization: correspondeces with reference keypoints
- vector<cv::KeyPoint> vCurrentKeys; // KeyPoints in current frame
- vector<bool> vbVO, vbMap; // Tracked MapPoints in current frame
- int state; // Tracking state
- //Copy variables within scoped mutex
- {
- unique_lock<mutex> lock(mMutex);
- state=mState;
- if(mState==Tracking::SYSTEM_NOT_READY)
- mState=Tracking::NO_IMAGES_YET;
- mImRight.copyTo(im);
- if(mState==Tracking::NOT_INITIALIZED)
- {
- vCurrentKeys = mvCurrentKeysRight;
- vIniKeys = mvIniKeys;
- vMatches = mvIniMatches;
- }
- else if(mState==Tracking::OK)
- {
- vCurrentKeys = mvCurrentKeysRight;
- vbVO = mvbVO;
- vbMap = mvbMap;
- }
- else if(mState==Tracking::LOST)
- {
- vCurrentKeys = mvCurrentKeysRight;
- }
- } // destroy scoped mutex -> release mutex
- if(imageScale != 1.f)
- {
- int imWidth = im.cols / imageScale;
- int imHeight = im.rows / imageScale;
- cv::resize(im, im, cv::Size(imWidth, imHeight));
- }
- if(im.channels()<3) //this should be always true
- cvtColor(im,im,cv::COLOR_GRAY2BGR);
- //Draw
- if(state==Tracking::NOT_INITIALIZED) //INITIALIZING
- {
- for(unsigned int i=0; i<vMatches.size(); i++)
- {
- if(vMatches[i]>=0)
- {
- cv::Point2f pt1,pt2;
- if(imageScale != 1.f)
- {
- pt1 = vIniKeys[i].pt / imageScale;
- pt2 = vCurrentKeys[vMatches[i]].pt / imageScale;
- }
- else
- {
- pt1 = vIniKeys[i].pt;
- pt2 = vCurrentKeys[vMatches[i]].pt;
- }
- cv::line(im,pt1,pt2,cv::Scalar(0,255,0));
- }
- }
- }
- else if(state==Tracking::OK) //TRACKING
- {
- mnTracked=0;
- mnTrackedVO=0;
- const float r = 5;
- const int n = mvCurrentKeysRight.size();
- const int Nleft = mvCurrentKeys.size();
- for(int i=0;i<n;i++)
- {
- if(vbVO[i + Nleft] || vbMap[i + Nleft])
- {
- cv::Point2f pt1,pt2;
- cv::Point2f point;
- if(imageScale != 1.f)
- {
- point = mvCurrentKeysRight[i].pt / imageScale;
- float px = mvCurrentKeysRight[i].pt.x / imageScale;
- float py = mvCurrentKeysRight[i].pt.y / imageScale;
- pt1.x=px-r;
- pt1.y=py-r;
- pt2.x=px+r;
- pt2.y=py+r;
- }
- else
- {
- point = mvCurrentKeysRight[i].pt;
- pt1.x=mvCurrentKeysRight[i].pt.x-r;
- pt1.y=mvCurrentKeysRight[i].pt.y-r;
- pt2.x=mvCurrentKeysRight[i].pt.x+r;
- pt2.y=mvCurrentKeysRight[i].pt.y+r;
- }
- // This is a match to a MapPoint in the map
- if(vbMap[i + Nleft])
- {
- cv::rectangle(im,pt1,pt2,cv::Scalar(0,255,0));
- cv::circle(im,point,2,cv::Scalar(0,255,0),-1);
- mnTracked++;
- }
- else // This is match to a "visual odometry" MapPoint created in the last frame
- {
- cv::rectangle(im,pt1,pt2,cv::Scalar(255,0,0));
- cv::circle(im,point,2,cv::Scalar(255,0,0),-1);
- mnTrackedVO++;
- }
- }
- }
- }
- cv::Mat imWithInfo;
- DrawTextInfo(im,state, imWithInfo);
- return imWithInfo;
- }
- void FrameDrawer::DrawTextInfo(cv::Mat &im, int nState, cv::Mat &imText)
- {
- stringstream s;
- if(nState==Tracking::NO_IMAGES_YET)
- s << " WAITING FOR IMAGES";
- else if(nState==Tracking::NOT_INITIALIZED)
- s << " TRYING TO INITIALIZE ";
- else if(nState==Tracking::OK)
- {
- if(!mbOnlyTracking)
- s << "SLAM MODE | ";
- else
- s << "LOCALIZATION | ";
- int nMaps = mpAtlas->CountMaps();
- int nKFs = mpAtlas->KeyFramesInMap();
- int nMPs = mpAtlas->MapPointsInMap();
- s << "Maps: " << nMaps << ", KFs: " << nKFs << ", MPs: " << nMPs << ", Matches: " << mnTracked;
- if(mnTrackedVO>0)
- s << ", + VO matches: " << mnTrackedVO;
- }
- else if(nState==Tracking::LOST)
- {
- s << " TRACK LOST. TRYING TO RELOCALIZE ";
- }
- else if(nState==Tracking::SYSTEM_NOT_READY)
- {
- s << " LOADING ORB VOCABULARY. PLEASE WAIT...";
- }
- int baseline=0;
- cv::Size textSize = cv::getTextSize(s.str(),cv::FONT_HERSHEY_PLAIN,1,1,&baseline);
- imText = cv::Mat(im.rows+textSize.height+10,im.cols,im.type());
- im.copyTo(imText.rowRange(0,im.rows).colRange(0,im.cols));
- imText.rowRange(im.rows,imText.rows) = cv::Mat::zeros(textSize.height+10,im.cols,im.type());
- cv::putText(imText,s.str(),cv::Point(5,imText.rows-5),cv::FONT_HERSHEY_PLAIN,1,cv::Scalar(255,255,255),1,8);
- }
- void FrameDrawer::Update(Tracking *pTracker)
- {
- unique_lock<mutex> lock(mMutex);
- pTracker->mImGray.copyTo(mIm);
- mvCurrentKeys=pTracker->mCurrentFrame.mvKeys;
- mThDepth = pTracker->mCurrentFrame.mThDepth;
- mvCurrentDepth = pTracker->mCurrentFrame.mvDepth;
- if(both){
- mvCurrentKeysRight = pTracker->mCurrentFrame.mvKeysRight;
- pTracker->mImRight.copyTo(mImRight);
- N = mvCurrentKeys.size() + mvCurrentKeysRight.size();
- }
- else{
- N = mvCurrentKeys.size();
- }
- mvbVO = vector<bool>(N,false);
- mvbMap = vector<bool>(N,false);
- mbOnlyTracking = pTracker->mbOnlyTracking;
- //Variables for the new visualization
- mCurrentFrame = pTracker->mCurrentFrame;
- mmProjectPoints = mCurrentFrame.mmProjectPoints;
- mmMatchedInImage.clear();
- mvpLocalMap = pTracker->GetLocalMapMPS();
- mvMatchedKeys.clear();
- mvMatchedKeys.reserve(N);
- mvpMatchedMPs.clear();
- mvpMatchedMPs.reserve(N);
- mvOutlierKeys.clear();
- mvOutlierKeys.reserve(N);
- mvpOutlierMPs.clear();
- mvpOutlierMPs.reserve(N);
- if(pTracker->mLastProcessedState==Tracking::NOT_INITIALIZED)
- {
- mvIniKeys=pTracker->mInitialFrame.mvKeys;
- mvIniMatches=pTracker->mvIniMatches;
- }
- else if(pTracker->mLastProcessedState==Tracking::OK)
- {
- for(int i=0;i<N;i++)
- {
- MapPoint* pMP = pTracker->mCurrentFrame.mvpMapPoints[i];
- if(pMP)
- {
- if(!pTracker->mCurrentFrame.mvbOutlier[i])
- {
- if(pMP->Observations()>0)
- mvbMap[i]=true;
- else
- mvbVO[i]=true;
- mmMatchedInImage[pMP->mnId] = mvCurrentKeys[i].pt;
- }
- else
- {
- mvpOutlierMPs.push_back(pMP);
- mvOutlierKeys.push_back(mvCurrentKeys[i]);
- }
- }
- }
- }
- mState=static_cast<int>(pTracker->mLastProcessedState);
- }
- } //namespace ORB_SLAM
|