Skip to content

Commit

Permalink
Finalize for Release (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
makra89 authored Mar 3, 2021
1 parent 2659cf9 commit cdd061c
Show file tree
Hide file tree
Showing 10 changed files with 336 additions and 58 deletions.
3 changes: 3 additions & 0 deletions python/example/runKittiDemo.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ def usage():
skew = 0.0
mono_calib = Vocpp.MonoCameraCalibration(foc_length, cam_center_x, cam_center_y, skew)

# Activate debug output
master.ActivateDebugOutput()

# Load calibration to master
ret = master.LoadCalibration(mono_calib)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class DeltaPoseReconstructor
/**
* /brief Provide next image frame to reconstructor together with a calibration matrix
*/
bool FeedNextFrame(const Frame& in_frame, const cv::Mat1f& in_calibMat);
bool FeedNextFrame(const Frame& in_frame, const cv::Mat1f& in_calibMat, bool in_debugOutputFlag);

/**
* /brief Get computed delta pose of last frame to the frame before
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/* This file is part of the Visual-Odometry-Cpp project.
* It is subject to the license terms in the LICENSE file
* found in the top-level directory of this distribution.
*
* Copyright (C) 2020 Manuel Kraus
*/

#ifndef VOCPP_FEATURE_TRACKER_H
#define VOCPP_FEATURE_TRACKER_H

#include <Vocpp_FeatureHandling/LshMatcher.h>

#include <map>

namespace VOCPP
{
namespace DeltaPoseReconstruction
{

class TrackedFeature
{
public:
TrackedFeature(unsigned int in_currentFrameId, unsigned int in_currentFeatureId, const FeatureHandling::BinaryFeatureDescription& in_currentDesc) :
m_frameIdVsFeatureId(),
m_frameIdVsDescription()
{
Update(in_currentFrameId, in_currentFeatureId, in_currentDesc);
}

bool IsPresentInFrame(unsigned int in_frameId) const
{
return m_frameIdVsFeatureId.count(in_frameId) > 0 ? true : false;
}

bool IsPresentInFrameWithFeatureId(const unsigned int& in_frameId, const unsigned int& in_featureId) const
{
bool ret = m_frameIdVsFeatureId.count(in_frameId) > 0 ? true : false;

if (ret)
{
ret = m_frameIdVsFeatureId.at(in_frameId) == in_featureId ? true : false;
}

return ret;
}

void Update(unsigned int in_currentFrameId, unsigned int in_currentFeatureId, const FeatureHandling::BinaryFeatureDescription& in_currentDesc)
{
// Only add occurence in current frame (should be present in last one already)
m_frameIdVsFeatureId.insert(std::pair<int, int>(in_currentFrameId, in_currentFeatureId));
m_frameIdVsDescription.insert(std::pair<int, FeatureHandling::BinaryFeatureDescription>(in_currentFrameId, in_currentDesc));
m_lastSeenFrameId = in_currentFrameId;
}

unsigned int m_lastSeenFrameId;
std::map<int, int> m_frameIdVsFeatureId;
std::map<int, FeatureHandling::BinaryFeatureDescription> m_frameIdVsDescription;
};

struct TrackedFeatureSet
{
std::vector<TrackedFeature> features;
bool isKeySet;
};

class FeatureTracker
{
public:

FeatureTracker(unsigned int in_minTrackedTwoFrames=100U, unsigned int in_minTrackedThreeFrames=10U)
: m_matcher(),
m_currentKeyFeatureSet(),
m_lastKeyFrameId(s_invalidFrameId),
m_KeyFrameIdBeforeLast(s_invalidFrameId),
m_lastKeyFrameDescriptions(),
m_minTrackedTwoFrames(in_minTrackedTwoFrames),
m_minTrackedThreeFrames(in_minTrackedThreeFrames),
m_trackingStatus(TrackingStatus::Lost)
{
}

TrackedFeatureSet ProvideDescriptionSet(unsigned int in_currentFrameId, std::vector<VOCPP::FeatureHandling::BinaryFeatureDescription>& in_currentDesc);

private:

FeatureHandling::LshMatcher m_matcher;
TrackedFeatureSet m_currentKeyFeatureSet;

unsigned int m_lastKeyFrameId;
unsigned int m_KeyFrameIdBeforeLast;
std::vector<FeatureHandling::BinaryFeatureDescription> m_lastKeyFrameDescriptions;
const unsigned int m_minTrackedTwoFrames;
const unsigned int m_minTrackedThreeFrames;

enum TrackingStatus
{
Active = 0U,
Lost = 1U
} m_trackingStatus;
};

} //namespace DeltaPoseReconstruction
} //namespace VOCPP

#endif /* VOCPP_FEATURE_TRACKER_H */
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,6 @@ class LocalMap
*/
void InsertLandmarks(const std::vector<LandmarkPosition>& in_positions, const std::vector<FeatureHandling::BinaryDescriptionMatch>& in_matches, const unsigned int& in_currentFrameId);

void RemoveUntrackedLandmarks(const unsigned int& in_currentFrameId);

bool GetLastRelativeScale(const unsigned int& in_lastFrameId, const unsigned int& in_currentFrameId, float& out_scale) const;

/**
Expand All @@ -173,6 +171,8 @@ class LocalMap

private:

void RemoveUntrackedLandmarks(const unsigned int& in_currentFrameId);

void ComputeRelativeScale(const unsigned int& in_currentFrameId);

std::vector<Landmark> m_landmarks; ///< stored landmarks
Expand Down
44 changes: 24 additions & 20 deletions src/DeltaPoseReconstruction/src/DeltaPoseReconstructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ DeltaPoseReconstructor::~DeltaPoseReconstructor()
Reset();
}

bool DeltaPoseReconstructor::FeedNextFrame(const Frame& in_frame, const cv::Mat1f& in_calibMat)
bool DeltaPoseReconstructor::FeedNextFrame(const Frame& in_frame, const cv::Mat1f& in_calibMat, bool in_debugOutputFlag)
{
bool ret = true;

Expand Down Expand Up @@ -134,8 +134,6 @@ bool DeltaPoseReconstructor::FeedNextFrame(const Frame& in_frame, const cv::Mat1
inlierMatches.push_back(matches[matchIdx]);
}

std::cout << inlierMatches.size() << std::endl;

// Triangulate all inliers
std::vector<LandmarkPosition> landmarks;
for (auto matchIdx : inlierMatchIndices)
Expand All @@ -149,19 +147,21 @@ bool DeltaPoseReconstructor::FeedNextFrame(const Frame& in_frame, const cv::Mat1
cv::Point3f triangulatedPoint;
Utils::PointTriangulationLinear(m_lastProjectionMat, currentProjMat, currFrameCamCoord, lastFrameCamCoord, triangulatedPoint);

// Add triangulated landmarks to local map
landmarks.push_back(LandmarkPosition{ triangulatedPoint.x, triangulatedPoint.y, triangulatedPoint.z });
}

/* Relative scale calculation currently deactivated
// Add triangulated landmarks to local map
// m_localMap.InsertLandmarks(landmarks, inlierMatches, in_frame.GetId());
m_localMap.InsertLandmarks(landmarks, inlierMatches, in_frame.GetId());
// And calculate scale, apply it to translation vector
float scale = 0.0;
if (m_localMap.GetLastRelativeScale(m_lastFrameId, in_frame.GetId(), scale))
{
// Currently deactivated, there is a memory leak somewhere
// translation = translation * scale;
translation = translation * scale;
}

*/

////////////////////////////////////////////////////////////////////////////////////////////////////
/////// REFINED POSE CALCULATION //////
////////////////////////////////////////////////////////////////////////////////////////////////////
Expand All @@ -180,21 +180,25 @@ bool DeltaPoseReconstructor::FeedNextFrame(const Frame& in_frame, const cv::Mat1
m_lastPose = CameraPose(currentPosWcs, currentOrientWcs);

tick.stop();
std::cout << "[DeltaPoseReconstruction]: Frame processing time: " << tick.getTimeMilli() << std::endl;
cv::Mat matchImage = in_frame.GetImageCopy();
cv::cvtColor(matchImage, matchImage, cv::COLOR_GRAY2BGR);
for (auto matchIdx : inlierMatchIndices)
// Only show debug output if requested
if (in_debugOutputFlag)
{
// Draw keypoints from current frame
cv::circle(matchImage, pCurrFrame[matchIdx], 5, cv::Scalar(0, 0.0, 255.0), 2);
// Draw keypoints from last frame
cv::circle(matchImage, pLastFrame[matchIdx], 5, cv::Scalar(0.0, 255.0, 0.0), 2);
// Draw connecting line
cv::line(matchImage, pCurrFrame[matchIdx], pLastFrame[matchIdx], cv::Scalar(0.0, 0.0, 255.0), 2);
std::cout << "[DeltaPoseReconstruction]: Frame processing time: " << tick.getTimeMilli() << std::endl;
cv::Mat matchImage = in_frame.GetImageCopy();
cv::cvtColor(matchImage, matchImage, cv::COLOR_GRAY2BGR);
for (auto matchIdx : inlierMatchIndices)
{
// Draw keypoints from current frame
cv::circle(matchImage, pCurrFrame[matchIdx], 5, cv::Scalar(0, 0.0, 255.0), 2);
// Draw keypoints from last frame
cv::circle(matchImage, pLastFrame[matchIdx], 5, cv::Scalar(0.0, 255.0, 0.0), 2);
// Draw connecting line
cv::line(matchImage, pCurrFrame[matchIdx], pLastFrame[matchIdx], cv::Scalar(0.0, 0.0, 255.0), 2);
}

cv::imshow("Optical Flow", matchImage);
cv::waitKey(1);
}

cv::imshow("Optical Flow", matchImage);
cv::waitKey(1);
}

// Save last frame, descriptions and keypoints
Expand Down
115 changes: 115 additions & 0 deletions src/DeltaPoseReconstruction/src/FeatureTracker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/* This file is part of the Visual-Odometry-Cpp project.
* It is subject to the license terms in the LICENSE file
* found in the top-level directory of this distribution.
*
* Copyright (C) 2020 Manuel Kraus
*/

#include <Vocpp_DeltaPoseReconstruction/FeatureTracker.h>

namespace
{

void RemoveUntrackedFeatures(VOCPP::DeltaPoseReconstruction::TrackedFeatureSet& featSet, const unsigned int& in_currentFrameId)
{
auto newEnd = std::remove_if(featSet.features.begin(), featSet.features.end(),
[&in_currentFrameId](const VOCPP::DeltaPoseReconstruction::TrackedFeature& i) {return i.m_lastSeenFrameId < in_currentFrameId; });
featSet.features.erase(newEnd, featSet.features.end());
};

}

namespace VOCPP
{
namespace DeltaPoseReconstruction
{

TrackedFeatureSet FeatureTracker::ProvideDescriptionSet(unsigned int in_currentFrameId, std::vector<VOCPP::FeatureHandling::BinaryFeatureDescription>& in_currentDesc)
{
TrackedFeatureSet featureSet{ std::vector<TrackedFeature>(), false };

if (m_trackingStatus == TrackingStatus::Lost)
{
for (auto desc : in_currentDesc)
{
featureSet.features.push_back(TrackedFeature(desc.GetFeature().frameId, desc.GetFeature().id, desc));
}

// No valid last key set
featureSet.isKeySet = true;
m_currentKeyFeatureSet = featureSet;
m_lastKeyFrameId = in_currentDesc.size() > 0U ? in_currentDesc[0].GetFeature().frameId : s_invalidFrameId;
m_lastKeyFrameDescriptions = in_currentDesc;
m_trackingStatus = in_currentDesc.size() > 0U ? TrackingStatus::Active : TrackingStatus::Lost;
std::cout << "Lost" << std::endl;
}
else
{
std::cout << "Active" << std::endl;
// Here we should have at least descriptions for the last keyFrame
std::vector<FeatureHandling::BinaryDescriptionMatch> matches;
bool ret = m_matcher.MatchDesriptions(in_currentDesc, m_lastKeyFrameDescriptions, matches);

// First copy the key set history to the new feature set
featureSet = m_currentKeyFeatureSet;

TrackedFeatureSet missingFeatureSet{ std::vector<TrackedFeature>(), false };

for (unsigned int it = 0U; it < matches.size(); it++)
{
// Check whether this feature has been observed before
bool found = false;
for (auto& feat : featureSet.features)
{
// We assume here that first frame == current frame and second frame == last frame
if (feat.IsPresentInFrameWithFeatureId(matches[it].GetSecondFeature().frameId, matches[it].GetSecondFeature().id))
{
feat.Update(matches[it].GetFirstFeature().frameId, matches[it].GetFirstFeature().id, matches[it].GetFirstDescription());
found = true;
}
}

// If feature has not been found --> store them for later when we decide whether this will be a key set
if (!found)
{
missingFeatureSet.features.push_back(TrackedFeature(matches[it].GetFirstFeature().frameId, matches[it].GetFirstFeature().id, matches[it].GetFirstDescription()));
}
}
RemoveUntrackedFeatures(featureSet, in_currentFrameId);

const unsigned int numMatchesTrackedTwoKeyFrames = matches.size();
unsigned int numMatchesTrackedThreeKeyFrames = 0U;
for (auto feat : m_currentKeyFeatureSet.features)
{
if (feat.IsPresentInFrame(m_KeyFrameIdBeforeLast))
{
numMatchesTrackedThreeKeyFrames++;
}
}
std::cout << numMatchesTrackedTwoKeyFrames << " " << numMatchesTrackedThreeKeyFrames << " "<<in_currentFrameId<<" "<< m_KeyFrameIdBeforeLast<< std::endl;
if (numMatchesTrackedTwoKeyFrames < m_minTrackedTwoFrames || numMatchesTrackedThreeKeyFrames < m_minTrackedThreeFrames)
{
featureSet.isKeySet = true;
for (auto feat : missingFeatureSet.features)
{
featureSet.features.push_back(feat);
}

m_currentKeyFeatureSet = featureSet;
m_lastKeyFrameDescriptions = in_currentDesc;
m_KeyFrameIdBeforeLast = m_lastKeyFrameId;
m_lastKeyFrameId = in_currentFrameId;
std::cout << "Keyframe " << std::endl;
}
else
{
featureSet.isKeySet = false;
}
}

return featureSet;
}


} //namespace DeltaPoseReconstruction
} //namespace VOCPP
2 changes: 2 additions & 0 deletions src/DeltaPoseReconstruction/src/LocalMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ void LocalMap::InsertLandmarks(const std::vector<LandmarkPosition>& in_positions
}
}

RemoveUntrackedLandmarks(in_currentFrameId);

ComputeRelativeScale(in_currentFrameId);
m_lastFrameId = in_currentFrameId;
}
Expand Down
Loading

0 comments on commit cdd061c

Please sign in to comment.