// Copyright Epic Games, Inc. All Rights Reserved. #include "RobustFeatureMatcher.h" #include "Common.h" #include "Internals/OpenCVCamera2MetaShapeCamera.h" #include #include using namespace TITAN_NAMESPACE; namespace TITAN_API_NAMESPACE { static std::vector EigenToPointsVector(const Eigen::MatrixX& InPoints) { std::vector Points; for (Eigen::MatrixX::Index Row = 0; Row < InPoints.rows(); ++Row) { double X = InPoints(Row, 0); double Y = InPoints(Row, 1); Points.push_back((float)X); Points.push_back((float)Y); } return Points; } struct RobustFeatureMatcher::Private { RobustFeatureMatcherParams Params; RobustFeatureMatcherContext Context; }; RobustFeatureMatcher::RobustFeatureMatcher() : pImpl(new Private()) { } RobustFeatureMatcher::~RobustFeatureMatcher() { if (pImpl) { delete pImpl; pImpl = nullptr; } } RobustFeatureMatcher::RobustFeatureMatcher(RobustFeatureMatcher&& InOther) noexcept : pImpl(InOther.pImpl) { InOther.pImpl = nullptr; } RobustFeatureMatcher& RobustFeatureMatcher::operator=(RobustFeatureMatcher&& InOther) noexcept { if (this == &InOther) { return *this; } if (pImpl) { delete pImpl; pImpl = nullptr; } pImpl = InOther.pImpl; InOther.pImpl = nullptr; return *this; } bool RobustFeatureMatcher::Init(const std::string& InCalibrationFilePath, double InReprojectionThreshold, double InRatioThreshold) { pImpl->Params.setMetaShapeCamerasFromFile(InCalibrationFilePath); pImpl->Params.setReprojectionThreshold(InReprojectionThreshold); pImpl->Params.setRatioThreshold(InRatioThreshold); pImpl->Context.setFeatureNumThreshold(100000); return true; } bool RobustFeatureMatcher::Init(const std::map& InCalibrationInformation, double InReprojectionThreshold, double InRatioThreshold) { std::vector> MetaShapeCalibrationInformation; std::transform(InCalibrationInformation.begin(), InCalibrationInformation.end(), std::back_inserter(MetaShapeCalibrationInformation), [](const std::pair& InElem) { return OpenCVCamera2MetaShapeCamera(InElem.first.c_str(), InElem.second); }); pImpl->Params.setMetaShapeCameras(MetaShapeCalibrationInformation); pImpl->Params.setReprojectionThreshold(InReprojectionThreshold); pImpl->Params.setRatioThreshold(InRatioThreshold); pImpl->Context.setFeatureNumThreshold(100000); return true; } bool RobustFeatureMatcher::AddCamera(const std::string& InCameraName, int32_t InWidth, int32_t InHeight) { RobustFeatureMatcherParams::Camera Camera; Camera.name = InCameraName; Camera.width = InWidth; Camera.height = InHeight; pImpl->Params.addCamera(Camera); return true; } bool RobustFeatureMatcher::GetDetectedFeatures(size_t InFrame, std::vector& OutPoints3d, std::vector>& OutCameraPoints, std::vector>& OutPoints3dReprojected) { try { TITAN_RESET_ERROR; Eigen::MatrixX Points3d; std::vector> Visibility; std::vector> CameraPoints; std::vector> Points3dReprojected; pImpl->Context.getScene(InFrame, Points3d, Visibility, CameraPoints, Points3dReprojected); OutPoints3d = EigenToPointsVector(Points3d); auto TransformLambda = [](const Eigen::MatrixX& InElem) { return EigenToPointsVector(InElem); }; std::transform(CameraPoints.begin(), CameraPoints.end(), std::inserter(OutCameraPoints, OutCameraPoints.end()), TransformLambda); std::transform(Points3dReprojected.begin(), Points3dReprojected.end(), std::inserter(OutPoints3dReprojected, OutPoints3dReprojected.end()), TransformLambda); return true; } catch (const std::exception& InException) { TITAN_HANDLE_EXCEPTION("Failed to obtain the detected features: {}", InException.what()); } } bool RobustFeatureMatcher::GetDetectedFeatures(const std::vector& InFrames, std::map>& OutPoints3d, std::map>>& OutCameraPoints, std::map>>& OutPoints3dReprojected) { for (size_t Frame : InFrames) { bool bSuccess = GetDetectedFeatures(Frame, OutPoints3d[Frame], OutCameraPoints[Frame], OutPoints3dReprojected[Frame]); if (!bSuccess) { return false; } } return true; } bool RobustFeatureMatcher::DetectFeatures(size_t InFrame, const std::vector& InImages) { try { TITAN_RESET_ERROR; pImpl->Context.setParams(pImpl->Params); pImpl->Context.computeFeaturesAndMatches(InFrame, InImages); pImpl->Context.createScene(InFrame); return true; } catch (const std::exception& InException) { TITAN_HANDLE_EXCEPTION("Failed to create a scene: {}", InException.what()); } } bool RobustFeatureMatcher::DetectFeatures(const std::map>& InImages) { for (const auto& ImagePair : InImages) { bool bSuccess = DetectFeatures(ImagePair.first, ImagePair.second); if (!bSuccess) { return false; } } return true; } } // namespace TITAN_API_NAMESPACE