You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
797 lines
24 KiB
797 lines
24 KiB
#ifndef _INTERFACE_MVS_H_ |
|
#define _INTERFACE_MVS_H_ |
|
|
|
|
|
// I N C L U D E S ///////////////////////////////////////////////// |
|
|
|
#include <fstream> |
|
#include <string> |
|
#include <cctype> |
|
#include <limits> |
|
|
|
|
|
// D E F I N E S /////////////////////////////////////////////////// |
|
|
|
#define MVSI_PROJECT_ID "MVSI" // identifies the project stream |
|
#define MVSI_PROJECT_VER ((uint32_t)7) // identifies the version of a project stream |
|
|
|
// set a default namespace name if none given |
|
#ifndef _INTERFACE_NAMESPACE |
|
#define _INTERFACE_NAMESPACE MVS |
|
#endif |
|
|
|
// uncomment to enable custom OpenCV data types |
|
// (should be uncommented if OpenCV is not available) |
|
#if !defined(_USE_OPENCV) && !defined(_USE_CUSTOM_CV) |
|
#define _USE_CUSTOM_CV |
|
#endif |
|
|
|
// set to disable custom NO_ID declaration |
|
#ifndef _DISABLE_NO_ID |
|
#define _INTERFACE_NO_ID |
|
#endif |
|
|
|
|
|
// S T R U C T S /////////////////////////////////////////////////// |
|
|
|
#ifdef _USE_CUSTOM_CV |
|
|
|
namespace cv { |
|
|
|
// simple cv::Point3_ |
|
template<typename Type> |
|
class Point3_ |
|
{ |
|
public: |
|
typedef Type value_type; |
|
|
|
inline Point3_() {} |
|
inline Point3_(Type _x, Type _y, Type _z) : x(_x), y(_y), z(_z) {} |
|
#ifdef _USE_EIGEN |
|
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Type,3) |
|
typedef Eigen::Matrix<Type,3,1> EVec; |
|
typedef Eigen::Map<EVec> EVecMap; |
|
template<typename Derived> |
|
inline Point3_(const Eigen::EigenBase<Derived>& rhs) { operator EVecMap () = rhs; } |
|
template<typename Derived> |
|
inline Point3_& operator = (const Eigen::EigenBase<Derived>& rhs) { operator EVecMap () = rhs; return *this; } |
|
inline operator const EVecMap () const { return EVecMap((Type*)this); } |
|
inline operator EVecMap () { return EVecMap((Type*)this); } |
|
#endif |
|
|
|
const Type* ptr() const { return &x; } |
|
Type* ptr() { return &x; } |
|
Type operator()(int r) const { return (&x)[r]; } |
|
Type& operator()(int r) { return (&x)[r]; } |
|
Point3_ operator - () const { |
|
return Point3_( |
|
-x, |
|
-y, |
|
-z |
|
); |
|
} |
|
Point3_ operator + (const Point3_& X) const { |
|
return Point3_( |
|
x+X.x, |
|
y+X.y, |
|
z+X.z |
|
); |
|
} |
|
Point3_ operator - (const Point3_& X) const { |
|
return Point3_( |
|
x-X.x, |
|
y-X.y, |
|
z-X.z |
|
); |
|
} |
|
|
|
public: |
|
Type x, y, z; |
|
}; |
|
|
|
// simple cv::Matx |
|
template<typename Type, int m, int n> |
|
class Matx |
|
{ |
|
public: |
|
typedef Type value_type; |
|
enum { |
|
rows = m, |
|
cols = n, |
|
channels = rows*cols |
|
}; |
|
|
|
inline Matx() {} |
|
#ifdef _USE_EIGEN |
|
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Type,m*n) |
|
typedef Eigen::Matrix<Type,m,n,(n>1?Eigen::RowMajor:Eigen::Default)> EMat; |
|
typedef Eigen::Map<const EMat> CEMatMap; |
|
typedef Eigen::Map<EMat> EMatMap; |
|
template<typename Derived> |
|
inline Matx(const Eigen::EigenBase<Derived>& rhs) { operator EMatMap () = rhs; } |
|
template<typename Derived> |
|
inline Matx& operator = (const Eigen::EigenBase<Derived>& rhs) { operator EMatMap () = rhs; return *this; } |
|
inline operator CEMatMap() const { return CEMatMap((const Type*)val); } |
|
inline operator EMatMap () { return EMatMap((Type*)val); } |
|
#endif |
|
|
|
Type operator()(int r, int c) const { return val[r*n+c]; } |
|
Type& operator()(int r, int c) { return val[r*n+c]; } |
|
Point3_<Type> operator * (const Point3_<Type>& X) const { |
|
Point3_<Type> R; |
|
for (int r = 0; r < m; r++) { |
|
R(r) = Type(0); |
|
for (int c = 0; c < n; c++) |
|
R(r) += operator()(r,c)*X(c); |
|
} |
|
return R; |
|
} |
|
template<int k> |
|
Matx<Type,m,k> operator * (const Matx<Type,n,k>& M) const { |
|
Matx<Type,m,k> R; |
|
for (int r = 0; r < m; r++) { |
|
for (int l = 0; l < k; l++) { |
|
R(r,l) = Type(0); |
|
for (int c = 0; c < n; c++) |
|
R(r,l) += operator()(r,c)*M(c,l); |
|
} |
|
} |
|
return R; |
|
} |
|
Matx<Type,n,m> t() const { |
|
Matx<Type,n,m> M; |
|
for (int r = 0; r < m; r++) |
|
for (int c = 0; c < n; c++) |
|
M(c,r) = operator()(r,c); |
|
return M; |
|
} |
|
|
|
static Matx eye() { |
|
Matx M; |
|
memset(M.val, 0, sizeof(Type)*m*n); |
|
const int shortdim(m < n ? m : n); |
|
for (int i = 0; i < shortdim; i++) |
|
M(i,i) = 1; |
|
return M; |
|
} |
|
|
|
public: |
|
Type val[m*n]; |
|
}; |
|
|
|
} // namespace cv |
|
#endif |
|
/*----------------------------------------------------------------*/ |
|
|
|
|
|
namespace _INTERFACE_NAMESPACE { |
|
|
|
// invalid index |
|
#ifdef _INTERFACE_NO_ID |
|
constexpr uint32_t NO_ID {std::numeric_limits<uint32_t>::max()}; |
|
#endif |
|
|
|
// custom serialization |
|
namespace ARCHIVE { |
|
|
|
// Basic serialization types |
|
struct ArchiveSave { |
|
std::ostream& stream; |
|
uint32_t version; |
|
ArchiveSave(std::ostream& _stream, uint32_t _version) |
|
: stream(_stream), version(_version) {} |
|
template<typename _Tp> |
|
ArchiveSave& operator & (const _Tp& obj); |
|
}; |
|
struct ArchiveLoad { |
|
std::istream& stream; |
|
uint32_t version; |
|
ArchiveLoad(std::istream& _stream, uint32_t _version) |
|
: stream(_stream), version(_version) {} |
|
template<typename _Tp> |
|
ArchiveLoad& operator & (_Tp& obj); |
|
}; |
|
|
|
template<typename _Tp> |
|
bool Save(ArchiveSave& a, const _Tp& obj) { |
|
const_cast<_Tp&>(obj).serialize(a, a.version); |
|
return true; |
|
} |
|
template<typename _Tp> |
|
bool Load(ArchiveLoad& a, _Tp& obj) { |
|
obj.serialize(a, a.version); |
|
return true; |
|
} |
|
|
|
template<typename _Tp> |
|
ArchiveSave& ArchiveSave::operator & (const _Tp& obj) { |
|
Save(*this, obj); |
|
return *this; |
|
} |
|
template<typename _Tp> |
|
ArchiveLoad& ArchiveLoad::operator & (_Tp& obj) { |
|
Load(*this, obj); |
|
return *this; |
|
} |
|
|
|
// Main exporter & importer |
|
template<typename _Tp> |
|
bool SerializeSave(const _Tp& obj, const std::string& fileName, uint32_t version=MVSI_PROJECT_VER) { |
|
// open the output stream |
|
std::ofstream stream(fileName, std::ofstream::binary); |
|
if (!stream.is_open()) |
|
return false; |
|
// write header |
|
if (version > 0) { |
|
// save project ID |
|
stream.write(MVSI_PROJECT_ID, 4); |
|
// save project version |
|
stream.write((const char*)&version, sizeof(uint32_t)); |
|
// reserve some bytes |
|
const uint32_t reserved(0); |
|
stream.write((const char*)&reserved, sizeof(uint32_t)); |
|
} |
|
// serialize out the current state |
|
ARCHIVE::ArchiveSave serializer(stream, version); |
|
serializer & obj; |
|
return true; |
|
} |
|
template<typename _Tp> |
|
bool SerializeLoad(_Tp& obj, const std::string& fileName, uint32_t* pVersion=NULL) { |
|
// open the input stream |
|
std::ifstream stream(fileName, std::ifstream::binary); |
|
if (!stream.is_open()) |
|
return false; |
|
// read header |
|
uint32_t version(0); |
|
// load project header ID |
|
char szHeader[4]; |
|
stream.read(szHeader, 4); |
|
if (!stream) |
|
return false; |
|
if (strncmp(szHeader, MVSI_PROJECT_ID, 4) != 0) { |
|
// try to load as the first version that didn't have a header |
|
const size_t size(fileName.size()); |
|
if (size <= 4) |
|
return false; |
|
std::string ext(fileName.substr(size-4)); |
|
std::transform(ext.begin(), ext.end(), ext.begin(), [](char c) { return (char)std::tolower(c); }); |
|
if (ext != ".mvs") |
|
return false; |
|
stream.seekg(0, std::ifstream::beg); |
|
} else { |
|
// load project version |
|
stream.read((char*)&version, sizeof(uint32_t)); |
|
if (!stream || version > MVSI_PROJECT_VER) |
|
return false; |
|
// skip reserved bytes |
|
uint32_t reserved; |
|
stream.read((char*)&reserved, sizeof(uint32_t)); |
|
} |
|
// serialize in the current state |
|
ARCHIVE::ArchiveLoad serializer(stream, version); |
|
serializer & obj; |
|
if (pVersion) |
|
*pVersion = version; |
|
return true; |
|
} |
|
|
|
|
|
#define ARCHIVE_DEFINE_TYPE(TYPE) \ |
|
template<> \ |
|
inline bool Save<TYPE>(ArchiveSave& a, const TYPE& v) { \ |
|
a.stream.write((const char*)&v, sizeof(TYPE)); \ |
|
return true; \ |
|
} \ |
|
template<> \ |
|
inline bool Load<TYPE>(ArchiveLoad& a, TYPE& v) { \ |
|
a.stream.read((char*)&v, sizeof(TYPE)); \ |
|
return true; \ |
|
} |
|
|
|
// Serialization support for basic types |
|
ARCHIVE_DEFINE_TYPE(uint32_t) |
|
ARCHIVE_DEFINE_TYPE(uint64_t) |
|
ARCHIVE_DEFINE_TYPE(float) |
|
ARCHIVE_DEFINE_TYPE(double) |
|
|
|
// Serialization support for cv::Matx |
|
template<typename _Tp, int m, int n> |
|
inline bool Save(ArchiveSave& a, const cv::Matx<_Tp,m,n>& _m) { |
|
a.stream.write((const char*)_m.val, sizeof(_Tp)*m*n); |
|
return true; |
|
} |
|
template<typename _Tp, int m, int n> |
|
inline bool Load(ArchiveLoad& a, cv::Matx<_Tp,m,n>& _m) { |
|
a.stream.read((char*)_m.val, sizeof(_Tp)*m*n); |
|
return true; |
|
} |
|
|
|
// Serialization support for cv::Point3_ |
|
template<typename _Tp> |
|
inline bool Save(ArchiveSave& a, const cv::Point3_<_Tp>& pt) { |
|
a.stream.write((const char*)&pt.x, sizeof(_Tp)*3); |
|
return true; |
|
} |
|
template<typename _Tp> |
|
inline bool Load(ArchiveLoad& a, cv::Point3_<_Tp>& pt) { |
|
a.stream.read((char*)&pt.x, sizeof(_Tp)*3); |
|
return true; |
|
} |
|
|
|
// Serialization support for std::string |
|
template<> |
|
inline bool Save<std::string>(ArchiveSave& a, const std::string& s) { |
|
const uint64_t size(s.size()); |
|
Save(a, size); |
|
if (size > 0) |
|
a.stream.write(&s[0], sizeof(char)*size); |
|
return true; |
|
} |
|
template<> |
|
inline bool Load<std::string>(ArchiveLoad& a, std::string& s) { |
|
uint64_t size; |
|
Load(a, size); |
|
if (size > 0) { |
|
s.resize(size); |
|
a.stream.read(&s[0], sizeof(char)*size); |
|
} |
|
return true; |
|
} |
|
|
|
// Serialization support for std::vector |
|
template<typename _Tp> |
|
inline bool Save(ArchiveSave& a, const std::vector<_Tp>& v) { |
|
const uint64_t size(v.size()); |
|
Save(a, size); |
|
for (uint64_t i=0; i<size; ++i) |
|
Save(a, v[i]); |
|
return true; |
|
} |
|
template<typename _Tp> |
|
inline bool Load(ArchiveLoad& a, std::vector<_Tp>& v) { |
|
uint64_t size; |
|
Load(a, size); |
|
if (size > 0) { |
|
v.resize(size); |
|
for (uint64_t i=0; i<size; ++i) |
|
Load(a, v[i]); |
|
} |
|
return true; |
|
} |
|
|
|
} // namespace ARCHIVE |
|
/*----------------------------------------------------------------*/ |
|
|
|
|
|
// interface used to export/import MVS input data; |
|
// - MAX(width,height) is used for normalization |
|
// - row-major order is used for storing the matrices |
|
struct Interface |
|
{ |
|
typedef cv::Point3_<float> Pos3f; |
|
typedef cv::Point3_<double> Pos3d; |
|
typedef cv::Matx<double,3,3> Mat33d; |
|
typedef cv::Matx<double,4,4> Mat44d; |
|
typedef cv::Point3_<uint8_t> Col3; // x=B, y=G, z=R |
|
/*----------------------------------------------------------------*/ |
|
|
|
// structure describing a mobile platform with cameras attached to it |
|
struct Platform { |
|
// structure describing a camera mounted on a platform |
|
struct Camera { |
|
std::string name; // camera's name |
|
std::string bandName; // camera's band name, ex: RGB, BLUE, GREEN, RED, NIR, THERMAL, etc (optional) |
|
uint32_t width, height; // image resolution in pixels for all images sharing this camera (optional) |
|
Mat33d K; // camera's intrinsics matrix (normalized if image resolution not specified), where integer coordinates is by convention the pixel center |
|
Mat33d R; // camera's rotation matrix relative to the platform |
|
Pos3d C; // camera's translation vector relative to the platform |
|
|
|
Camera() : width(0), height(0) {} |
|
bool HasResolution() const { return width > 0 && height > 0; } |
|
bool IsNormalized() const { return !HasResolution(); } |
|
static uint32_t GetNormalizationScale(uint32_t width, uint32_t height) { return std::max(width, height); } |
|
uint32_t GetNormalizationScale() const { return GetNormalizationScale(width, height); } |
|
|
|
// project point: camera to image (homogeneous) coordinates |
|
inline Pos3d operator * (const Pos3d& X) const { |
|
return Pos3d( |
|
K(0,2)+K(0,0)*X.x/X.z, |
|
K(1,2)+K(1,1)*X.y/X.z, |
|
1.0); |
|
} |
|
// back-project point: image (z is the depth) to camera coordinates |
|
inline Pos3d operator / (const Pos3d& x) const { |
|
return Pos3d( |
|
(x.x-K(0,2))*x.z/K(0,0), |
|
(x.y-K(1,2))*x.z/K(1,1), |
|
1.0); |
|
} |
|
|
|
template <class Archive> |
|
void serialize(Archive& ar, const unsigned int version) { |
|
ar & name; |
|
if (version > 3) { |
|
ar & bandName; |
|
} |
|
if (version > 0) { |
|
ar & width; |
|
ar & height; |
|
} |
|
ar & K; |
|
ar & R; |
|
ar & C; |
|
} |
|
}; |
|
typedef std::vector<Camera> CameraArr; |
|
|
|
// structure describing a pose along the trajectory of a platform |
|
struct Pose { |
|
Mat33d R; // platform's rotation matrix that rotates a point from world to camera coordinate system |
|
Pos3d C; // platform's translation vector (position) in world coordinate system |
|
|
|
Pose() {} |
|
template <typename MAT, typename POS> |
|
Pose(const MAT& _R, const POS& _C) : R(_R), C(_C) {} |
|
|
|
// translation vector t = -RC |
|
inline Pos3d GetTranslation() const { return R*(-C); } |
|
inline void SetTranslation(const Pos3d& T) { C = R.t()*(-T); } |
|
|
|
// combine poses |
|
inline Pose operator * (const Pose& P) const { |
|
return Pose(R*P.R, P.R.t()*C+P.C); |
|
} |
|
inline Pose& operator *= (const Pose& P) { |
|
R = R*P.R; C = P.R.t()*C+P.C; return *this; |
|
} |
|
|
|
// project point: world to local coordinates |
|
inline Pos3d operator * (const Pos3d& X) const { |
|
return R * (X - C); |
|
} |
|
// back-project point: local to world coordinates |
|
inline Pos3d operator / (const Pos3d& X) const { |
|
return R.t() * X + C; |
|
} |
|
|
|
template <class Archive> |
|
void serialize(Archive& ar, const unsigned int /*version*/) { |
|
ar & R; |
|
ar & C; |
|
} |
|
}; |
|
typedef std::vector<Pose> PoseArr; |
|
|
|
std::string name; // platform's name |
|
CameraArr cameras; // cameras mounted on the platform |
|
PoseArr poses; // trajectory of the platform |
|
|
|
const Mat33d& GetK(uint32_t cameraID) const { |
|
return cameras[cameraID].K; |
|
} |
|
static Mat33d ScaleK(const Mat33d& _K, double scale) { |
|
Mat33d K(_K); |
|
const bool bNormalized(K(0,2) < 3 && K(1,2) < 3); |
|
K(0,0) *= scale; |
|
K(1,1) *= scale; |
|
K(0,2) = bNormalized ? K(0,2)*scale : (K(0,2)+0.5)*scale-0.5; |
|
K(1,2) = bNormalized ? K(1,2)*scale : (K(1,2)+0.5)*scale-0.5; |
|
K(0,1) *= scale; |
|
return K; |
|
} |
|
const Mat33d& SetFullK(uint32_t cameraID, const Mat33d& K, uint32_t width, uint32_t height, bool normalize=false) { |
|
Camera& camera = cameras[cameraID]; |
|
if (normalize) { |
|
camera.width = camera.height = 0; |
|
camera.K = ScaleK(K, 1.0/(double)Camera::GetNormalizationScale(width, height)); |
|
} else { |
|
camera.width = width; camera.height = height; |
|
camera.K = K; |
|
} |
|
return camera.K; |
|
} |
|
Mat33d GetFullK(uint32_t cameraID, uint32_t width, uint32_t height) const { |
|
const Camera& camera = cameras[cameraID]; |
|
if (!camera.IsNormalized() && camera.width == width && camera.height == height) |
|
return camera.K; |
|
return ScaleK(camera.K, (double)Camera::GetNormalizationScale(width, height)/ |
|
(camera.IsNormalized()?1.0:(double)camera.GetNormalizationScale())); |
|
} |
|
|
|
Pose GetPose(uint32_t cameraID, uint32_t poseID) const { |
|
const Camera& camera = cameras[cameraID]; |
|
const Pose& pose = poses[poseID]; |
|
// add the relative camera pose to the platform |
|
return Pose{ |
|
camera.R*pose.R, |
|
pose.R.t()*camera.C+pose.C |
|
}; |
|
} |
|
|
|
template <class Archive> |
|
void serialize(Archive& ar, const unsigned int /*version*/) { |
|
ar & name; |
|
ar & cameras; |
|
ar & poses; |
|
} |
|
}; |
|
typedef std::vector<Platform> PlatformArr; |
|
/*----------------------------------------------------------------*/ |
|
|
|
// structure describing an image |
|
struct Image { |
|
// structure describing how an other image relates to this image in terms of overlap, |
|
// i.e. how many 3D points are shared between the two images, base-line and common area, |
|
// useful for ex. when selecting the best images to densly match with |
|
struct ViewScore { |
|
uint32_t ID; // image local-ID, the index in this scene images list |
|
uint32_t points; // number of 3D points shared with the reference image |
|
float scale; // image scale relative to the reference image |
|
float angle; // image angle relative to the reference image (radians) |
|
float area; // common image area relative to the reference image (ratio) |
|
float score; // aggregated image score relative to the reference image (larger is better) |
|
|
|
template<class Archive> |
|
void serialize(Archive& ar, const unsigned int /*version*/) { |
|
ar & ID; |
|
ar & points; |
|
ar & scale; |
|
ar & angle; |
|
ar & area; |
|
ar & score; |
|
} |
|
}; |
|
|
|
std::string name; // image file name |
|
std::string maskName; // segmentation file name (optional) |
|
uint32_t platformID; // ID of the associated platform |
|
uint32_t cameraID; // ID of the associated camera on the associated platform |
|
uint32_t poseID; // ID of the pose of the associated platform |
|
uint32_t ID; // image global-ID, ex. the ID given outside the current scene, like the index in the full list of image files (optional) |
|
float minDepth; // minimum depth of the points seen by this image (optional) |
|
float avgDepth; // average depth of the points seen by this image (optional) |
|
float maxDepth; // maximum depth of the points seen by this image (optional) |
|
std::vector<ViewScore> viewScores; // list of view scores for this image (optional) |
|
|
|
Image() : platformID(NO_ID), cameraID(NO_ID), poseID(NO_ID), ID(NO_ID), minDepth(0), avgDepth(0), maxDepth(0) {} |
|
|
|
bool IsValid() const { return poseID != NO_ID; } |
|
|
|
template <class Archive> |
|
void serialize(Archive& ar, const unsigned int version) { |
|
ar & name; |
|
if (version > 4) { |
|
ar & maskName; |
|
} |
|
ar & platformID; |
|
ar & cameraID; |
|
ar & poseID; |
|
if (version > 2) { |
|
ar & ID; |
|
} |
|
if (version > 6) { |
|
ar & minDepth; |
|
ar & avgDepth; |
|
ar & maxDepth; |
|
ar & viewScores; |
|
} |
|
} |
|
}; |
|
typedef std::vector<Image> ImageArr; |
|
/*----------------------------------------------------------------*/ |
|
|
|
// structure describing a 3D point |
|
struct Vertex { |
|
// structure describing one view for a given 3D feature |
|
struct View { |
|
uint32_t imageID; // image ID corresponding to this view |
|
float confidence; // view's confidence (0 - not available) |
|
|
|
template<class Archive> |
|
void serialize(Archive& ar, const unsigned int /*version*/) { |
|
ar & imageID; |
|
ar & confidence; |
|
} |
|
}; |
|
typedef std::vector<View> ViewArr; |
|
|
|
Pos3f X; // 3D point position |
|
ViewArr views; // list of all available views for this 3D feature |
|
|
|
template <class Archive> |
|
void serialize(Archive& ar, const unsigned int /*version*/) { |
|
ar & X; |
|
ar & views; |
|
} |
|
}; |
|
typedef std::vector<Vertex> VertexArr; |
|
/*----------------------------------------------------------------*/ |
|
|
|
// structure describing a 3D line |
|
struct Line { |
|
// structure describing one view for a given 3D feature |
|
struct View { |
|
uint32_t imageID; // image ID corresponding to this view |
|
float confidence; // view's confidence (0 - not available) |
|
|
|
template<class Archive> |
|
void serialize(Archive& ar, const unsigned int /*version*/) { |
|
ar & imageID; |
|
ar & confidence; |
|
} |
|
}; |
|
typedef std::vector<View> ViewArr; |
|
|
|
Pos3f pt1; // 3D line segment end-point |
|
Pos3f pt2; // 3D line segment end-point |
|
ViewArr views; // list of all available views for this 3D feature |
|
|
|
template <class Archive> |
|
void serialize(Archive& ar, const unsigned int /*version*/) { |
|
ar & pt1; |
|
ar & pt2; |
|
ar & views; |
|
} |
|
}; |
|
typedef std::vector<Line> LineArr; |
|
/*----------------------------------------------------------------*/ |
|
|
|
// structure describing a 3D point's normal (optional) |
|
struct Normal { |
|
Pos3f n; // 3D feature normal |
|
|
|
template <class Archive> |
|
void serialize(Archive& ar, const unsigned int /*version*/) { |
|
ar & n; |
|
} |
|
}; |
|
typedef std::vector<Normal> NormalArr; |
|
/*----------------------------------------------------------------*/ |
|
|
|
// structure describing a 3D point's color (optional) |
|
struct Color { |
|
Col3 c; // 3D feature color |
|
|
|
template <class Archive> |
|
void serialize(Archive& ar, const unsigned int /*version*/) { |
|
ar & c; |
|
} |
|
}; |
|
typedef std::vector<Color> ColorArr; |
|
/*----------------------------------------------------------------*/ |
|
|
|
// structure describing a Oriented Bounding-Box (optional) |
|
struct OBB { |
|
Mat33d rot; // rotation from scene to OBB coordinate system |
|
Pos3d ptMin; // minimal point represented in OBB coordinate system |
|
Pos3d ptMax; // maximal point represented in OBB coordinate system |
|
|
|
OBB() : rot(Mat33d::eye()), ptMin(0, 0, 0), ptMax(0, 0, 0) {} |
|
|
|
bool IsValid() const { return ptMin.x < ptMax.x && ptMin.y < ptMax.y && ptMin.z < ptMax.z; } |
|
|
|
template <class Archive> |
|
void serialize(Archive& ar, const unsigned int /*version*/) { |
|
ar & rot; |
|
ar & ptMin; |
|
ar & ptMax; |
|
} |
|
}; |
|
/*----------------------------------------------------------------*/ |
|
|
|
PlatformArr platforms; // array of platforms |
|
ImageArr images; // array of images |
|
VertexArr vertices; // array of reconstructed 3D points |
|
NormalArr verticesNormal; // array of reconstructed 3D points' normal (optional) |
|
ColorArr verticesColor; // array of reconstructed 3D points' color (optional) |
|
LineArr lines; // array of reconstructed 3D lines (optional) |
|
NormalArr linesNormal; // array of reconstructed 3D lines' normal (optional) |
|
ColorArr linesColor; // array of reconstructed 3D lines' color (optional) |
|
Mat44d transform; // transformation used to convert from absolute to relative coordinate system (optional) |
|
OBB obb; // minimum oriented bounding box containing the scene (optional) |
|
|
|
Interface() : transform(Mat44d::eye()) {} |
|
|
|
const Mat33d& GetK(uint32_t imageID) const { |
|
const Image& image = images[imageID]; |
|
return platforms[image.platformID].GetK(image.cameraID); |
|
} |
|
Mat33d GetFullK(uint32_t imageID, uint32_t width, uint32_t height) const { |
|
const Image& image = images[imageID]; |
|
return platforms[image.platformID].GetFullK(image.cameraID, width, height); |
|
} |
|
|
|
const Platform::Camera& GetCamera(uint32_t imageID) const { |
|
const Image& image = images[imageID]; |
|
return platforms[image.platformID].cameras[image.cameraID]; |
|
} |
|
|
|
Platform::Pose GetPose(uint32_t imageID) const { |
|
const Image& image = images[imageID]; |
|
return platforms[image.platformID].GetPose(image.cameraID, image.poseID); |
|
} |
|
|
|
// apply similarity transform |
|
void Transform(const Mat33d& rotation, const Pos3d& translation, const double scale) { |
|
for (Platform& platform : platforms) { |
|
for (Platform::Pose& pose : platform.poses) { |
|
pose.R = pose.R * rotation.t(); |
|
pose.C = rotation * pose.C * scale + translation; |
|
} |
|
} |
|
for (Vertex& vertex : vertices) { |
|
vertex.X = rotation * Pos3d(vertex.X) * scale + translation; |
|
} |
|
for (Normal& normal : verticesNormal) { |
|
normal.n = rotation * Pos3d(normal.n); |
|
} |
|
for (Line& line : lines) { |
|
line.pt1 = rotation * Pos3d(line.pt1) * scale + translation; |
|
line.pt2 = rotation * Pos3d(line.pt2) * scale + translation; |
|
} |
|
for (Normal& normal : linesNormal) { |
|
normal.n = rotation * Pos3d(normal.n); |
|
} |
|
} |
|
|
|
template <class Archive> |
|
void serialize(Archive& ar, const unsigned int version) { |
|
ar & platforms; |
|
ar & images; |
|
ar & vertices; |
|
ar & verticesNormal; |
|
ar & verticesColor; |
|
if (version > 0) { |
|
ar & lines; |
|
ar & linesNormal; |
|
ar & linesColor; |
|
if (version > 1) { |
|
ar & transform; |
|
if (version > 5) { |
|
ar & obb; |
|
} |
|
} |
|
} |
|
} |
|
}; |
|
/*----------------------------------------------------------------*/ |
|
|
|
|
|
// interface used to export/import MVS depth-map data; |
|
// see MVS::ExportDepthDataRaw() and MVS::ImportDepthDataRaw() for usage example: |
|
// - image-resolution at which the depth-map was estimated |
|
// - depth-map-resolution, for now only the same resolution as the image is supported |
|
// - min/max-depth of the values in the depth-map |
|
// - image-file-name is the path to the reference color image |
|
// - image-IDs are the reference view ID and neighbor view IDs used to estimate the depth-map (global ID) |
|
// - camera/rotation/position matrices (row-major) is the absolute pose corresponding to the reference view |
|
// - depth-map: the pixels' depth |
|
// - normal-map (optional): the 3D point normal in camera space; same resolution as the depth-map |
|
// - confidence-map (optional): the 3D point confidence (usually a value in [0,1]); same resolution as the depth-map |
|
// - views-map (optional): the pixels' views, indexing image-IDs starting after first view (up to 4); same resolution as the depth-map |
|
struct HeaderDepthDataRaw { |
|
enum { |
|
HAS_DEPTH = (1<<0), |
|
HAS_NORMAL = (1<<1), |
|
HAS_CONF = (1<<2), |
|
HAS_VIEWS = (1<<3), |
|
}; |
|
uint16_t name; // file type |
|
uint8_t type; // content type |
|
uint8_t padding; // reserve |
|
uint32_t imageWidth, imageHeight; // image resolution |
|
uint32_t depthWidth, depthHeight; // depth-map resolution |
|
float dMin, dMax; // depth range for this view |
|
// image file name length followed by the characters: uint16_t nFileNameSize; char* FileName |
|
// number of view IDs followed by view ID and neighbor view IDs: uint32_t nIDs; uint32_t* IDs |
|
// camera, rotation and position matrices (row-major) at image resolution: double K[3][3], R[3][3], C[3] |
|
// depth, normal, confidence maps: float depthMap[height][width], normalMap[height][width][3], confMap[height][width] |
|
inline HeaderDepthDataRaw() : name(0), type(0), padding(0) {} |
|
static uint16_t HeaderDepthDataRawName() { return *reinterpret_cast<const uint16_t*>("DR"); } |
|
}; |
|
/*----------------------------------------------------------------*/ |
|
|
|
} // namespace _INTERFACE_NAMESPACE |
|
|
|
#endif // _INTERFACE_MVS_H_
|
|
|