From 40de3b1a39c663c6725fb03d1290c34c6d426b9a Mon Sep 17 00:00:00 2001 From: geoffrey Date: Fri, 26 Jul 2019 13:29:15 +0100 Subject: [PATCH 01/16] Adding re-texturing option: allows to backup and reuse the atlas to re-texture the mesh later using the same UV's --- apps/TextureMesh/TextureMesh.cpp | 4 +- libs/MVS/Scene.h | 2 +- libs/MVS/SceneTexture.cpp | 185 ++++++++++++++++++++++++++++++- 3 files changed, 185 insertions(+), 6 deletions(-) diff --git a/apps/TextureMesh/TextureMesh.cpp b/apps/TextureMesh/TextureMesh.cpp index 9e610a8ba..d7ea10813 100644 --- a/apps/TextureMesh/TextureMesh.cpp +++ b/apps/TextureMesh/TextureMesh.cpp @@ -53,6 +53,7 @@ float fOutlierThreshold; float fRatioDataSmoothness; bool bGlobalSeamLeveling; bool bLocalSeamLeveling; +bool reTexture; unsigned nTextureSizeMultiple; unsigned nRectPackingHeuristic; uint32_t nColEmpty; @@ -104,6 +105,7 @@ bool Initialize(size_t argc, LPCTSTR* argv) ("cost-smoothness-ratio", boost::program_options::value(&OPT::fRatioDataSmoothness)->default_value(0.1f), "ratio used to adjust the preference for more compact patches (1 - best quality/worst compactness, ~0 - worst quality/best compactness)") ("global-seam-leveling", boost::program_options::value(&OPT::bGlobalSeamLeveling)->default_value(true), "generate uniform texture patches using global seam leveling") ("local-seam-leveling", boost::program_options::value(&OPT::bLocalSeamLeveling)->default_value(true), "generate uniform texture patch borders using local seam leveling") + ("re-texture", boost::program_options::value(&OPT::reTexture)->default_value(false), "generate texture using previous atlas") ("texture-size-multiple", boost::program_options::value(&OPT::nTextureSizeMultiple)->default_value(0), "texture size should be a multiple of this value (0 - power of two)") ("patch-packing-heuristic", boost::program_options::value(&OPT::nRectPackingHeuristic)->default_value(3), "specify the heuristic used when deciding where to place a new patch (0 - best fit, 3 - good speed, 100 - best speed)") ("empty-color", boost::program_options::value(&OPT::nColEmpty)->default_value(0x00FF7F27), "color used for faces not covered by any image") @@ -228,7 +230,7 @@ int main(int argc, LPCTSTR* argv) { // compute mesh texture TD_TIMER_START(); - if (!scene.TextureMesh(OPT::nResolutionLevel, OPT::nMinResolution, OPT::fOutlierThreshold, OPT::fRatioDataSmoothness, OPT::bGlobalSeamLeveling, OPT::bLocalSeamLeveling, OPT::nTextureSizeMultiple, OPT::nRectPackingHeuristic, Pixel8U(OPT::nColEmpty))) + if (!scene.TextureMesh(OPT::nResolutionLevel, OPT::nMinResolution, OPT::fOutlierThreshold, OPT::fRatioDataSmoothness, OPT::bGlobalSeamLeveling, OPT::bLocalSeamLeveling, OPT::nTextureSizeMultiple, OPT::nRectPackingHeuristic, Pixel8U(OPT::nColEmpty), OPT::reTexture)) return EXIT_FAILURE; VERBOSE("Mesh texturing completed: %u vertices, %u faces (%s)", scene.mesh.vertices.GetSize(), scene.mesh.faces.GetSize(), TD_TIMER_GET_FMT().c_str()); diff --git a/libs/MVS/Scene.h b/libs/MVS/Scene.h index 581ad120e..4c6c66ec5 100644 --- a/libs/MVS/Scene.h +++ b/libs/MVS/Scene.h @@ -96,7 +96,7 @@ class MVS_API Scene #endif // Mesh texturing - bool TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, float fOutlierThreshold=0.f, float fRatioDataSmoothness=0.3f, bool bGlobalSeamLeveling=true, bool bLocalSeamLeveling=true, unsigned nTextureSizeMultiple=0, unsigned nRectPackingHeuristic=3, Pixel8U colEmpty=Pixel8U(255,127,39)); + bool TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, float fOutlierThreshold=0.f, float fRatioDataSmoothness=0.3f, bool bGlobalSeamLeveling=true, bool bLocalSeamLeveling=true, unsigned nTextureSizeMultiple=0, unsigned nRectPackingHeuristic=3, Pixel8U colEmpty=Pixel8U(255,127,39), bool reTexture=false); #ifdef _USE_BOOST // implement BOOST serialization diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index 400616c5c..cc366ca74 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -37,7 +37,11 @@ #include #include +#include +#include + using namespace MVS; +using namespace std; // D E F I N E S /////////////////////////////////////////////////// @@ -194,6 +198,17 @@ struct MeshTexture { Label label; // view index Mesh::FaceIdxArr faces; // indices of the faces contained by the patch RectsBinPack::Rect rect; // the bounding box in the view containing the patch + + #ifdef _USE_BOOST + // implement BOOST serialization + template + void serialize(Archive& ar, const unsigned int /*version*/) { + ar & label; + ar & faces; + ar & rect; + } + #endif + }; typedef cList TexturePatchArr; @@ -209,6 +224,16 @@ struct MeshTexture { inline bool operator == (uint32_t _idxSeamVertex) const { return (idxSeamVertex == _idxSeamVertex); } + + #ifdef _USE_BOOST + // implement BOOST serialization + template + void serialize(Archive& ar, const unsigned int /*version*/) { + ar & idxSeamVertex; + ar & idxFace; + } + #endif + }; typedef cList Edges; @@ -221,6 +246,17 @@ struct MeshTexture { inline bool operator == (uint32_t _idxPatch) const { return (idxPatch == _idxPatch); } + + #ifdef _USE_BOOST + // implement BOOST serialization + template + void serialize(Archive& ar, const unsigned int /*version*/) { + ar & idxPatch; + ar & proj; + ar & edges; + } + #endif + }; typedef cList Patches; @@ -245,6 +281,16 @@ struct MeshTexture { return patches[i0].idxPatch < patches[i1].idxPatch; }); } + + #ifdef _USE_BOOST + // implement BOOST serialization + template + void serialize(Archive& ar, const unsigned int /*version*/) { + ar & idxVertex; + ar & patches; + } + #endif + }; typedef cList SeamVertices; @@ -384,12 +430,14 @@ struct MeshTexture { bool FaceOutlierDetection(FaceDataArr& faceDatas, float fOutlierThreshold) const; #endif + void BkpTexture(); + void LoadBkpTexture(); bool FaceViewSelection(float fOutlierThreshold, float fRatioDataSmoothness); void CreateSeamVertices(); void GlobalSeamLeveling(); void LocalSeamLeveling(); - void GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty); + void GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty, bool reTexture); template static inline PIXEL RGB2YCBCR(const PIXEL& v) { @@ -825,6 +873,93 @@ bool MeshTexture::FaceOutlierDetection(FaceDataArr& faceDatas, float thOutlier) } #endif +// backup variables before global seam leveling +void MeshTexture::BkpTexture() +{ + // create backup directory + if (mkdir("atlas_backup", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) + { + if( errno == EEXIST ) { + // alredy exists + } else { + // something else + ABORT("cannot create sessionnamefolder error:" << strerror(errno)); + } + } + + ofstream ofscomponents("atlas_backup/components"); + { + boost::archive::text_oarchive oa(ofscomponents); + oa << components; + } + + ofstream ofsmapIdxPatch("atlas_backup/mapIdxPatch"); + { + boost::archive::text_oarchive oa(ofsmapIdxPatch); + oa << mapIdxPatch; + } + + ofstream ofsseamVertices("atlas_backup/seamVertices"); + { + boost::archive::text_oarchive oa(ofsseamVertices); + oa << seamVertices; + } + + ofstream ofstexturePatches("atlas_backup/texturePatches"); + { + boost::archive::text_oarchive oa(ofstexturePatches); + oa << texturePatches; + } + + ofstream ofsscene("atlas_backup/scene"); + { + boost::archive::text_oarchive oa(ofsscene); + oa << scene; + } +} + + +// load backed-up variables for global seam leveling +void MeshTexture::LoadBkpTexture() +{ + { + // empty variable + seamVertices.Empty(); + // open an archive for input + std::ifstream ifs("atlas_backup/seamVertices"); + boost::archive::text_iarchive ia(ifs); + // read class state from archive + ia >> seamVertices; + } + + { + components.Empty(); + std::ifstream ifs("atlas_backup/components"); + boost::archive::text_iarchive ia(ifs); + ia >> components; + } + + { + mapIdxPatch.Empty(); + std::ifstream ifs("atlas_backup/mapIdxPatch"); + boost::archive::text_iarchive ia(ifs); + ia >> mapIdxPatch; + } + + { + texturePatches.Empty(); + std::ifstream ifs("atlas_backup/texturePatches"); + boost::archive::text_iarchive ia(ifs); + ia >> texturePatches; + } + + { + std::ifstream ifs("atlas_backup/scene"); + boost::archive::text_iarchive ia(ifs); + ia >> scene; + } +} + bool MeshTexture::FaceViewSelection(float fOutlierThreshold, float fRatioDataSmoothness) { // extract array of triangles incident to each vertex @@ -1784,7 +1919,7 @@ void MeshTexture::LocalSeamLeveling() } } -void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty) +void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty, bool reTexture) { // project patches in the corresponding view and compute texture-coordinates and bounding-box const int border(2); @@ -1846,6 +1981,12 @@ void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLevel // create seam vertices and edges CreateSeamVertices(); + if(reTexture ==0){ + BkpTexture(); + }else{ + LoadBkpTexture(); + } + // perform global seam leveling if (bGlobalSeamLeveling) { TD_TIMER_STARTD(); @@ -1927,6 +2068,42 @@ void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLevel const float invNorm(1.f/(float)(textureSize-1)); textureDiffuse.create(textureSize, textureSize); textureDiffuse.setTo(cv::Scalar(colEmpty.b, colEmpty.g, colEmpty.r)); + + // backup patches/atlas + if(reTexture ==0){ + ofstream ofsrects("atlas_backup/rects"); + // save data to archive + { + boost::archive::text_oarchive oa(ofsrects); + oa << rects; + } + + ofstream ofstexturePatchesFINAL("atlas_backup/texturePatchesFINAL"); + { + boost::archive::text_oarchive oa(ofstexturePatchesFINAL); + // write class instance to archive + oa << texturePatches; + } + }else{ + // load backed-up patches/atlas + { + rects.Empty(); + // open an archive for input + std::ifstream ifs("atlas_backup/rects"); + boost::archive::text_iarchive ia(ifs); + // read class state from archive + ia >> rects; + } + { + texturePatches.Empty(); + // open an archive for input + std::ifstream ifs("atlas_backup/texturePatchesFINAL"); + boost::archive::text_iarchive ia(ifs); + // read class state from archive + ia >> texturePatches; + } + } + #ifdef TEXOPT_USE_OPENMP #pragma omp parallel for schedule(dynamic) for (int_t i=0; i<(int_t)texturePatches.GetSize(); ++i) { @@ -1969,7 +2146,7 @@ void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLevel } // texture mesh -bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, float fOutlierThreshold, float fRatioDataSmoothness, bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty) +bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, float fOutlierThreshold, float fRatioDataSmoothness, bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty, bool reTexture) { MeshTexture texture(*this, nResolutionLevel, nMinResolution); @@ -1984,7 +2161,7 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, floa // generate the texture image and atlas { TD_TIMER_STARTD(); - texture.GenerateTexture(bGlobalSeamLeveling, bLocalSeamLeveling, nTextureSizeMultiple, nRectPackingHeuristic, colEmpty); + texture.GenerateTexture(bGlobalSeamLeveling, bLocalSeamLeveling, nTextureSizeMultiple, nRectPackingHeuristic, colEmpty, reTexture); DEBUG_EXTRA("Generating texture atlas and image completed: %u patches, %u image size (%s)", texture.texturePatches.GetSize(), mesh.textureDiffuse.width(), TD_TIMER_GET_FMT().c_str()); } From 8fa1a85092d881745f396f379a5b6bd34495531b Mon Sep 17 00:00:00 2001 From: geoffrey Date: Fri, 26 Jul 2019 13:29:15 +0100 Subject: [PATCH 02/16] Adding re-texturing option: allows to backup and reuse the atlas to re-texture the mesh later using the same UV's --- apps/TextureMesh/TextureMesh.cpp | 4 +- libs/MVS/Scene.h | 2 +- libs/MVS/SceneTexture.cpp | 190 ++++++++++++++++++++++++++++++- 3 files changed, 190 insertions(+), 6 deletions(-) diff --git a/apps/TextureMesh/TextureMesh.cpp b/apps/TextureMesh/TextureMesh.cpp index 9e610a8ba..d7ea10813 100644 --- a/apps/TextureMesh/TextureMesh.cpp +++ b/apps/TextureMesh/TextureMesh.cpp @@ -53,6 +53,7 @@ float fOutlierThreshold; float fRatioDataSmoothness; bool bGlobalSeamLeveling; bool bLocalSeamLeveling; +bool reTexture; unsigned nTextureSizeMultiple; unsigned nRectPackingHeuristic; uint32_t nColEmpty; @@ -104,6 +105,7 @@ bool Initialize(size_t argc, LPCTSTR* argv) ("cost-smoothness-ratio", boost::program_options::value(&OPT::fRatioDataSmoothness)->default_value(0.1f), "ratio used to adjust the preference for more compact patches (1 - best quality/worst compactness, ~0 - worst quality/best compactness)") ("global-seam-leveling", boost::program_options::value(&OPT::bGlobalSeamLeveling)->default_value(true), "generate uniform texture patches using global seam leveling") ("local-seam-leveling", boost::program_options::value(&OPT::bLocalSeamLeveling)->default_value(true), "generate uniform texture patch borders using local seam leveling") + ("re-texture", boost::program_options::value(&OPT::reTexture)->default_value(false), "generate texture using previous atlas") ("texture-size-multiple", boost::program_options::value(&OPT::nTextureSizeMultiple)->default_value(0), "texture size should be a multiple of this value (0 - power of two)") ("patch-packing-heuristic", boost::program_options::value(&OPT::nRectPackingHeuristic)->default_value(3), "specify the heuristic used when deciding where to place a new patch (0 - best fit, 3 - good speed, 100 - best speed)") ("empty-color", boost::program_options::value(&OPT::nColEmpty)->default_value(0x00FF7F27), "color used for faces not covered by any image") @@ -228,7 +230,7 @@ int main(int argc, LPCTSTR* argv) { // compute mesh texture TD_TIMER_START(); - if (!scene.TextureMesh(OPT::nResolutionLevel, OPT::nMinResolution, OPT::fOutlierThreshold, OPT::fRatioDataSmoothness, OPT::bGlobalSeamLeveling, OPT::bLocalSeamLeveling, OPT::nTextureSizeMultiple, OPT::nRectPackingHeuristic, Pixel8U(OPT::nColEmpty))) + if (!scene.TextureMesh(OPT::nResolutionLevel, OPT::nMinResolution, OPT::fOutlierThreshold, OPT::fRatioDataSmoothness, OPT::bGlobalSeamLeveling, OPT::bLocalSeamLeveling, OPT::nTextureSizeMultiple, OPT::nRectPackingHeuristic, Pixel8U(OPT::nColEmpty), OPT::reTexture)) return EXIT_FAILURE; VERBOSE("Mesh texturing completed: %u vertices, %u faces (%s)", scene.mesh.vertices.GetSize(), scene.mesh.faces.GetSize(), TD_TIMER_GET_FMT().c_str()); diff --git a/libs/MVS/Scene.h b/libs/MVS/Scene.h index 581ad120e..4c6c66ec5 100644 --- a/libs/MVS/Scene.h +++ b/libs/MVS/Scene.h @@ -96,7 +96,7 @@ class MVS_API Scene #endif // Mesh texturing - bool TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, float fOutlierThreshold=0.f, float fRatioDataSmoothness=0.3f, bool bGlobalSeamLeveling=true, bool bLocalSeamLeveling=true, unsigned nTextureSizeMultiple=0, unsigned nRectPackingHeuristic=3, Pixel8U colEmpty=Pixel8U(255,127,39)); + bool TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, float fOutlierThreshold=0.f, float fRatioDataSmoothness=0.3f, bool bGlobalSeamLeveling=true, bool bLocalSeamLeveling=true, unsigned nTextureSizeMultiple=0, unsigned nRectPackingHeuristic=3, Pixel8U colEmpty=Pixel8U(255,127,39), bool reTexture=false); #ifdef _USE_BOOST // implement BOOST serialization diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index 400616c5c..c0ce9ab27 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -37,7 +37,11 @@ #include #include +#include +#include + using namespace MVS; +using namespace std; // D E F I N E S /////////////////////////////////////////////////// @@ -194,6 +198,17 @@ struct MeshTexture { Label label; // view index Mesh::FaceIdxArr faces; // indices of the faces contained by the patch RectsBinPack::Rect rect; // the bounding box in the view containing the patch + + #ifdef _USE_BOOST + // implement BOOST serialization + template + void serialize(Archive& ar, const unsigned int /*version*/) { + ar & label; + ar & faces; + ar & rect; + } + #endif + }; typedef cList TexturePatchArr; @@ -209,6 +224,16 @@ struct MeshTexture { inline bool operator == (uint32_t _idxSeamVertex) const { return (idxSeamVertex == _idxSeamVertex); } + + #ifdef _USE_BOOST + // implement BOOST serialization + template + void serialize(Archive& ar, const unsigned int /*version*/) { + ar & idxSeamVertex; + ar & idxFace; + } + #endif + }; typedef cList Edges; @@ -221,6 +246,17 @@ struct MeshTexture { inline bool operator == (uint32_t _idxPatch) const { return (idxPatch == _idxPatch); } + + #ifdef _USE_BOOST + // implement BOOST serialization + template + void serialize(Archive& ar, const unsigned int /*version*/) { + ar & idxPatch; + ar & proj; + ar & edges; + } + #endif + }; typedef cList Patches; @@ -245,6 +281,16 @@ struct MeshTexture { return patches[i0].idxPatch < patches[i1].idxPatch; }); } + + #ifdef _USE_BOOST + // implement BOOST serialization + template + void serialize(Archive& ar, const unsigned int /*version*/) { + ar & idxVertex; + ar & patches; + } + #endif + }; typedef cList SeamVertices; @@ -384,12 +430,14 @@ struct MeshTexture { bool FaceOutlierDetection(FaceDataArr& faceDatas, float fOutlierThreshold) const; #endif + void BkpTexture(); + void LoadBkpTexture(); bool FaceViewSelection(float fOutlierThreshold, float fRatioDataSmoothness); void CreateSeamVertices(); void GlobalSeamLeveling(); void LocalSeamLeveling(); - void GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty); + void GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty, bool reTexture); template static inline PIXEL RGB2YCBCR(const PIXEL& v) { @@ -825,6 +873,98 @@ bool MeshTexture::FaceOutlierDetection(FaceDataArr& faceDatas, float thOutlier) } #endif +// backup variables before global seam leveling +void MeshTexture::BkpTexture() +{ + + // create backup directory + #if defined(_WIN32) + if (_mkdir("atlas_backup") == -1) // can be used on Windows + #else + if (mkdir("atlas_backup", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) // can be used on non-Windows + #endif + { + if( errno == EEXIST ) { + // alredy exists + } else { + // something else + ABORT("cannot create sessionnamefolder error:" << strerror(errno)); + } + } + + ofstream ofscomponents("atlas_backup/components"); + { + boost::archive::text_oarchive oa(ofscomponents); + oa << components; + } + + ofstream ofsmapIdxPatch("atlas_backup/mapIdxPatch"); + { + boost::archive::text_oarchive oa(ofsmapIdxPatch); + oa << mapIdxPatch; + } + + ofstream ofsseamVertices("atlas_backup/seamVertices"); + { + boost::archive::text_oarchive oa(ofsseamVertices); + oa << seamVertices; + } + + ofstream ofstexturePatches("atlas_backup/texturePatches"); + { + boost::archive::text_oarchive oa(ofstexturePatches); + oa << texturePatches; + } + + ofstream ofsscene("atlas_backup/scene"); + { + boost::archive::text_oarchive oa(ofsscene); + oa << scene; + } +} + + +// load backed-up variables for global seam leveling +void MeshTexture::LoadBkpTexture() +{ + { + // empty variable + seamVertices.Empty(); + // open an archive for input + std::ifstream ifs("atlas_backup/seamVertices"); + boost::archive::text_iarchive ia(ifs); + // read class state from archive + ia >> seamVertices; + } + + { + components.Empty(); + std::ifstream ifs("atlas_backup/components"); + boost::archive::text_iarchive ia(ifs); + ia >> components; + } + + { + mapIdxPatch.Empty(); + std::ifstream ifs("atlas_backup/mapIdxPatch"); + boost::archive::text_iarchive ia(ifs); + ia >> mapIdxPatch; + } + + { + texturePatches.Empty(); + std::ifstream ifs("atlas_backup/texturePatches"); + boost::archive::text_iarchive ia(ifs); + ia >> texturePatches; + } + + { + std::ifstream ifs("atlas_backup/scene"); + boost::archive::text_iarchive ia(ifs); + ia >> scene; + } +} + bool MeshTexture::FaceViewSelection(float fOutlierThreshold, float fRatioDataSmoothness) { // extract array of triangles incident to each vertex @@ -1784,7 +1924,7 @@ void MeshTexture::LocalSeamLeveling() } } -void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty) +void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty, bool reTexture) { // project patches in the corresponding view and compute texture-coordinates and bounding-box const int border(2); @@ -1846,6 +1986,12 @@ void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLevel // create seam vertices and edges CreateSeamVertices(); + if(reTexture ==0){ + BkpTexture(); + }else{ + LoadBkpTexture(); + } + // perform global seam leveling if (bGlobalSeamLeveling) { TD_TIMER_STARTD(); @@ -1927,6 +2073,42 @@ void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLevel const float invNorm(1.f/(float)(textureSize-1)); textureDiffuse.create(textureSize, textureSize); textureDiffuse.setTo(cv::Scalar(colEmpty.b, colEmpty.g, colEmpty.r)); + + // backup patches/atlas + if(reTexture ==0){ + ofstream ofsrects("atlas_backup/rects"); + // save data to archive + { + boost::archive::text_oarchive oa(ofsrects); + oa << rects; + } + + ofstream ofstexturePatchesFINAL("atlas_backup/texturePatchesFINAL"); + { + boost::archive::text_oarchive oa(ofstexturePatchesFINAL); + // write class instance to archive + oa << texturePatches; + } + }else{ + // load backed-up patches/atlas + { + rects.Empty(); + // open an archive for input + std::ifstream ifs("atlas_backup/rects"); + boost::archive::text_iarchive ia(ifs); + // read class state from archive + ia >> rects; + } + { + texturePatches.Empty(); + // open an archive for input + std::ifstream ifs("atlas_backup/texturePatchesFINAL"); + boost::archive::text_iarchive ia(ifs); + // read class state from archive + ia >> texturePatches; + } + } + #ifdef TEXOPT_USE_OPENMP #pragma omp parallel for schedule(dynamic) for (int_t i=0; i<(int_t)texturePatches.GetSize(); ++i) { @@ -1969,7 +2151,7 @@ void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLevel } // texture mesh -bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, float fOutlierThreshold, float fRatioDataSmoothness, bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty) +bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, float fOutlierThreshold, float fRatioDataSmoothness, bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty, bool reTexture) { MeshTexture texture(*this, nResolutionLevel, nMinResolution); @@ -1984,7 +2166,7 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, floa // generate the texture image and atlas { TD_TIMER_STARTD(); - texture.GenerateTexture(bGlobalSeamLeveling, bLocalSeamLeveling, nTextureSizeMultiple, nRectPackingHeuristic, colEmpty); + texture.GenerateTexture(bGlobalSeamLeveling, bLocalSeamLeveling, nTextureSizeMultiple, nRectPackingHeuristic, colEmpty, reTexture); DEBUG_EXTRA("Generating texture atlas and image completed: %u patches, %u image size (%s)", texture.texturePatches.GetSize(), mesh.textureDiffuse.width(), TD_TIMER_GET_FMT().c_str()); } From 410551bf920d4b23ab454df3314efb9426cdffb8 Mon Sep 17 00:00:00 2001 From: geoffrey Date: Fri, 26 Jul 2019 16:21:08 +0100 Subject: [PATCH 03/16] Adding re-texturing option: allows to backup and reuse the atlas to re-texture the mesh later using the same UV's - fix forwin32 path creation --- libs/MVS/SceneTexture.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index c0ce9ab27..2daed7007 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -876,6 +876,7 @@ bool MeshTexture::FaceOutlierDetection(FaceDataArr& faceDatas, float thOutlier) // backup variables before global seam leveling void MeshTexture::BkpTexture() { +<<<<<<< HEAD // create backup directory #if defined(_WIN32) @@ -883,6 +884,10 @@ void MeshTexture::BkpTexture() #else if (mkdir("atlas_backup", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) // can be used on non-Windows #endif +======= + // create backup directory + if (mkdir("atlas_backup", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) +>>>>>>> 40de3b1a39c663c6725fb03d1290c34c6d426b9a { if( errno == EEXIST ) { // alredy exists From 5990f87a2967a818647f5c586639dfda0ea3f4c0 Mon Sep 17 00:00:00 2001 From: geoffrey Date: Fri, 26 Jul 2019 16:28:23 +0100 Subject: [PATCH 04/16] Adding re-texturing option: allows to backup and reuse the atlas to re-texture the mesh later using the same UV's - fix forwin32 path creation -sorry for the mess... --- libs/MVS/SceneTexture.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index 2daed7007..c324e2bb2 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -876,7 +876,6 @@ bool MeshTexture::FaceOutlierDetection(FaceDataArr& faceDatas, float thOutlier) // backup variables before global seam leveling void MeshTexture::BkpTexture() { -<<<<<<< HEAD // create backup directory #if defined(_WIN32) @@ -884,10 +883,7 @@ void MeshTexture::BkpTexture() #else if (mkdir("atlas_backup", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) // can be used on non-Windows #endif -======= // create backup directory - if (mkdir("atlas_backup", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) ->>>>>>> 40de3b1a39c663c6725fb03d1290c34c6d426b9a { if( errno == EEXIST ) { // alredy exists From e56a9eb8ff88e6e1a898c8c281670831964988c2 Mon Sep 17 00:00:00 2001 From: geoffrey Date: Fri, 26 Jul 2019 16:28:23 +0100 Subject: [PATCH 05/16] Adding re-texturing option: allows to backup and reuse the atlas to re-texture the mesh later using the same UV's - fix forwin32 path creation -sorry for the mess... --- libs/MVS/SceneTexture.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index 2daed7007..c324e2bb2 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -876,7 +876,6 @@ bool MeshTexture::FaceOutlierDetection(FaceDataArr& faceDatas, float thOutlier) // backup variables before global seam leveling void MeshTexture::BkpTexture() { -<<<<<<< HEAD // create backup directory #if defined(_WIN32) @@ -884,10 +883,7 @@ void MeshTexture::BkpTexture() #else if (mkdir("atlas_backup", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) // can be used on non-Windows #endif -======= // create backup directory - if (mkdir("atlas_backup", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) ->>>>>>> 40de3b1a39c663c6725fb03d1290c34c6d426b9a { if( errno == EEXIST ) { // alredy exists From 3080a280b4167ed4c72e3cf64fc383bd7793df87 Mon Sep 17 00:00:00 2001 From: geoffrey Date: Fri, 26 Jul 2019 17:54:02 +0100 Subject: [PATCH 06/16] Adding re-texturing option: allows to backup and reuse the atlas to re-texture the mesh later using the same UV's - fix for win32 path creation. 2nd attempt --- libs/MVS/SceneTexture.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index c324e2bb2..0040a9f02 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -39,6 +39,9 @@ #include #include +#ifdef defined(_WIN32) || defined(WIN32) +#include +#endif using namespace MVS; using namespace std; @@ -878,7 +881,7 @@ void MeshTexture::BkpTexture() { // create backup directory - #if defined(_WIN32) + #if (defined(_WIN32) || defined(WIN32)) if (_mkdir("atlas_backup") == -1) // can be used on Windows #else if (mkdir("atlas_backup", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) // can be used on non-Windows From 4237d6456b24a23c4e2a6497b3cc53d9aabc2047 Mon Sep 17 00:00:00 2001 From: geoffrey Date: Sat, 27 Jul 2019 14:24:42 +0100 Subject: [PATCH 07/16] Adding re-texturing option: allows to backup and reuse the atlas to re-texture the mesh later using the same UV's - fix for win32 path creation. 3rd attempt --- libs/MVS/SceneTexture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index 0040a9f02..f768ca988 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -40,7 +40,7 @@ #include #include #ifdef defined(_WIN32) || defined(WIN32) -#include +#include #endif using namespace MVS; From 5c419d21625c077f0711ccda1738f07cef5bfe03 Mon Sep 17 00:00:00 2001 From: geoffrey Date: Sat, 27 Jul 2019 14:56:17 +0100 Subject: [PATCH 08/16] this is a test --- libs/MVS/SceneTexture.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index f768ca988..bd7a028d1 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -29,6 +29,8 @@ * containing it. */ +// THIS IS A TEST + #include "Common.h" #include "Scene.h" #include "RectsBinPack.h" From 27bfde92b995707dc83528394d952e6668a82b3e Mon Sep 17 00:00:00 2001 From: geoffrey Date: Sat, 27 Jul 2019 15:11:24 +0100 Subject: [PATCH 09/16] fixing win32 folder creation issue --- libs/MVS/SceneTexture.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index bd7a028d1..883ad6501 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -29,8 +29,6 @@ * containing it. */ -// THIS IS A TEST - #include "Common.h" #include "Scene.h" #include "RectsBinPack.h" @@ -881,10 +879,10 @@ bool MeshTexture::FaceOutlierDetection(FaceDataArr& faceDatas, float thOutlier) // backup variables before global seam leveling void MeshTexture::BkpTexture() { - // create backup directory #if (defined(_WIN32) || defined(WIN32)) - if (_mkdir("atlas_backup") == -1) // can be used on Windows + wstring folder = L"atlas_backup"; + if (CreateDirectory(folder.c_str(), NULL) == -1) // can be used on Windows #else if (mkdir("atlas_backup", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) // can be used on non-Windows #endif From 3cd5adb605e061590c38a8baa4d847fa8f390af9 Mon Sep 17 00:00:00 2001 From: geoffrey Date: Sat, 27 Jul 2019 17:00:31 +0100 Subject: [PATCH 10/16] fixing win32 build --- libs/MVS/SceneTexture.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index 883ad6501..9aeea32fe 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -44,8 +44,6 @@ #endif using namespace MVS; -using namespace std; - // D E F I N E S /////////////////////////////////////////////////// @@ -896,31 +894,31 @@ void MeshTexture::BkpTexture() } } - ofstream ofscomponents("atlas_backup/components"); + std::ofstream ofscomponents("atlas_backup/components"); { boost::archive::text_oarchive oa(ofscomponents); oa << components; } - ofstream ofsmapIdxPatch("atlas_backup/mapIdxPatch"); + std::ofstream ofsmapIdxPatch("atlas_backup/mapIdxPatch"); { boost::archive::text_oarchive oa(ofsmapIdxPatch); oa << mapIdxPatch; } - ofstream ofsseamVertices("atlas_backup/seamVertices"); + std::ofstream ofsseamVertices("atlas_backup/seamVertices"); { boost::archive::text_oarchive oa(ofsseamVertices); oa << seamVertices; } - ofstream ofstexturePatches("atlas_backup/texturePatches"); + std::ofstream ofstexturePatches("atlas_backup/texturePatches"); { boost::archive::text_oarchive oa(ofstexturePatches); oa << texturePatches; } - ofstream ofsscene("atlas_backup/scene"); + std::ofstream ofsscene("atlas_backup/scene"); { boost::archive::text_oarchive oa(ofsscene); oa << scene; @@ -2080,14 +2078,14 @@ void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLevel // backup patches/atlas if(reTexture ==0){ - ofstream ofsrects("atlas_backup/rects"); + std::ofstream ofsrects("atlas_backup/rects"); // save data to archive { boost::archive::text_oarchive oa(ofsrects); oa << rects; } - ofstream ofstexturePatchesFINAL("atlas_backup/texturePatchesFINAL"); + std::ofstream ofstexturePatchesFINAL("atlas_backup/texturePatchesFINAL"); { boost::archive::text_oarchive oa(ofstexturePatchesFINAL); // write class instance to archive From ce428e1a0024e202c98c5614ff601f4ea87f77c9 Mon Sep 17 00:00:00 2001 From: geoffrey Date: Sat, 27 Jul 2019 17:00:31 +0100 Subject: [PATCH 11/16] fixing win32 build --- libs/MVS/SceneTexture.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index 883ad6501..9aeea32fe 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -44,8 +44,6 @@ #endif using namespace MVS; -using namespace std; - // D E F I N E S /////////////////////////////////////////////////// @@ -896,31 +894,31 @@ void MeshTexture::BkpTexture() } } - ofstream ofscomponents("atlas_backup/components"); + std::ofstream ofscomponents("atlas_backup/components"); { boost::archive::text_oarchive oa(ofscomponents); oa << components; } - ofstream ofsmapIdxPatch("atlas_backup/mapIdxPatch"); + std::ofstream ofsmapIdxPatch("atlas_backup/mapIdxPatch"); { boost::archive::text_oarchive oa(ofsmapIdxPatch); oa << mapIdxPatch; } - ofstream ofsseamVertices("atlas_backup/seamVertices"); + std::ofstream ofsseamVertices("atlas_backup/seamVertices"); { boost::archive::text_oarchive oa(ofsseamVertices); oa << seamVertices; } - ofstream ofstexturePatches("atlas_backup/texturePatches"); + std::ofstream ofstexturePatches("atlas_backup/texturePatches"); { boost::archive::text_oarchive oa(ofstexturePatches); oa << texturePatches; } - ofstream ofsscene("atlas_backup/scene"); + std::ofstream ofsscene("atlas_backup/scene"); { boost::archive::text_oarchive oa(ofsscene); oa << scene; @@ -2080,14 +2078,14 @@ void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLevel // backup patches/atlas if(reTexture ==0){ - ofstream ofsrects("atlas_backup/rects"); + std::ofstream ofsrects("atlas_backup/rects"); // save data to archive { boost::archive::text_oarchive oa(ofsrects); oa << rects; } - ofstream ofstexturePatchesFINAL("atlas_backup/texturePatchesFINAL"); + std::ofstream ofstexturePatchesFINAL("atlas_backup/texturePatchesFINAL"); { boost::archive::text_oarchive oa(ofstexturePatchesFINAL); // write class instance to archive From 07d14b741e686b14c0d9a6375fb8cd1756b0f1fe Mon Sep 17 00:00:00 2001 From: geoffrey Date: Sat, 27 Jul 2019 17:27:52 +0100 Subject: [PATCH 12/16] fixing win32 build --- libs/MVS/SceneTexture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index 9aeea32fe..13079c29f 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -879,7 +879,7 @@ void MeshTexture::BkpTexture() { // create backup directory #if (defined(_WIN32) || defined(WIN32)) - wstring folder = L"atlas_backup"; + std::wstring folder = (L"atlas_backup"); if (CreateDirectory(folder.c_str(), NULL) == -1) // can be used on Windows #else if (mkdir("atlas_backup", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) // can be used on non-Windows From 6bdc5ecbf45b540d408ded4592191dd30c3f69cf Mon Sep 17 00:00:00 2001 From: geoffrey Date: Sat, 27 Jul 2019 18:25:06 +0100 Subject: [PATCH 13/16] fixing win32 build --- libs/MVS/SceneTexture.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index 13079c29f..fb19befd1 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -879,8 +879,7 @@ void MeshTexture::BkpTexture() { // create backup directory #if (defined(_WIN32) || defined(WIN32)) - std::wstring folder = (L"atlas_backup"); - if (CreateDirectory(folder.c_str(), NULL) == -1) // can be used on Windows + if (CreateDirectoryA("atlas_backup", NULL) == -1) // can be used on Windows #else if (mkdir("atlas_backup", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) // can be used on non-Windows #endif From 409f881d88a705ff7585dd8d50952d58ceab67d0 Mon Sep 17 00:00:00 2001 From: geoffrey Date: Sat, 3 Aug 2019 17:48:14 +0100 Subject: [PATCH 14/16] Read 32bit (only) EXR file (header and data) - Output 32bit (linear) and 8bit (log) data. Works as expected with current openMVS code but limited to 8bit output due to current implementation. pImage->ReadData(image.data, PF_R8G8B8, 3, (CImage::Size)image.step) --- build/Modules/FindOpenEXR.cmake | 98 +++++++++ build/Templates/ConfigLocal.h.in | 3 + libs/Common/Types.inl | 6 +- libs/IO/CMakeLists.txt | 10 +- libs/IO/Common.h | 6 + libs/IO/Image.cpp | 94 ++++++++ libs/IO/Image.h | 10 + libs/IO/ImageEXR.cpp | 363 +++++++++++++++++++++++++++++++ libs/IO/ImageEXR.h | 44 ++++ 9 files changed, 632 insertions(+), 2 deletions(-) create mode 100644 build/Modules/FindOpenEXR.cmake create mode 100644 libs/IO/ImageEXR.cpp create mode 100644 libs/IO/ImageEXR.h diff --git a/build/Modules/FindOpenEXR.cmake b/build/Modules/FindOpenEXR.cmake new file mode 100644 index 000000000..bb75a03bf --- /dev/null +++ b/build/Modules/FindOpenEXR.cmake @@ -0,0 +1,98 @@ +# +# Copyright 2016 Pixar +# +# Licensed under the Apache License, Version 2.0 (the "Apache License") +# with the following modification; you may not use this file except in +# compliance with the Apache License and the following modification to it: +# Section 6. Trademarks. is deleted and replaced with: +# +# 6. Trademarks. This License does not grant permission to use the trade +# names, trademarks, service marks, or product names of the Licensor +# and its affiliates, except as required to comply with Section 4(c) of +# the License and to reproduce the content of the NOTICE file. +# +# You may obtain a copy of the Apache License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the Apache License with the above modification is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the Apache License for the specific +# language governing permissions and limitations under the Apache License. +# + +find_path(OPENEXR_INCLUDE_DIR + OpenEXR/half.h +HINTS + "${OPENEXR_LOCATION}" + "$ENV{OPENEXR_LOCATION}" +PATH_SUFFIXES + include/ +DOC + "OpenEXR headers path" +) + +if(OPENEXR_INCLUDE_DIR) + set(openexr_config_file "${OPENEXR_INCLUDE_DIR}/OpenEXR/OpenEXRConfig.h") + if(EXISTS ${openexr_config_file}) + file(STRINGS + ${openexr_config_file} + TMP + REGEX "#define OPENEXR_VERSION_STRING.*$") + string(REGEX MATCHALL "[0-9.]+" OPENEXR_VERSION ${TMP}) + + file(STRINGS + ${openexr_config_file} + TMP + REGEX "#define OPENEXR_VERSION_MAJOR.*$") + string(REGEX MATCHALL "[0-9]" OPENEXR_MAJOR_VERSION ${TMP}) + + file(STRINGS + ${openexr_config_file} + TMP + REGEX "#define OPENEXR_VERSION_MINOR.*$") + string(REGEX MATCHALL "[0-9]" OPENEXR_MINOR_VERSION ${TMP}) + endif() +endif() + +foreach(OPENEXR_LIB + Half + Iex + Imath + IlmImf + IlmThread + ) + + # OpenEXR libraries may be suffixed with the version number, so we search + # using both versioned and unversioned names. + find_library(OPENEXR_${OPENEXR_LIB}_LIBRARY + NAMES + ${OPENEXR_LIB}-${OPENEXR_MAJOR_VERSION}_${OPENEXR_MINOR_VERSION} + ${OPENEXR_LIB} + HINTS + "${OPENEXR_LOCATION}" + "$ENV{OPENEXR_LOCATION}" + PATH_SUFFIXES + lib/ + DOC + "OPENEXR's ${OPENEXR_LIB} library path" + ) + + if(OPENEXR_${OPENEXR_LIB}_LIBRARY) + list(APPEND OPENEXR_LIBRARIES ${OPENEXR_${OPENEXR_LIB}_LIBRARY}) + endif() +endforeach(OPENEXR_LIB) + +# So #include works +list(APPEND OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR}) +list(APPEND OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR}/OpenEXR) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(OpenEXR + REQUIRED_VARS + OPENEXR_INCLUDE_DIRS + OPENEXR_LIBRARIES + VERSION_VAR + OPENEXR_VERSION +) diff --git a/build/Templates/ConfigLocal.h.in b/build/Templates/ConfigLocal.h.in index 5fbc77b78..eb0df11f7 100644 --- a/build/Templates/ConfigLocal.h.in +++ b/build/Templates/ConfigLocal.h.in @@ -34,6 +34,9 @@ // TIFF codec #cmakedefine _USE_TIFF +// EXR codec +#cmakedefine _USE_EXR + // OpenGL support #cmakedefine _USE_OPENGL diff --git a/libs/Common/Types.inl b/libs/Common/Types.inl index eb1582583..91ccefebc 100644 --- a/libs/Common/Types.inl +++ b/libs/Common/Types.inl @@ -2378,7 +2378,7 @@ inline void _ProcessScanLine(int y, const TPoint3& pa, const TPoint3& pb, } } // Raster the given triangle and output the position and depth of each pixel of the triangle; -// based on "Learning how to write a 3D software engine – Rasterization & Z-Buffering" by Nick (David Rousset) +// based on "Learning how to write a 3D software engine � Rasterization & Z-Buffering" by Nick (David Rousset) // http://blogs.msdn.com/b/davrous/archive/2013/06/21/tutorial-part-4-learning-how-to-write-a-3d-software-engine-in-c-ts-or-js-rasterization-amp-z-buffering.aspx template template @@ -2751,6 +2751,10 @@ bool TImage::Save(const String& fileName) const compression_params.push_back(cv::IMWRITE_JPEG_QUALITY); compression_params.push_back(80); } else + if (ext == ".exr") { + compression_params.push_back(cv::IMWRITE_EXR_TYPE_FLOAT); + compression_params.push_back(2); + } else if (ext == ".pfm") { if (Base::depth() != CV_32F) return false; diff --git a/libs/IO/CMakeLists.txt b/libs/IO/CMakeLists.txt index a354376be..3ac337e58 100644 --- a/libs/IO/CMakeLists.txt +++ b/libs/IO/CMakeLists.txt @@ -23,6 +23,14 @@ if(TIFF_FOUND) else() SET(TIFF_LIBRARIES "") endif() +FIND_PACKAGE(OpenEXR) +if(OPENEXR_FOUND) + INCLUDE_DIRECTORIES(${OPENEXR_INCLUDE_DIR}) + ADD_DEFINITIONS(${OPENEXR_DEFINITIONS} -D_USE_EXR) + SET(_USE_EXR TRUE CACHE INTERNAL "") +else() + SET(OPENEXR_LIBRARIES "") +endif() # List sources files FILE(GLOB PCH_C "Common.cpp") @@ -43,7 +51,7 @@ cxx_library_with_type_no_pch(IO "Libs" "STATIC" "${cxx_default}" set_target_pch(IO Common.h) # Link its dependencies -TARGET_LINK_LIBRARIES(IO Common ${PNG_LIBRARIES} ${JPEG_LIBRARIES} ${TIFF_LIBRARIES} ${EXIV2_LIBS}) +TARGET_LINK_LIBRARIES(IO Common ${PNG_LIBRARIES} ${JPEG_LIBRARIES} ${TIFF_LIBRARIES} ${OPENEXR_LIBRARIES} ${EXIV2_LIBS}) # Install SET_TARGET_PROPERTIES(IO PROPERTIES diff --git a/libs/IO/Common.h b/libs/IO/Common.h index e43aaac44..490acad53 100644 --- a/libs/IO/Common.h +++ b/libs/IO/Common.h @@ -36,6 +36,9 @@ #ifdef _USE_TIFF #define _IMAGE_TIFF // add TIFF support #endif +#ifdef _USE_EXR +#define _IMAGE_EXR // add EXR support +#endif #include "ImageSCI.h" #ifdef _IMAGE_BMP @@ -47,6 +50,9 @@ #ifdef _IMAGE_DDS #include "ImageDDS.h" #endif +#ifdef _IMAGE_EXR +#include "ImageEXR.h" +#endif #ifdef _IMAGE_PNG #include "ImagePNG.h" #endif diff --git a/libs/IO/Image.cpp b/libs/IO/Image.cpp index 0a9de141f..0db712883 100644 --- a/libs/IO/Image.cpp +++ b/libs/IO/Image.cpp @@ -7,6 +7,7 @@ #include "Common.h" #include "Image.h" +#include using namespace SEACAVE; @@ -193,6 +194,7 @@ CImage::Size CImage::GetStride(PIXELFORMAT pixFormat) switch (pixFormat) { case PF_A8: + case PF_A32: case PF_GRAY8: return 1; case PF_R5G6B5: @@ -204,14 +206,22 @@ CImage::Size CImage::GetStride(PIXELFORMAT pixFormat) case PF_A8R8G8B8: case PF_B8G8R8A8: case PF_A8B8G8R8: + case PF_GRAY32: return 4; case PF_DXT1: return 8; + case PF_B32G32R32: + case PF_R32G32B32: + return 12; case PF_DXT2: case PF_DXT3: case PF_DXT4: case PF_DXT5: case PF_3DC: + case PF_R32G32B32A32: + case PF_A32R32G32B32: + case PF_B32G32R32A32: + case PF_A32B32G32R32: return 16; default: LOG(LT_IMAGE, "error: unsupported SCI pixel format"); @@ -227,6 +237,7 @@ bool CImage::FormatHasAlpha(PIXELFORMAT format) switch (format) { case PF_A8: + case PF_A32: case PF_R8G8B8A8: case PF_A8R8G8B8: case PF_B8G8R8A8: @@ -235,11 +246,18 @@ bool CImage::FormatHasAlpha(PIXELFORMAT format) case PF_DXT3: case PF_DXT4: case PF_DXT5: + case PF_R32G32B32A32: + case PF_A32R32G32B32: + case PF_B32G32R32A32: + case PF_A32B32G32R32: return true; case PF_GRAY8: + case PF_GRAY32: case PF_R5G6B5: case PF_B8G8R8: case PF_R8G8B8: + case PF_B32G32R32: + case PF_R32G32B32: case PF_DXT1: case PF_3DC: return false; @@ -259,6 +277,7 @@ bool CImage::FilterFormat(void* pDst, PIXELFORMAT formatDst, Size strideDst, con switch (formatDst) { case PF_A8: + case PF_A32: case PF_GRAY8: switch (formatSrc) { @@ -409,6 +428,67 @@ bool CImage::FilterFormat(void* pDst, PIXELFORMAT formatDst, Size strideDst, con ((uint8_t*)pDst)[2] = ((uint8_t*)pSrc)[1]; } return true; + + case PF_B32G32R32: + // from PF_B32G32R32 to PF_R8G8B8 (flip) + ASSERT(pDst != pSrc); + for (Size i=0; i +#include +#include +#include +#include "OpenEXR/Iex.h" + +#include + +namespace IMF = OPENEXR_IMF_NAMESPACE; + +using namespace std; +using namespace IMF; +using namespace SEACAVE; +using namespace IMATH_NAMESPACE; + + + +// D E F I N E S /////////////////////////////////////////////////// +typedef struct tagRGBF { + float red; + float green; + float blue; +} RGBF; + +typedef struct tagRGBI { + uint8_t red; + uint8_t green; + uint8_t blue; +} RGBI; + + +// F U N C T I O N S /////////////////////////////////////////////// +int +pixelType (PixelType pt) +{ + int val=0; + switch (pt) + { + case UINT: + //cout << "32-bit unsigned integer"; + break; + case HALF: + //cout << "16-bit floating-point"; + val = 2; + break; + case FLOAT: + //cout << "32-bit floating-point"; + val = 4; + break; + default: + //cout << "check exr type --> " << int (pt); + break; + } + return val; +} + +// S T R U C T S /////////////////////////////////////////////////// +class C_IStream: public IStream +{ + public: + + C_IStream (FILE *file, const char fileName[]): + IStream (fileName), _file (file) {} + + virtual bool read (char c[/*n*/], int n); + virtual Int64 tellg (); + virtual void seekg (Int64 pos); + virtual void clear (); + + private: + + FILE * _file; +}; + +bool +C_IStream::read (char c[/*n*/], int n) +{ + if (n != static_cast(fread (c, 1, n, _file))) + { + // + // fread() failed, but the return value does not distinguish + // between I/O errors and end of file, so we call ferror() to + // determine what happened. + // + + if (ferror (_file)) + IEX_NAMESPACE::throwErrnoExc(); + else + throw IEX_NAMESPACE::InputExc ("Unexpected end of file."); + } + + return feof (_file); +} + + +Int64 +C_IStream::tellg () +{ + return ftell (_file); +} + + +void +C_IStream::seekg (Int64 pos) +{ + clearerr (_file); + fseek (_file, pos, SEEK_SET); +} + +void +C_IStream::clear () +{ + clearerr (_file); +} + + +CImageEXR::CImageEXR() +{ +} // Constructor + +CImageEXR::~CImageEXR() +{ + Close(); +} // Destructor +/*----------------------------------------------------------------*/ + +void CImageEXR::Close() +{ + m_width = m_height = 0; + CImage::Close(); +} +/*----------------------------------------------------------------*/ + + +HRESULT CImageEXR::ReadHeader() +{ + int byte=0,channelsNum=0; + string colortype=""; + // reading image + { + + FILE * cfile = fopen (m_fileName, "rb"); + if (!cfile) { + LOG(LT_IMAGE, "error: unsupported EXR image"); + return _INVALIDFILE; + } + + if (cfile == 0) + { + LOG(LT_IMAGE, "Cannot open EXR file '%s'", m_fileName); + } + else + { + try + { + C_IStream istr (cfile, "EXR_FILE"); + RgbaInputFile exr (istr); + Box2i dw = exr.dataWindow(); + + m_dataWidth =m_width=dw.max.x - dw.min.x + 1; + m_dataHeight=m_height=dw.max.y - dw.min.y + 1; + + if(exr.isComplete()) + { + m_numLevels = 0; + m_level = 0; + + const ChannelList &channels = exr.header().channels(); + for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) + { + colortype+=i.name(); + if(strcmp(i.name(), "R")||strcmp(i.name(), "G")||strcmp(i.name(), "B")||strcmp(i.name(), "A") == 0){ + byte=pixelType(i.channel().type); + } + channelsNum++; + } + + // check if 32bit image + if(byte==4) + { + // channel number + switch (channelsNum) + { + case 1: + if(colortype == "A"){ + m_format = PF_A32; + }else{ + m_format = PF_GRAY32; + } + m_stride = channelsNum*byte; + break; + case 3: + m_format = PF_R32G32B32; + m_stride = channelsNum*byte; + break; + case 4: + m_format = PF_R32G32B32A32; + m_stride = channelsNum*byte; + // consider RGBA as RGB ?? + // m_format = PF_R32G32B32; + // m_stride = (channelsNum-1)*byte; + break; + default: + LOG(LT_IMAGE, "error: unsupported EXR image"); + Close(); + return _INVALIDFILE; + } + m_lineWidth = m_width * m_stride; + + }else{ + Close(); + LOG(LT_IMAGE, "error: not a 32bit float EXR image"); + return _FAIL; + } + + }else{ + Close(); + LOG(LT_IMAGE, "error: incomplete EXR image"); + return _FAIL; + } + } + catch (...) + { + LOG(LT_IMAGE, "error: can't process EXR image"); + Close(); + throw; + return _FAIL; + } + // ending as expected + return _OK; + } + } + + Close(); + return _FAIL; +} // ReadHeader +/*----------------------------------------------------------------*/ + + +HRESULT CImageEXR::ReadData(void* pData, PIXELFORMAT dataFormat, Size nStride, Size lineWidth) +{ + FILE *cfile = fopen (m_fileName, "rb"); + if (!cfile) { + LOG(LT_IMAGE, "error: unsupported EXR image"); + return _INVALIDFILE; + } + if (cfile == 0) + { + LOG(LT_IMAGE, "Cannot open EXR file '%s'", m_fileName); + } + else + { + try + { + if (m_width && m_height) + { + // use the low level interface + C_IStream istr (cfile, "EXR_FILE"); + + if (dataFormat == m_format && nStride == m_stride) + { + const BYTE *bits = (BYTE*&)pData; + InputFile exr (istr); + // build a frame buffer (i.e. what we want on output) + FrameBuffer frameBuffer; + + Array2D rPixels(m_height, m_width); + const Box2i &dw = exr.header().dataWindow(); + const size_t bytespp = sizeof (rPixels[0][0]) * 1; + const unsigned pitch = sizeof (rPixels[0][0]) * m_width; // could be lineWidth ?? + // allow dataWindow with minimal bounds different form zero + size_t offset = - dw.min.x * bytespp - dw.min.y * pitch; + + const char *channel_name[3] = { "R", "G", "B" }; + for(int c = 0; c < 3; c++) + { + frameBuffer.insert ( + channel_name[c], // name + Slice (FLOAT, // type + (char*)(bits + c * sizeof(float) + offset), // base + bytespp, // xStride sizeof (rPixels[0][0]) * 1, + pitch, // yStride sizeof (rPixels[0][0]) * width, + 1, 1, // x/y sampling + 0.0)); // fillValue + } + + // read the file + exr.setFrameBuffer(frameBuffer); + exr.readPixels(dw.min.y, dw.max.y); + + }else{ + // read image to a buffer and convert it + const BYTE *bits = (BYTE*&)pData; + BYTE *data = (BYTE*)bits; + RgbaInputFile exr (istr); + // read the file in lines + Box2i dw = exr.dataWindow(); + + Array2D line(1, m_width); + + while (dw.min.y <= dw.max.y) { + // read a line + exr.setFrameBuffer (&line[0][0] - dw.min.x - dw.min.y * m_width, 1, m_width); + exr.readPixels (dw.min.y, min(dw.min.y , dw.max.y)); + + RGBI *pixel = (RGBI*)data; + for(int x = 0; x < m_width; x++) { + pixel[x].red = F32TO8(line[0][x].b); + pixel[x].green = F32TO8(line[0][x].g); + pixel[x].blue = F32TO8(line[0][x].r); + } + // next line + data += lineWidth; + dw.min.y += 1; + } + } + return _OK; + } + } + catch (...) + { + LOG(LT_IMAGE, "error: can't process EXR image"); + Close(); + throw; + return _FAIL; + } + } + Close(); + return _FAIL; +} // Read +/*----------------------------------------------------------------*/ + + +HRESULT CImageEXR::WriteHeader(PIXELFORMAT imageFormat, Size width, Size height, BYTE /*numLevels*/) +{ + // TODO: to implement the EXR encoder + + return _OK; +} // WriteHeader +/*----------------------------------------------------------------*/ + + +HRESULT CImageEXR::WriteData(void* pData, PIXELFORMAT dataFormat, Size nStride, Size lineWidth) +{ + + // TODO: to implement the EXR encoder + + return _OK; +} // WriteData +/*----------------------------------------------------------------*/ + +//#endif // _IMAGE_EXR diff --git a/libs/IO/ImageEXR.h b/libs/IO/ImageEXR.h new file mode 100644 index 000000000..8abd9f2b1 --- /dev/null +++ b/libs/IO/ImageEXR.h @@ -0,0 +1,44 @@ +//////////////////////////////////////////////////////////////////// +// ImageEXR.h +// +// Copyright 2007 cDc@seacave +// Distributed under the Boost Software License, Version 1.0 +// (See http://www.boost.org/LICENSE_1_0.txt) + +#ifndef __SEACAVE_IMAGEEXR_H__ +#define __SEACAVE_IMAGEEXR_H__ + + +// D E F I N E S /////////////////////////////////////////////////// + + +// I N C L U D E S ///////////////////////////////////////////////// + +#include "Image.h" + + +namespace SEACAVE { + +// S T R U C T S /////////////////////////////////////////////////// + +class IO_API CImageEXR : public CImage +{ +public: + CImageEXR(); + virtual ~CImageEXR(); + + void Close(); + + HRESULT ReadHeader(); + HRESULT ReadData(void*, PIXELFORMAT, Size nStride, Size lineWidth); + HRESULT WriteHeader(PIXELFORMAT, Size width, Size height, BYTE numLevels); + HRESULT WriteData(void*, PIXELFORMAT, Size nStride, Size lineWidth); + +protected: + +}; // class CImageEXR +/*----------------------------------------------------------------*/ + +} // namespace SEACAVE + +#endif // __SEACAVE_IMAGEEXR_H__ From b07aa5c83d1e08b2945502fd0564da08d71a44dc Mon Sep 17 00:00:00 2001 From: geoffrey Date: Sat, 3 Aug 2019 21:34:00 +0100 Subject: [PATCH 15/16] simplify ImageEXR code and improve compatibility with older openCV version --- libs/Common/Types.inl | 4 +- libs/IO/ImageEXR.cpp | 97 ++++++++++++++++++------------------------- 2 files changed, 42 insertions(+), 59 deletions(-) diff --git a/libs/Common/Types.inl b/libs/Common/Types.inl index 91ccefebc..5778d0e99 100644 --- a/libs/Common/Types.inl +++ b/libs/Common/Types.inl @@ -2752,8 +2752,8 @@ bool TImage::Save(const String& fileName) const compression_params.push_back(80); } else if (ext == ".exr") { - compression_params.push_back(cv::IMWRITE_EXR_TYPE_FLOAT); - compression_params.push_back(2); + //compression_params.push_back(cv::IMWRITE_EXR_TYPE_FLOAT); + //compression_params.push_back(2); } else if (ext == ".pfm") { if (Base::depth() != CV_32F) diff --git a/libs/IO/ImageEXR.cpp b/libs/IO/ImageEXR.cpp index 052309859..47de1e89e 100644 --- a/libs/IO/ImageEXR.cpp +++ b/libs/IO/ImageEXR.cpp @@ -205,11 +205,11 @@ HRESULT CImageEXR::ReadHeader() m_stride = channelsNum*byte; break; case 4: - m_format = PF_R32G32B32A32; - m_stride = channelsNum*byte; - // consider RGBA as RGB ?? - // m_format = PF_R32G32B32; - // m_stride = (channelsNum-1)*byte; + // m_format = PF_R32G32B32A32; + // m_stride = channelsNum*byte; + //consider RGBA as RGB ?? + m_format = PF_R32G32B32; + m_stride = (channelsNum-1)*byte; break; default: LOG(LT_IMAGE, "error: unsupported EXR image"); @@ -268,62 +268,45 @@ HRESULT CImageEXR::ReadData(void* pData, PIXELFORMAT dataFormat, Size nStride, S // use the low level interface C_IStream istr (cfile, "EXR_FILE"); - if (dataFormat == m_format && nStride == m_stride) - { - const BYTE *bits = (BYTE*&)pData; - InputFile exr (istr); - // build a frame buffer (i.e. what we want on output) - FrameBuffer frameBuffer; - - Array2D rPixels(m_height, m_width); - const Box2i &dw = exr.header().dataWindow(); - const size_t bytespp = sizeof (rPixels[0][0]) * 1; - const unsigned pitch = sizeof (rPixels[0][0]) * m_width; // could be lineWidth ?? - // allow dataWindow with minimal bounds different form zero - size_t offset = - dw.min.x * bytespp - dw.min.y * pitch; - - const char *channel_name[3] = { "R", "G", "B" }; - for(int c = 0; c < 3; c++) + // read image to a buffer and convert it + const BYTE *bits = (BYTE*&)pData; + BYTE *data = (BYTE*)bits; + RgbaInputFile exr (istr); + RGBF *pixelFloat; + RGBI *pixel; + Box2i dw = exr.dataWindow(); + Array2D line(1, m_width); + // read the file in lines + while (dw.min.y <= dw.max.y) { + // read a line + exr.setFrameBuffer (&line[0][0] - dw.min.x - dw.min.y * m_width, 1, m_width); + exr.readPixels (dw.min.y, min(dw.min.y , dw.max.y)); + + if (dataFormat == m_format && nStride == m_stride) { - frameBuffer.insert ( - channel_name[c], // name - Slice (FLOAT, // type - (char*)(bits + c * sizeof(float) + offset), // base - bytespp, // xStride sizeof (rPixels[0][0]) * 1, - pitch, // yStride sizeof (rPixels[0][0]) * width, - 1, 1, // x/y sampling - 0.0)); // fillValue + pixelFloat = (RGBF*)data; + }else{ + pixel = (RGBI*)data; } - // read the file - exr.setFrameBuffer(frameBuffer); - exr.readPixels(dw.min.y, dw.max.y); - - }else{ - // read image to a buffer and convert it - const BYTE *bits = (BYTE*&)pData; - BYTE *data = (BYTE*)bits; - RgbaInputFile exr (istr); - // read the file in lines - Box2i dw = exr.dataWindow(); - - Array2D line(1, m_width); - - while (dw.min.y <= dw.max.y) { - // read a line - exr.setFrameBuffer (&line[0][0] - dw.min.x - dw.min.y * m_width, 1, m_width); - exr.readPixels (dw.min.y, min(dw.min.y , dw.max.y)); - - RGBI *pixel = (RGBI*)data; - for(int x = 0; x < m_width; x++) { - pixel[x].red = F32TO8(line[0][x].b); - pixel[x].green = F32TO8(line[0][x].g); - pixel[x].blue = F32TO8(line[0][x].r); - } - // next line - data += lineWidth; - dw.min.y += 1; + for(int x = 0; x < m_width; x++) { + if (dataFormat == m_format && nStride == m_stride) + { + // FLOAT OUTPUT + pixelFloat[x].red = line[0][x].b; + pixelFloat[x].green = line[0][x].g; + pixelFloat[x].blue = line[0][x].r; + }else{ + // INT OUTPUT + pixel[x].red = F32TO8(line[0][x].b); + pixel[x].green = F32TO8(line[0][x].g); + pixel[x].blue = F32TO8(line[0][x].r); } + + } + // next line + data += lineWidth; + dw.min.y += 1; } return _OK; } From 5954d8a4a804cbaa4974dac7e51e6322bc8d3845 Mon Sep 17 00:00:00 2001 From: geoffrey Date: Sat, 3 Aug 2019 23:06:09 +0100 Subject: [PATCH 16/16] -quick conversion to 32bit float to allow 32bit texturing output using TextureMesh (hasn't been tested for anything else than TextureMesh but could work ) -changing default output to float 32bit EXR file format. --- apps/InterfaceCOLMAP/InterfaceCOLMAP.cpp | 2 +- .../InterfacePhotoScan/InterfacePhotoScan.cpp | 4 +- .../InterfaceVisualSFM/InterfaceVisualSFM.cpp | 8 +- apps/TextureMesh/TextureMesh.cpp | 10 +- apps/Viewer/Scene.cpp | 2 +- libs/Common/CUDA.h | 6 +- libs/IO/OBJ.cpp | 5 +- libs/IO/OBJ.h | 6 +- libs/MVS/DepthMap.cpp | 38 ++-- libs/MVS/DepthMap.h | 4 +- libs/MVS/Image.cpp | 15 +- libs/MVS/Image.h | 10 +- libs/MVS/Interface.h | 3 +- libs/MVS/Mesh.cpp | 38 ++-- libs/MVS/Mesh.h | 10 +- libs/MVS/PointCloud.h | 2 +- libs/MVS/Scene.cpp | 2 +- libs/MVS/Scene.h | 2 +- libs/MVS/SceneDensify.cpp | 28 +-- libs/MVS/SceneRefine.cpp | 4 +- libs/MVS/SceneRefineCUDA.cpp | 38 ++-- libs/MVS/SceneTexture.cpp | 170 +++++++++--------- 22 files changed, 207 insertions(+), 200 deletions(-) diff --git a/apps/InterfaceCOLMAP/InterfaceCOLMAP.cpp b/apps/InterfaceCOLMAP/InterfaceCOLMAP.cpp index 651b44c98..15c6461b5 100644 --- a/apps/InterfaceCOLMAP/InterfaceCOLMAP.cpp +++ b/apps/InterfaceCOLMAP/InterfaceCOLMAP.cpp @@ -686,7 +686,7 @@ bool ExportScene(const String& strFolder, const Interface& scene) ProjectVertex_3x4_3_2(cameras[view.imageID].P.val, X.ptr(), proj.p.data()); img.projs.push_back(proj); } - point.c = scene.verticesColor.empty() ? Interface::Col3(255,255,255) : scene.verticesColor[ID].c; + point.c = scene.verticesColor.empty() ? Interface::Col3(1.f,1.f,1.f) : scene.verticesColor[ID].c; point.e = 0; if (!point.Write(file)) return false; diff --git a/apps/InterfacePhotoScan/InterfacePhotoScan.cpp b/apps/InterfacePhotoScan/InterfacePhotoScan.cpp index 25d9db5b4..a85667044 100644 --- a/apps/InterfacePhotoScan/InterfacePhotoScan.cpp +++ b/apps/InterfacePhotoScan/InterfacePhotoScan.cpp @@ -416,7 +416,7 @@ bool UndistortBrown(MVS::Image& imageData, uint32_t ID, const DistCoeff& dc, con #endif // undistort image - Image8U3 imgUndist; + Image32F3 imgUndist; cv::undistort(imageData.image, imgUndist, prevK, distCoeffs, K); imageData.ReleaseImage(); @@ -475,7 +475,7 @@ void AssignPoints(const MVS::Image& imageData, uint32_t ID, MVS::PointCloud& poi const int cw(ir.x+j); if (!depthMap.isInside(ImageRef(cw,rw))) continue; - if (depthMap(rw,cw) < Xc.z) + if (depthMap(rw,cw) < Xc.z) goto NEXT_POINT; } } diff --git a/apps/InterfaceVisualSFM/InterfaceVisualSFM.cpp b/apps/InterfaceVisualSFM/InterfaceVisualSFM.cpp index 75bce304b..10c5bdf18 100644 --- a/apps/InterfaceVisualSFM/InterfaceVisualSFM.cpp +++ b/apps/InterfaceVisualSFM/InterfaceVisualSFM.cpp @@ -233,14 +233,14 @@ inline TPoint2 DistortPointR1(const TPoint2& pt, const REAL& k1) { #endif } -void UndistortImage(const Camera& camera, const REAL& k1, const Image8U3 imgIn, Image8U3& imgOut) +void UndistortImage(const Camera& camera, const REAL& k1, const Image32F3 imgIn, Image32F3& imgOut) { // allocate the undistorted image if (imgOut.data == imgIn.data || imgOut.cols != imgIn.cols || imgOut.rows != imgIn.rows || imgOut.type() != imgIn.type()) - imgOut = Image8U3(imgIn.rows, imgIn.cols); + imgOut = Image32F3(imgIn.rows, imgIn.cols); // compute each pixel const int w = imgIn.cols; @@ -260,13 +260,13 @@ void UndistortImage(const Camera& camera, const REAL& k1, const Image8U3 imgIn, Camera::NormalizeProjection(K.val, pt.ptr(), pt.ptr()); // if coordinates in range - Pixel8U& col = imgOut(v,u); + Pixel32F& col = imgOut(v,u); if (imgIn.isInside(pt)) { // get pixel color col = imgIn.sample(sampler, pt).cast(); } else { // set to black - col = Pixel8U::BLACK; + col = Pixel32F::BLACK; } } } diff --git a/apps/TextureMesh/TextureMesh.cpp b/apps/TextureMesh/TextureMesh.cpp index d7ea10813..2ca3286fc 100644 --- a/apps/TextureMesh/TextureMesh.cpp +++ b/apps/TextureMesh/TextureMesh.cpp @@ -230,7 +230,7 @@ int main(int argc, LPCTSTR* argv) { // compute mesh texture TD_TIMER_START(); - if (!scene.TextureMesh(OPT::nResolutionLevel, OPT::nMinResolution, OPT::fOutlierThreshold, OPT::fRatioDataSmoothness, OPT::bGlobalSeamLeveling, OPT::bLocalSeamLeveling, OPT::nTextureSizeMultiple, OPT::nRectPackingHeuristic, Pixel8U(OPT::nColEmpty), OPT::reTexture)) + if (!scene.TextureMesh(OPT::nResolutionLevel, OPT::nMinResolution, OPT::fOutlierThreshold, OPT::fRatioDataSmoothness, OPT::bGlobalSeamLeveling, OPT::bLocalSeamLeveling, OPT::nTextureSizeMultiple, OPT::nRectPackingHeuristic, Pixel32F(OPT::nColEmpty), OPT::reTexture)) return EXIT_FAILURE; VERBOSE("Mesh texturing completed: %u vertices, %u faces (%s)", scene.mesh.vertices.GetSize(), scene.mesh.faces.GetSize(), TD_TIMER_GET_FMT().c_str()); @@ -246,14 +246,14 @@ int main(int argc, LPCTSTR* argv) if (OPT::nOrthoMapResolution) { // project mesh as an orthographic image ProjectOrtho: - Image8U3 imageRGB; - Image8U imageRGBA[4]; + Image32F3 imageRGB; + Image32F imageRGBA[4]; Point3 center; scene.mesh.ProjectOrthoTopDown(OPT::nOrthoMapResolution, imageRGB, imageRGBA[3], center); - Image8U4 image; + Image32F4 image; cv::split(imageRGB, imageRGBA); cv::merge(imageRGBA, 4, image); - image.Save(baseFileName+_T("_orthomap.png")); + image.Save(baseFileName+_T("_orthomap.exr")); SML sml(_T("OrthoMap")); sml[_T("Center")].val = String::FormatString(_T("%g %g %g"), center.x, center.y, center.z); sml.Save(baseFileName+_T("_orthomap.txt")); diff --git a/apps/Viewer/Scene.cpp b/apps/Viewer/Scene.cpp index 8e63dbf9a..6dc0ba3c7 100644 --- a/apps/Viewer/Scene.cpp +++ b/apps/Viewer/Scene.cpp @@ -361,7 +361,7 @@ bool Scene::Open(LPCTSTR fileName, LPCTSTR meshFileName) image.SetImage(scene.mesh.textureDiffuse); scene.mesh.textureDiffuse.release(); #else // preserve texture, used only to be able to export the mesh - Image8U3 textureDiffuse; + Image32F3 textureDiffuse; cv::flip(scene.mesh.textureDiffuse, textureDiffuse, 0); image.SetImage(textureDiffuse); #endif diff --git a/libs/Common/CUDA.h b/libs/Common/CUDA.h index 1ab9b5303..2bd4922f3 100644 --- a/libs/Common/CUDA.h +++ b/libs/Common/CUDA.h @@ -211,7 +211,7 @@ class EventRT } void Release(); CUresult Reset(unsigned flags = CU_EVENT_DEFAULT); - + inline operator CUevent() const { return hEvent; } @@ -458,7 +458,7 @@ class TArrayRT public: inline TArrayRT() : hArray(NULL) {} - inline TArrayRT(const Image8U::Size& size, unsigned flags=0) : hArray(NULL) { reportCudaError(Reset(size, flags)); } + inline TArrayRT(const Image32F::Size& size, unsigned flags=0) : hArray(NULL) { reportCudaError(Reset(size, flags)); } inline TArrayRT(unsigned width, unsigned height, unsigned depth=0, unsigned flags=0) : hArray(NULL) { reportCudaError(Reset(width, height, depth, flags)); } inline ~TArrayRT() { Release(); } @@ -478,7 +478,7 @@ class TArrayRT hArray = NULL; } } - inline CUresult Reset(const Image8U::Size& size, unsigned flags=0) { + inline CUresult Reset(const Image32F::Size& size, unsigned flags=0) { return Reset((unsigned)size.width, (unsigned)size.height, 0, flags); } CUresult Reset(unsigned width, unsigned height, unsigned depth=0, unsigned flags=0) { diff --git a/libs/IO/OBJ.cpp b/libs/IO/OBJ.cpp index 2d8bd4fda..6dd61c63d 100644 --- a/libs/IO/OBJ.cpp +++ b/libs/IO/OBJ.cpp @@ -23,7 +23,7 @@ using namespace SEACAVE; // S T R U C T S /////////////////////////////////////////////////// -ObjModel::MaterialLib::Material::Material(const Image8U3& _diffuse_map, const Color& _Kd) +ObjModel::MaterialLib::Material::Material(const Image32F3& _diffuse_map, const Color& _Kd) : diffuse_map(_diffuse_map), Kd(_Kd) @@ -72,7 +72,8 @@ bool ObjModel::MaterialLib::Save(const String& prefix, bool texLossless) const if (mat.diffuse_map.empty()) continue; if (mat.diffuse_name.IsEmpty()) - const_cast(mat.diffuse_name) = name+"_"+mat.name+"_map_Kd."+(texLossless?"png":"jpg"); + const_cast(mat.diffuse_name) = name+"_"+mat.name+"_map_Kd."+("exr"); + //const_cast(mat.diffuse_name) = name+"_"+mat.name+"_map_Kd."+(texLossless?"png":"jpg"); out << "map_Kd " << mat.diffuse_name << "\n"; const bool bRet(mat.diffuse_map.Save(pathName+mat.diffuse_name)); #ifdef OBJ_USE_OPENMP diff --git a/libs/IO/OBJ.h b/libs/IO/OBJ.h index d32c3569f..df20aa323 100644 --- a/libs/IO/OBJ.h +++ b/libs/IO/OBJ.h @@ -20,7 +20,7 @@ namespace SEACAVE { // S T R U C T S /////////////////////////////////////////////////// // OBJ model files parser. -// +// // The OBJ file format is a simple data-format that represents 3D geometry alone — // namely, the position of each vertex, the UV position of each texture coordinate // vertex, vertex normals, and the faces that make each polygon defined as a list of @@ -37,12 +37,12 @@ class IO_API ObjModel { struct Material { String name; String diffuse_name; - Image8U3 diffuse_map; + Image32F3 diffuse_map; Color Kd; Material() : Kd(Color::WHITE) {} Material(const String& _name) : name(_name), Kd(Color::WHITE) {} - Material(const Image8U3& _diffuse_map, const Color& _Kd=Color::WHITE); + Material(const Image32F3& _diffuse_map, const Color& _Kd=Color::WHITE); // Makes sure the image is loaded for the diffuse map bool LoadDiffuseMap(); diff --git a/libs/MVS/DepthMap.cpp b/libs/MVS/DepthMap.cpp index 9c4d77c8a..bf9992225 100644 --- a/libs/MVS/DepthMap.cpp +++ b/libs/MVS/DepthMap.cpp @@ -124,7 +124,7 @@ void DepthData::GetNormal(const ImageRef& ir, Point3f& N, const TImage* const int nPoints = 2*nPointsHalf+1; const int nWindowHalf = nPointsHalf*nPointsStep; const int nWindow = 2*nWindowHalf+1; - const Image8U::Size size(depthMap.size()); + const Image32F::Size size(depthMap.size()); const ImageRef ptCorner(ir.x-nWindowHalf, ir.y-nWindowHalf); const ImageRef ptCornerRel(ptCorner.x>=0?0:-ptCorner.x, ptCorner.y>=0?0:-ptCorner.y); Point3Arr points(1, nPoints*nPoints); @@ -229,7 +229,7 @@ unsigned DepthData::DecRef() // 1 2 3 // 1 2 4 7 5 3 6 8 9 --> 4 5 6 // 7 8 9 -void DepthEstimator::MapMatrix2ZigzagIdx(const Image8U::Size& size, DepthEstimator::MapRefArr& coords, const BitMatrix& mask, int rawStride) +void DepthEstimator::MapMatrix2ZigzagIdx(const Image32F::Size& size, DepthEstimator::MapRefArr& coords, const BitMatrix& mask, int rawStride) { typedef DepthEstimator::MapRef MapRef; const int w = size.width; @@ -1043,11 +1043,11 @@ void MVS::EstimatePointColors(const ImageArr& images, PointCloud& pointcloud) } if (pImageData == NULL) { // set a dummy color - color = Pixel8U::WHITE; + color = Pixel32F::WHITE; } else { // get image color const Point2f proj(pImageData->camera.ProjectPointP(point)); - color = (pImageData->image.isInsideWithBorder(proj) ? pImageData->image.sample(proj) : Pixel8U::WHITE); + color = (pImageData->image.isInsideWithBorder(proj) ? pImageData->image.sample(proj) : Pixel32F::WHITE); } } @@ -1169,7 +1169,7 @@ bool MVS::ExportDepthMap(const String& fileName, const DepthMap& depthMap, Depth } const Depth deltaDepth = maxDepth - minDepth; // save image - Image8U img(depthMap.size()); + Image32F img(depthMap.size()); for (int i=depthMap.area(); --i >= 0; ) { const Depth depth = depthMap[i]; img[i] = (depth > 0 ? (uint8_t)CLAMP((maxDepth-depth)*255.f/deltaDepth, 0.f, 255.f) : 0); @@ -1183,12 +1183,12 @@ bool MVS::ExportNormalMap(const String& fileName, const NormalMap& normalMap) { if (normalMap.empty()) return false; - Image8U3 img(normalMap.size()); + Image32F3 img(normalMap.size()); for (int i=normalMap.area(); --i >= 0; ) { img[i] = [](const Normal& n) { return ISZERO(n) ? - Image8U3::Type::BLACK : - Image8U3::Type( + Image32F3::Type::BLACK : + Image32F3::Type( CLAMP(ROUND2INT((1.f-n.x)*127.5f), 0, 255), CLAMP(ROUND2INT((1.f-n.y)*127.5f), 0, 255), CLAMP(ROUND2INT( -n.z *255.0f), 0, 255) @@ -1222,7 +1222,7 @@ bool MVS::ExportConfidenceMap(const String& fileName, const ConfidenceMap& confM DEBUG_ULTIMATE("\tconfidence range: [%g, %g]", minConf, maxConf); const float deltaConf = maxConf - minConf; // save image - Image8U img(confMap.size()); + Image32F img(confMap.size()); for (int i=confMap.area(); --i >= 0; ) { const float conf = confMap[i]; img[i] = (conf > 0 ? (uint8_t)CLAMP((conf-minConf)*255.f/deltaConf, 0.f, 255.f) : 0); @@ -1277,7 +1277,7 @@ bool MVS::ExportPointCloud(const String& fileName, const Image& imageData, const continue; const Point3f X(P0.TransformPointI2W(Point3(i,j,depth))); vertex.x = X.x; vertex.y = X.y; vertex.z = X.z; - const Pixel8U c(imageData.image.empty() ? Pixel8U::WHITE : imageData.image(j,i)); + const Pixel32F c(imageData.image.empty() ? Pixel32F::WHITE : imageData.image(j,i)); vertex.r = c.r; vertex.g = c.g; vertex.b = c.b; ply.put_element(&vertex); } @@ -1335,7 +1335,7 @@ bool MVS::ExportPointCloud(const String& fileName, const Image& imageData, const vertex.x = X.x; vertex.y = X.y; vertex.z = X.z; const Point3f N(P0.R.t() * Cast(normalMap(j,i))); vertex.nx = N.x; vertex.ny = N.y; vertex.nz = N.z; - const Pixel8U c(imageData.image.empty() ? Pixel8U::WHITE : imageData.image(j, i)); + const Pixel32F c(imageData.image.empty() ? Pixel32F::WHITE : imageData.image(j, i)); vertex.r = c.r; vertex.g = c.g; vertex.b = c.b; ply.put_element(&vertex); } @@ -1391,35 +1391,35 @@ void MVS::CompareDepthMaps(const DepthMap& depthMap, const DepthMap& depthMapGT, const std::pair th(ComputeX84Threshold(errors.Begin(), errors.GetSize())); #if TD_VERBOSE != TD_VERBOSE_OFF IDX idxPixel = 0; - Image8U3 errorsVisual(depthMap.size()); + Image32F3 errorsVisual(depthMap.size()); for (uint32_t i=0; i threshold) { - pix = Pixel8U::RED; + pix = Pixel32F::RED; ++nErrorPixels; continue; } const uint8_t gray((uint8_t)CLAMP((1.f-SAFEDIVIDE(ABS(error), threshold))*255.f, 0.f, 255.f)); - pix = Pixel8U(gray, gray, gray); + pix = Pixel32F(gray, gray, gray); } } - errorsVisual.Save(ComposeDepthFilePath(idxImage, "errors.png")); + errorsVisual.Save(ComposeDepthFilePath(idxImage, "errors.exr")); #endif VERBOSE("Depth-maps compared for image % 3u: %.4f PSNR; %g median %g mean %g stddev error; %u (%.2f%%%%) error %u (%.2f%%%%) missing %u (%.2f%%%%) extra pixels (%s)", idxImage, diff --git a/libs/MVS/DepthMap.h b/libs/MVS/DepthMap.h index 426b8b6d1..29138bda8 100644 --- a/libs/MVS/DepthMap.h +++ b/libs/MVS/DepthMap.h @@ -314,7 +314,7 @@ struct MVS_API DepthEstimator { const Image64F& image0Sum; // integral image used to fast compute patch mean intensity #endif const MapRefArr& coords; - const Image8U::Size size; + const Image32F::Size size; const Depth dMin, dMax; const Depth dMinSqr, dMaxSqr; const ENDIRECTION dir; @@ -413,7 +413,7 @@ struct MVS_API DepthEstimator { normal = RMatrixBaseF(normal.cross(viewDir), MINF((ACOS(cosAngLen/norm(viewDir))-FD2R(90.f))*1.01f, -0.001f)) * normal; } - static void MapMatrix2ZigzagIdx(const Image8U::Size& size, DepthEstimator::MapRefArr& coords, const BitMatrix& mask, int rawStride=16); + static void MapMatrix2ZigzagIdx(const Image32F::Size& size, DepthEstimator::MapRefArr& coords, const BitMatrix& mask, int rawStride=16); const float smoothBonusDepth, smoothBonusNormal; const float smoothSigmaDepth, smoothSigmaNormal; diff --git a/libs/MVS/Image.cpp b/libs/MVS/Image.cpp index c5454b665..5ecbfebfe 100644 --- a/libs/MVS/Image.cpp +++ b/libs/MVS/Image.cpp @@ -63,7 +63,7 @@ IMAGEPTR Image::ReadImageHeader(const String& fileName) } // ReadImageHeader /*----------------------------------------------------------------*/ -IMAGEPTR Image::ReadImage(const String& fileName, Image8U3& image) +IMAGEPTR Image::ReadImage(const String& fileName, Image32F3& image) { IMAGEPTR pImage(OpenImage(fileName)); if (pImage != NULL && !ReadImage(pImage, image)) @@ -72,14 +72,15 @@ IMAGEPTR Image::ReadImage(const String& fileName, Image8U3& image) } // ReadImage /*----------------------------------------------------------------*/ -bool Image::ReadImage(IMAGEPTR pImage, Image8U3& image) +bool Image::ReadImage(IMAGEPTR pImage, Image32F3& image) { if (FAILED(pImage->ReadHeader())) { LOG("error: failed loading image header"); return false; } image.create(pImage->GetHeight(), pImage->GetWidth()); - if (FAILED(pImage->ReadData(image.data, PF_R8G8B8, 3, (CImage::Size)image.step))) { + if (FAILED(pImage->ReadData(image.data, PF_R32G32B32, 12, (CImage::Size)image.step))) { + //if (FAILED(pImage->ReadData(image.data, PF_R8G8B8, 3, (CImage::Size)image.step))) { LOG("error: failed loading image data"); return false; } @@ -166,16 +167,16 @@ unsigned Image::RecomputeMaxResolution(unsigned& level, unsigned minImageSize, u IMAGEPTR pImage(ReadImageHeader(name)); if (pImage == NULL) { // something went wrong, use the current known size (however it will most probably fail later) - return Image8U3::computeMaxResolution(width, height, level, minImageSize, maxImageSize); + return Image32F3::computeMaxResolution(width, height, level, minImageSize, maxImageSize); } // re-compute max image size - return Image8U3::computeMaxResolution(pImage->GetWidth(), pImage->GetHeight(), level, minImageSize, maxImageSize); + return Image32F3::computeMaxResolution(pImage->GetWidth(), pImage->GetHeight(), level, minImageSize, maxImageSize); } // RecomputeMaxResolution /*----------------------------------------------------------------*/ // compute the camera extrinsics from the platform pose and the relative camera pose to the platform -Camera Image::GetCamera(const PlatformArr& platforms, const Image8U::Size& resolution) const +Camera Image::GetCamera(const PlatformArr& platforms, const Image32F::Size& resolution) const { ASSERT(platformID != NO_ID); ASSERT(cameraID != NO_ID); @@ -193,7 +194,7 @@ Camera Image::GetCamera(const PlatformArr& platforms, const Image8U::Size& resol } // GetCamera void Image::UpdateCamera(const PlatformArr& platforms) { - camera = GetCamera(platforms, Image8U::Size(width, height)); + camera = GetCamera(platforms, Image32F::Size(width, height)); } // UpdateCamera // computes camera's field of view for the given direction REAL Image::ComputeFOV(int dir) const diff --git a/libs/MVS/Image.h b/libs/MVS/Image.h index 20d68065e..d69b908f2 100644 --- a/libs/MVS/Image.h +++ b/libs/MVS/Image.h @@ -81,7 +81,7 @@ class MVS_API Image String name; // image file name (relative path) Camera camera; // view's pose uint32_t width, height; // image size - Image8U3 image; // image color pixels + Image32F3 image; // image color pixels ViewScoreArr neighbors; // score&store the neighbor images float scale; // image scale relative to the original size float avgDepth; // average depth of the points seen by this camera @@ -94,20 +94,20 @@ class MVS_API Image } inline bool IsValid() const { return poseID != NO_ID; } - inline Image8U::Size GetSize() const { return Image8U::Size(width, height); } + inline Image32F::Size GetSize() const { return Image32F::Size(width, height); } // read image data from the file static IMAGEPTR OpenImage(const String& fileName); static IMAGEPTR ReadImageHeader(const String& fileName); - static IMAGEPTR ReadImage(const String& fileName, Image8U3& image); - static bool ReadImage(IMAGEPTR pImage, Image8U3& image); + static IMAGEPTR ReadImage(const String& fileName, Image32F3& image); + static bool ReadImage(IMAGEPTR pImage, Image32F3& image); bool LoadImage(const String& fileName, unsigned nMaxResolution=0); bool ReloadImage(unsigned nMaxResolution=0, bool bLoadPixels=true); void ReleaseImage(); float ResizeImage(unsigned nMaxResolution=0); unsigned RecomputeMaxResolution(unsigned& level, unsigned minImageSize, unsigned maxImageSize=INT_MAX) const; - Camera GetCamera(const PlatformArr& platforms, const Image8U::Size& resolution) const; + Camera GetCamera(const PlatformArr& platforms, const Image32F::Size& resolution) const; void UpdateCamera(const PlatformArr& platforms); REAL ComputeFOV(int dir) const; diff --git a/libs/MVS/Interface.h b/libs/MVS/Interface.h index 18c586897..7938b2c2d 100644 --- a/libs/MVS/Interface.h +++ b/libs/MVS/Interface.h @@ -355,7 +355,8 @@ struct Interface typedef cv::Point3_ Pos3d; typedef cv::Matx Mat33d; typedef cv::Matx Mat44d; - typedef cv::Point3_ Col3; // x=B, y=G, z=R + //typedef cv::Point3_ Col3; // x=B, y=G, z=R + typedef cv::Point3_ Col3; // x=B, y=G, z=R /*----------------------------------------------------------------*/ // structure describing a mobile platform with cameras attached to it diff --git a/libs/MVS/Mesh.cpp b/libs/MVS/Mesh.cpp index 48ee5a1f9..75ee8a3bb 100644 --- a/libs/MVS/Mesh.cpp +++ b/libs/MVS/Mesh.cpp @@ -1459,7 +1459,7 @@ bool Mesh::SavePLY(const String& fileName, const cList& comments, bool b // export texture file name as comment if needed String textureFileName; if (!faceTexcoords.IsEmpty() && !textureDiffuse.empty()) { - textureFileName = Util::getFileFullName(fileName)+_T(".png"); + textureFileName = Util::getFileFullName(fileName)+_T(".exr"); ply.append_comment((_T("TextureFile ")+Util::getFileNameExt(textureFileName)).c_str()); } @@ -2221,16 +2221,16 @@ static int ImproveVertexValence(Polyhedron& p, int valence_mode=2) static void UpdateMeshData(Polyhedron& p); -// Description: +// Description: // It iterates through all the mesh vertices and it tries to fix degenerate triangles. // There are conditions that check for large and small angles. // Parameters: -// - degenerateAngleDeg +// - degenerateAngleDeg // - for large angles: if an angle is bigger than degenerateAngleDeg. // - a good values to use is typically 170 -// - collapseRatio +// - collapseRatio // - for small angles: given the corresponding edges (a,b,c) in all permutations, if (a/b < collapseRatio) & (a/c < collapseRatio) -// - a good value to use is 0.1 +// - a good value to use is 0.1 static int FixDegeneracy(Polyhedron& p, double collapseRatio, double degenerateAngleDeg) { DEBUG_LEVEL(3, "Fix degeneracy: %g collapse-ratio, %g degenerate-angle", collapseRatio, degenerateAngleDeg); @@ -2440,7 +2440,7 @@ static void Smooth(Polyhedron& p, double delta, int mode=0) } -// Description: +// Description: // - The goal of this method is to ensure that all the edges of the mesh are within the interval [epsilonMin,epsilonMax]. // In order to do so, edge collapses and edge split operations are performed. // - The method also attempts to fix degeneracies by invoking FixDegeneracy(collapseRatio,degenerate_angle_deg) and performs some local smoothing, based on the operating mode. @@ -2451,7 +2451,7 @@ static void Smooth(Polyhedron& p, double delta, int mode=0) // 1 - fixDegeneracy=Yes smoothing=Yes; (default) // 10 - fixDegeneracy=Yes smoothing=No; // - max_iter (default=30) - maximum number of iterations to be performed; since there is no guarantee that one operations (such as a collapse, for example) -// will not in turn generate new degeneracies, operations are being performed on the mesh in an iterative fashion. +// will not in turn generate new degeneracies, operations are being performed on the mesh in an iterative fashion. static void EnsureEdgeSize(Polyhedron& p, double epsilonMin, double epsilonMax, double collapseRatio, double degenerate_angle_deg, int mode, int max_iters, int comp_size_threshold) { if (mode>0) @@ -2546,7 +2546,7 @@ static void EnsureEdgeSize(Polyhedron& p, double epsilonMin, double epsilonMax, ComputeStatsEdge(p, edge); VERBOSE("Edge size in [%g, %g] (requested in [%g, %g]): %d ops, %d iters", edge.min, edge.max, epsilonMin, epsilonMax, total_no_ops, iters); } - #endif + #endif } static void ComputeVertexNormals(Polyhedron& p) @@ -2579,7 +2579,7 @@ static std::vector< std::pair > GetRingNeighbourhood(Vertex& v, in std::queue elems; std::vector< std::pair > result; - // add base level + // add base level elems.push(&v); neigh_map[&v]=0; @@ -2690,7 +2690,7 @@ static void UpdateMeshData(Polyhedron& p) // compute vertex normal ComputeVertexNormals(p); #if ROBUST_NORMALS>0 - // compute robust vertex normal + // compute robust vertex normal for (Vertex_iterator vi=p.vertices_begin(); vi!=p.vertices_end(); vi++) ComputeVertexRobustNormal(*vi, ROBUST_NORMALS); #endif @@ -2709,7 +2709,7 @@ static void UpdateMeshData(Polyhedron& p) ComputeVertexLaplacianDeriv(*vi); } - // set border edges + // set border edges for (Halfedge_iterator hi=p.border_halfedges_begin(); hi!=p.halfedges_end(); hi++) hi->vertex()->setBorder(); } @@ -2729,7 +2729,7 @@ class TMeshBuilder : public CGAL::Modifier_base typedef typename HDS::Vertex::Point Point; CGAL::Polyhedron_incremental_builder_3 B(hds, false); B.begin_surface(vertices.GetSize(), faces.GetSize()); - // add the vertices + // add the vertices FOREACH(i, vertices) { const Mesh::Vertex& v = vertices[i]; B.add_vertex(Point(v.x, v.y, v.z)); @@ -3540,16 +3540,16 @@ void Mesh::Project(const Camera& camera, DepthMap& depthMap) const for (const Face& facet: faces) rasterer.Project(facet); } -void Mesh::Project(const Camera& camera, DepthMap& depthMap, Image8U3& image) const +void Mesh::Project(const Camera& camera, DepthMap& depthMap, Image32F3& image) const { ASSERT(!faceTexcoords.IsEmpty() && !textureDiffuse.empty()); struct RasterMesh : TRasterMesh { typedef TRasterMesh Base; const Mesh& mesh; - Image8U3& image; + Image32F3& image; FIndex idxFaceTex; TexCoord xt; - RasterMesh(const Mesh& _mesh, const Camera& _camera, DepthMap& _depthMap, Image8U3& _image) + RasterMesh(const Mesh& _mesh, const Camera& _camera, DepthMap& _depthMap, Image32F3& _image) : Base(_mesh.vertices, _camera, _depthMap), mesh(_mesh), image(_image) {} inline void Clear() { Base::Clear(); @@ -3609,16 +3609,16 @@ void Mesh::ProjectOrtho(const Camera& camera, DepthMap& depthMap) const for (const Face& facet: faces) rasterer.Project(facet); } -void Mesh::ProjectOrtho(const Camera& camera, DepthMap& depthMap, Image8U3& image) const +void Mesh::ProjectOrtho(const Camera& camera, DepthMap& depthMap, Image32F3& image) const { ASSERT(!faceTexcoords.IsEmpty() && !textureDiffuse.empty()); struct RasterMesh : TRasterMesh { typedef TRasterMesh Base; const Mesh& mesh; - Image8U3& image; + Image32F3& image; FIndex idxFaceTex; TexCoord xt; - RasterMesh(const Mesh& _mesh, const Camera& _camera, DepthMap& _depthMap, Image8U3& _image) + RasterMesh(const Mesh& _mesh, const Camera& _camera, DepthMap& _depthMap, Image32F3& _image) : Base(_mesh.vertices, _camera, _depthMap), mesh(_mesh), image(_image) {} inline void Clear() { Base::Clear(); @@ -3661,7 +3661,7 @@ void Mesh::ProjectOrtho(const Camera& camera, DepthMap& depthMap, Image8U3& imag } } // assuming the mesh is properly oriented, ortho-project it to a camera looking from top to down -void Mesh::ProjectOrthoTopDown(unsigned resolution, Image8U3& image, Image8U& mask, Point3& center) const +void Mesh::ProjectOrthoTopDown(unsigned resolution, Image32F3& image, Image32F& mask, Point3& center) const { ASSERT(!IsEmpty() && !textureDiffuse.empty()); // initialize camera diff --git a/libs/MVS/Mesh.h b/libs/MVS/Mesh.h index 09da00aed..0ebab0814 100644 --- a/libs/MVS/Mesh.h +++ b/libs/MVS/Mesh.h @@ -94,7 +94,7 @@ class MVS_API Mesh NormalArr faceNormals; // for each face, the normal to it (optional) TexCoordArr faceTexcoords; // for each face, the texture-coordinates corresponding to the contained vertices (optional) - Image8U3 textureDiffuse; // texture containing the diffuse color (optional) + Image32F3 textureDiffuse; // texture containing the diffuse color (optional) #ifdef _USE_CUDA static CUDA::KernelRT kernelComputeFaceNormal; @@ -162,10 +162,10 @@ class MVS_API Mesh void SamplePoints(REAL samplingDensity, unsigned mumPointsTheoretic, PointCloud&) const; void Project(const Camera& camera, DepthMap& depthMap) const; - void Project(const Camera& camera, DepthMap& depthMap, Image8U3& image) const; + void Project(const Camera& camera, DepthMap& depthMap, Image32F3& image) const; void ProjectOrtho(const Camera& camera, DepthMap& depthMap) const; - void ProjectOrtho(const Camera& camera, DepthMap& depthMap, Image8U3& image) const; - void ProjectOrthoTopDown(unsigned resolution, Image8U3& image, Image8U& mask, Point3& center) const; + void ProjectOrtho(const Camera& camera, DepthMap& depthMap, Image32F3& image) const; + void ProjectOrthoTopDown(unsigned resolution, Image32F3& image, Image32F& mask, Point3& center) const; // file IO bool Load(const String& fileName); @@ -263,7 +263,7 @@ struct TRasterMesh { if (!static_cast(this)->CheckNormal(faceCenter)) return; // draw triangle and for each pixel compute depth as the ray intersection with the plane - Image8U3::RasterizeTriangle(pti[0], pti[1], pti[2], *this); + Image32F3::RasterizeTriangle(pti[0], pti[1], pti[2], *this); } void Raster(const ImageRef& pt) { diff --git a/libs/MVS/PointCloud.h b/libs/MVS/PointCloud.h index ce2a9722d..b8fff93aa 100644 --- a/libs/MVS/PointCloud.h +++ b/libs/MVS/PointCloud.h @@ -65,7 +65,7 @@ class MVS_API PointCloud typedef TPoint3 Normal; typedef CLISTDEF0(Normal) NormalArr; - typedef Pixel8U Color; + typedef Pixel32F Color; typedef CLISTDEF0(Color) ColorArr; typedef AABB3f Box; diff --git a/libs/MVS/Scene.cpp b/libs/MVS/Scene.cpp index 7932ae348..06b29f59e 100644 --- a/libs/MVS/Scene.cpp +++ b/libs/MVS/Scene.cpp @@ -179,7 +179,7 @@ bool Scene::LoadInterface(const String & fileName) } if (!obj.verticesColor.empty()) { ASSERT(obj.vertices.size() == obj.verticesColor.size()); - pointcloud.colors.CopyOf((const Pixel8U*)&obj.verticesColor[0].c, obj.vertices.size()); + pointcloud.colors.CopyOf((const Pixel32F*)&obj.verticesColor[0].c, obj.vertices.size()); } } diff --git a/libs/MVS/Scene.h b/libs/MVS/Scene.h index 4c6c66ec5..7917b7c74 100644 --- a/libs/MVS/Scene.h +++ b/libs/MVS/Scene.h @@ -96,7 +96,7 @@ class MVS_API Scene #endif // Mesh texturing - bool TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, float fOutlierThreshold=0.f, float fRatioDataSmoothness=0.3f, bool bGlobalSeamLeveling=true, bool bLocalSeamLeveling=true, unsigned nTextureSizeMultiple=0, unsigned nRectPackingHeuristic=3, Pixel8U colEmpty=Pixel8U(255,127,39), bool reTexture=false); + bool TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, float fOutlierThreshold=0.f, float fRatioDataSmoothness=0.3f, bool bGlobalSeamLeveling=true, bool bLocalSeamLeveling=true, unsigned nTextureSizeMultiple=0, unsigned nRectPackingHeuristic=3, Pixel32F colEmpty=Pixel32F(1,0.498,0.1529), bool reTexture=false); #ifdef _USE_BOOST // implement BOOST serialization diff --git a/libs/MVS/SceneDensify.cpp b/libs/MVS/SceneDensify.cpp index 8424f7cfa..e1518cac9 100644 --- a/libs/MVS/SceneDensify.cpp +++ b/libs/MVS/SceneDensify.cpp @@ -158,8 +158,8 @@ class DepthMapsData DepthDataArr arrDepthData; // used internally to estimate the depth-maps - Image8U::Size prevDepthMapSize; // remember the size of the last estimated depth-map - Image8U::Size prevDepthMapSizeTrg; // ... same for target image + Image32F::Size prevDepthMapSize; // remember the size of the last estimated depth-map + Image32F::Size prevDepthMapSizeTrg; // ... same for target image DepthEstimator::MapRefArr coords; // map pixel index to zigzag matrix coordinates DepthEstimator::MapRefArr coordsTrg; // ... same for target image }; @@ -550,7 +550,7 @@ bool DepthMapsData::InitDepthMap(DepthData& depthData) data.normal = normalized(edge2.cross(edge1)); data.normalPlane = data.normal * INVERT(data.normal.dot(c0)); // draw triangle and for each pixel compute depth as the ray intersection with the plane - Image8U::RasterizeTriangle(reinterpret_cast(i2), reinterpret_cast(i1), reinterpret_cast(i0), data); + Image32F::RasterizeTriangle(reinterpret_cast(i2), reinterpret_cast(i1), reinterpret_cast(i0), data); } DEBUG_ULTIMATE("Depth-map %3u roughly estimated from %u sparse points: %dx%d (%s)", &depthData-arrDepthData.Begin(), depthData.points.GetSize(), image.image.width(), image.image.height(), TD_TIMER_GET_FMT().c_str()); @@ -670,7 +670,7 @@ bool DepthMapsData::EstimateDepthMap(IIndex idxImage) ASSERT(depthData.images.GetSize() > 1 && !depthData.points.IsEmpty()); const DepthData::ViewData& image(depthData.images.First()); ASSERT(!image.image.empty() && !depthData.images[1].image.empty()); - const Image8U::Size size(image.image.size()); + const Image32F::Size size(image.image.size()); depthData.depthMap.create(size); depthData.depthMap.memset(0); depthData.normalMap.create(size); depthData.confMap.create(size); @@ -970,7 +970,7 @@ bool DepthMapsData::GapInterpolation(DepthData& depthData) const Depth avg((depthFirst+depth)*0.5f); do { depthMap(v,u_curr) = avg; - } while (++u_curr(view.imageHost))); @@ -2548,7 +2548,7 @@ void MeshRefineCUDA::ScoreMesh(float* gradients) // project mesh to the given camera plane void MeshRefineCUDA::ProjectMesh( const CameraFaces& cameraFaces, - const Camera& camera, const Image8U::Size& size, uint32_t idxImage) + const Camera& camera, const Image32F::Size& size, uint32_t idxImage) { View& view = views[idxImage]; // init depth-map @@ -2594,7 +2594,7 @@ void MeshRefineCUDA::ProcessPair(uint32_t idxImageA, uint32_t idxImageB) const Image& imageDataA = images[idxImageA]; ASSERT(imageDataA.IsValid()); const Camera& cameraA = imageDataA.camera; - const Image8U::Size& sizeA(views[idxImageA].size); + const Image32F::Size& sizeA(views[idxImageA].size); // fetch view B data const Image& imageDataB = images[idxImageB]; ASSERT(imageDataB.IsValid()); @@ -2612,7 +2612,7 @@ void MeshRefineCUDA::ProcessPair(uint32_t idxImageA, uint32_t idxImageB) // project image from view B to view A through the mesh; // the projected image is stored in imageA void MeshRefineCUDA::ImageMeshWarp( - const Camera& cameraA, const Camera& cameraB, const Image8U::Size& size, + const Camera& cameraA, const Camera& cameraB, const Image32F::Size& size, uint32_t idxImageA, uint32_t idxImageB) { // set image texture @@ -2629,7 +2629,7 @@ void MeshRefineCUDA::ImageMeshWarp( #if 0 // debug view Image16F _imageAB(size); - Image8U _mask(size); + Image32F _mask(size); imageAB.GetData(_imageAB); mask.GetData(_mask); Image32F __imageAB(cvtImage(_imageAB)); @@ -2637,7 +2637,7 @@ void MeshRefineCUDA::ImageMeshWarp( } // compute local variance for each image pixel -void MeshRefineCUDA::ComputeLocalVariance(const CUDA::ArrayRT16F& image, const Image8U::Size& size, +void MeshRefineCUDA::ComputeLocalVariance(const CUDA::ArrayRT16F& image, const Image32F::Size& size, CUDA::MemDevice& imageMean, CUDA::MemDevice& imageVar) { surfImageRef.Bind(image); @@ -2664,7 +2664,7 @@ void MeshRefineCUDA::ComputeLocalVariance(const CUDA::ArrayRT16F& image, const I } // compute local ZNCC and its gradient for each image pixel -void MeshRefineCUDA::ComputeLocalZNCC(const Image8U::Size& size) +void MeshRefineCUDA::ComputeLocalZNCC(const Image32F::Size& size) { reportCudaError(kernelComputeImageCov(size, imageMeanA, @@ -2704,7 +2704,7 @@ void MeshRefineCUDA::ComputeLocalZNCC(const Image8U::Size& size) } // compute the photometric gradient for all vertices seen by an image pair -void MeshRefineCUDA::ComputePhotometricGradient(const Camera& cameraA, const Camera& cameraB, const Image8U::Size& size, +void MeshRefineCUDA::ComputePhotometricGradient(const Camera& cameraA, const Camera& cameraB, const Image32F::Size& size, uint32_t idxImageA, uint32_t idxImageB, uint32_t numVertices, float RegularizationScale) { // compute photometric gradient for all visible vertices @@ -2758,7 +2758,7 @@ void MeshRefineCUDA::ComputeSmoothnessGradient(uint32_t numVertices) numVertices, uint8_t(1) )); - #if 0 + #if 0 // debug view Point3fArr _smoothGrad1(numVertices); Point3fArr _smoothGrad2(numVertices); @@ -2793,7 +2793,7 @@ void MeshRefineCUDA::CombineGradients(uint32_t numVertices) elasticity )); } - #if 0 + #if 0 // debug view Point3fArr _photoGrad(numVertices); photoGrad.GetData(_photoGrad); diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index fb19befd1..afa577f39 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -143,11 +143,11 @@ typedef int MatIdx; typedef Eigen::Triplet MatEntry; typedef Eigen::SparseMatrix SparseMat; -enum Mask { - empty = 0, - border = 128, - interior = 255 -}; +// enum Mask { +// empty = 0, +// border = 128, +// interior = 255 +// }; struct MeshTexture { // used to render the surface to a view camera @@ -334,10 +334,10 @@ struct MeshTexture { typedef Sampler::Linear Sampler; struct SampleImage { AccumColor accumColor; - const Image8U3& image; + const Image32F3& image; const Sampler sampler; - inline SampleImage(const Image8U3& _image) : image(_image), sampler() {} + inline SampleImage(const Image32F3& _image) : image(_image), sampler() {} // sample the edge with linear weights void AddEdge(const TexCoord& p0, const TexCoord& p1) { const TexCoord p01(p1 - p0); @@ -381,27 +381,27 @@ struct MeshTexture { // used to compute the coverage of a texture patch struct RasterPatchCoverageData { const TexCoord* tri; - Image8U& image; + Image32F& image; - inline RasterPatchCoverageData(Image8U& _image) : image(_image) {} + inline RasterPatchCoverageData(Image32F& _image) : image(_image) {} inline void operator()(const ImageRef& pt) { ASSERT(image.isInside(pt)); - image(pt) = interior; + image(pt) = 1.f; } }; // used to draw the average edge color of a texture patch struct RasterPatchMeanEdgeData { Image32F3& image; - Image8U& mask; + Image32F& mask; const Image32F3& image0; - const Image8U3& image1; + const Image32F3& image1; const TexCoord p0, p0Dir; const TexCoord p1, p1Dir; const float length; const Sampler sampler; - inline RasterPatchMeanEdgeData(Image32F3& _image, Image8U& _mask, const Image32F3& _image0, const Image8U3& _image1, + inline RasterPatchMeanEdgeData(Image32F3& _image, Image32F& _mask, const Image32F3& _image0, const Image32F3& _image1, const TexCoord& _p0, const TexCoord& _p0Adj, const TexCoord& _p1, const TexCoord& _p1Adj) : image(_image), mask(_mask), image0(_image0), image1(_image1), p0(_p0), p0Dir(_p0Adj-_p0), p1(_p1), p1Dir(_p1Adj-_p1), length((float)norm(p0Dir)), sampler() {} @@ -411,10 +411,11 @@ struct MeshTexture { const TexCoord samplePos0(p0 + p0Dir * l); AccumColor accumColor(image0.sample(sampler, samplePos0), 1.f); const TexCoord samplePos1(p1 + p1Dir * l); - accumColor.Add(image1.sample(sampler, samplePos1)/255.f, 1.f); + //accumColor.Add(image1.sample(sampler, samplePos1)/255.f, 1.f); + accumColor.Add(image1.sample(sampler, samplePos1)/1.f, 1.f); image(pt) = accumColor.Normalized(); // set mask edge also - mask(pt) = border; + mask(pt) = 0.5f; } }; @@ -438,7 +439,7 @@ struct MeshTexture { void CreateSeamVertices(); void GlobalSeamLeveling(); void LocalSeamLeveling(); - void GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty, bool reTexture); + void GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel32F colEmpty, bool reTexture); template static inline PIXEL RGB2YCBCR(const PIXEL& v) { @@ -463,8 +464,8 @@ struct MeshTexture { protected: - static void ProcessMask(Image8U& mask, int stripWidth); - static void PoissonBlending(const Image32F3& src, Image32F3& dst, const Image8U& mask, float bias=1.f); + static void ProcessMask(Image32F& mask, int stripWidth); + static void PoissonBlending(const Image32F3& src, Image32F3& dst, const Image32F& mask, float bias=1.f); public: @@ -484,7 +485,7 @@ struct MeshTexture { Mesh::VertexFacesArr& vertexFaces; // for each vertex, the list of faces containing it BoolArr& vertexBoundary; // for each vertex, stores if it is at the boundary or not Mesh::TexCoordArr& faceTexcoords; // for each face, the texture-coordinates of the vertices - Image8U3& textureDiffuse; // texture containing the diffuse color + Image32F3& textureDiffuse; // texture containing the diffuse color // constant the entire time Mesh::VertexArr& vertices; @@ -704,7 +705,8 @@ bool MeshTexture::FaceOutlierDetection(FaceDataArr& faceDatas, float thOutlier) { // consider as outlier if the absolute difference to the median is outside this threshold if (thOutlier <= 0) - thOutlier = 0.15f*255.f; + //thOutlier = 0.15f*255.f; + thOutlier = 0.15f*1.f; // init colors array if (faceDatas.GetSize() <= 3) @@ -1516,11 +1518,11 @@ void MeshTexture::GlobalSeamLeveling() const Color& a = imageAdj(r,c); if (a == Color::ZERO) continue; - Pixel8U& v = image.at(r,c); + Pixel32F& v = image.at(r,c); const Color col(RGB2YCBCR(Color(v))); const Color acol(YCBCR2RGB(Color(col+a))); - for (int p=0; p<3; ++p) - v[p] = (uint8_t)CLAMP(ROUND2INT(acol[p]), 0, 255); + // for (int p=0; p<3; ++p) + // v[p] = (uint8_t)CLAMP(ROUND2INT(acol[p]), 0, 255); } } } @@ -1529,17 +1531,17 @@ void MeshTexture::GlobalSeamLeveling() // set to one in order to dilate also on the diagonal of the border // (normally not needed) #define DILATE_EXTRA 0 -void MeshTexture::ProcessMask(Image8U& mask, int stripWidth) +void MeshTexture::ProcessMask(Image32F& mask, int stripWidth) { - typedef Image8U::Type Type; + typedef Image32F::Type Type; // dilate and erode around the border, // in order to fill all gaps and remove outside pixels // (due to imperfect overlay of the raster line border and raster faces) #define DILATEDIR(rd,cd) { \ Type& vi = mask(r+(rd),c+(cd)); \ - if (vi != border) \ - vi = interior; \ + if (vi != 0.5f) \ + vi = 1.f; \ } const int HalfSize(1); const int RowsEnd(mask.rows-HalfSize); @@ -1547,7 +1549,7 @@ void MeshTexture::ProcessMask(Image8U& mask, int stripWidth) for (int r=HalfSize; r PixelSet; PixelSet borderPixels; @@ -1661,7 +1663,7 @@ void MeshTexture::ProcessMask(Image8U& mask, int stripWidth) // iteratively erode all border pixels { - Image8U orgMask; + Image32F orgMask; mask.copyTo(orgMask); typedef std::vector PixelVector; for (int s=0; s(sampler, patch.proj)/255.f, 1.f); + const Image32F3& img(images[texturePatches[patch.idxPatch].label].image); + //accumColor.Add(img.sample(sampler, patch.proj)/255.f, 1.f); + accumColor.Add(img.sample(sampler, patch.proj)/1.f, 1.f); } const SeamVertex::Patch& thisPatch = seamVertex.patches[idxVertPatch]; - const ImageRef pt(ROUND2INT(thisPatch.proj-offset)); + //const ImageRef pt(ROUND2INT(thisPatch.proj-offset)); + const ImageRef pt(thisPatch.proj-offset); image(pt) = accumColor.Normalized(); - mask(pt) = border; + mask(pt) = 0.5f; } // make sure the border is continuous and // keep only the exterior tripe of the given size @@ -1914,18 +1918,18 @@ void MeshTexture::LocalSeamLeveling() cv::Mat imagePatch(images[texturePatch.label].image(texturePatch.rect)); for (int r=0; r(r,c); - for (int p=0; p<3; ++p) - v[p] = (uint8_t)CLAMP(ROUND2INT(a[p]*255.f), 0, 255); + Pixel32F& v = imagePatch.at(r,c); + // for (int p=0; p<3; ++p) + // v[p] = (uint8_t)CLAMP(ROUND2INT(a[p]*255.f), 0, 255); } } } } -void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty, bool reTexture) +void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel32F colEmpty, bool reTexture) { // project patches in the corresponding view and compute texture-coordinates and bounding-box const int border(2); @@ -2073,7 +2077,7 @@ void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLevel // create texture image const float invNorm(1.f/(float)(textureSize-1)); textureDiffuse.create(textureSize, textureSize); - textureDiffuse.setTo(cv::Scalar(colEmpty.b, colEmpty.g, colEmpty.r)); + textureDiffuse.setTo(cv::Scalar(pow(colEmpty.b/255.f,2.2), pow(colEmpty.g/255.f,2.2), pow(colEmpty.r/255.f,2.2))); // backup patches/atlas if(reTexture ==0){ @@ -2152,7 +2156,7 @@ void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLevel } // texture mesh -bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, float fOutlierThreshold, float fRatioDataSmoothness, bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel8U colEmpty, bool reTexture) +bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, float fOutlierThreshold, float fRatioDataSmoothness, bool bGlobalSeamLeveling, bool bLocalSeamLeveling, unsigned nTextureSizeMultiple, unsigned nRectPackingHeuristic, Pixel32F colEmpty, bool reTexture) { MeshTexture texture(*this, nResolutionLevel, nMinResolution);