Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export masks to openMVS #2168

Merged
merged 1 commit into from
Feb 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/software/SfM/export/InterfaceMVS.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// D E F I N E S ///////////////////////////////////////////////////

#define MVSI_PROJECT_ID "MVSI" // identifies the project stream
#define MVSI_PROJECT_VER ((uint32_t)2) // identifies the version of a project stream
#define MVSI_PROJECT_VER ((uint32_t)5) // identifies the version of a project stream

// set a default namespace name is none given
#ifndef _INTERFACE_NAMESPACE
Expand Down Expand Up @@ -308,6 +308,7 @@ struct Interface
// structure describing a camera mounted on a platform
struct Camera {
std::string name; // camera's name
std::string bandName; // camera's band name, ex: RGB, BLUE, GREEN, RED, NIR, THERMAL, etc (optional)
uint32_t width, height; // image resolution in pixels for all images sharing this camera (optional)
Mat33d K; // camera's intrinsics matrix (normalized if image resolution not specified)
Mat33d R; // camera's rotation matrix relative to the platform
Expand All @@ -320,6 +321,9 @@ struct Interface
template <class Archive>
void serialize(Archive& ar, const unsigned int version) {
ar & name;
if (version > 3) {
ar& bandName;
}
if (version > 0) {
ar & width;
ar & height;
Expand Down Expand Up @@ -361,16 +365,24 @@ struct Interface
// structure describing an image
struct Image {
std::string name; // image file name
std::string maskName; // segmentation file name (optional)
uint32_t platformID; // ID of the associated platform
uint32_t cameraID; // ID of the associated camera on the associated platform
uint32_t poseID; // ID of the pose of the associated platform
uint32_t ID; // ID of this image in the global space (optional)

template <class Archive>
void serialize(Archive& ar, const unsigned int /*version*/) {
void serialize(Archive& ar, const unsigned int version) {
ar & name;
if (version > 4) {
ar& maskName;
}
ar & platformID;
ar & cameraID;
ar & poseID;
if (version > 2) {
ar& ID;
}
}
};
typedef std::vector<Image> ImageArr;
Expand Down
75 changes: 71 additions & 4 deletions src/software/SfM/export/main_openMVG2openMVS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,17 @@ bool exportToOpenMVS(

// define images & poses
scene.images.reserve(nViews);

const std::string mask_filename_global = stlplus::create_filespec(sfm_data.s_root_path, "mask", "png");

for (const auto& view : sfm_data.GetViews())
{
++my_progress_bar;

IntrinsicBase *intrinsic = sfm_data.GetIntrinsics().at(view.second.get()->id_intrinsic).get();
const std::string srcImage = stlplus::create_filespec(sfm_data.s_root_path, view.second->s_Img_path);
const std::string mask_filename_local = stlplus::create_filespec(sfm_data.s_root_path, stlplus::basename_part(srcImage) + "_mask", "png");
const std::string maskName = stlplus::create_filespec(sOutDir, stlplus::basename_part(srcImage) + ".mask.png");
const std::string globalMaskName = stlplus::create_filespec(sOutDir, "global_mask_" + std::to_string(view.second.get()->id_intrinsic), ".png");
if (!stlplus::is_file(srcImage))
{
OPENMVG_LOG_INFO << "Cannot read the corresponding image: " << srcImage;
Expand All @@ -108,9 +114,14 @@ bool exportToOpenMVS(
image.platformID = map_intrinsic.at(view.second->id_intrinsic);
_INTERFACE_NAMESPACE::Interface::Platform& platform = scene.platforms[image.platformID];
image.cameraID = 0;
if (stlplus::file_exists(mask_filename_local))
image.maskName = maskName;
else if (stlplus::file_exists(mask_filename_global))
image.maskName = globalMaskName;

_INTERFACE_NAMESPACE::Interface::Platform::Pose pose;
image.poseID = platform.poses.size();
image.ID = image.poseID;
const openMVG::geometry::Pose3 poseMVG(sfm_data.GetPoseOrDie(view.second.get()));
pose.R = poseMVG.rotation();
pose.C = poseMVG.center();
Expand Down Expand Up @@ -147,6 +158,9 @@ bool exportToOpenMVS(
// Get image paths
const std::string srcImage = stlplus::create_filespec(sfm_data.s_root_path, view->s_Img_path);
const std::string imageName = stlplus::create_filespec(sOutDir, view->s_Img_path);
const std::string mask_filename_local = stlplus::create_filespec(sfm_data.s_root_path, stlplus::basename_part(srcImage) + "_mask", "png");
const std::string maskName = stlplus::create_filespec(sOutDir, stlplus::basename_part(srcImage) + ".mask.png");


if (sfm_data.IsPoseAndIntrinsicDefined(view))
{
Expand All @@ -162,7 +176,7 @@ bool exportToOpenMVS(
if (ReadImage(srcImage.c_str(), &imageRGB))
{
UndistortImage(imageRGB, cam, imageRGB_ud, BLACK);
bOk = WriteImage(imageName.c_str(), imageRGB_ud);
bOk = bOk & WriteImage(imageName.c_str(), imageRGB_ud);
}
else // If RGBColor reading fails, try to read as gray image
if (ReadImage(srcImage.c_str(), &image_gray))
Expand All @@ -173,24 +187,77 @@ bool exportToOpenMVS(
}
else
{
bOk = false;
bOk = bOk & false;
}

Image<unsigned char> imageMask;
// Try to read the local mask
if (stlplus::file_exists(mask_filename_local))
{
if (!ReadImage(mask_filename_local.c_str(), &imageMask)||
!(imageMask.Width() == cam->w() && imageMask.Height() == cam->h()))
{
OPENMVG_LOG_ERROR
<< "Invalid mask: " << mask_filename_local << ';';
bOk = bOk & false;
continue;
}
UndistortImage(imageMask, cam, image_gray_ud, BLACK);
const bool bRes = WriteImage(maskName.c_str(), image_gray_ud);
bOk = bOk & bRes;
}
}
catch (const std::bad_alloc& e)
{
bOk = false;
bOk = bOk & false;
}
}
else
{
// just copy image
stlplus::file_copy(srcImage, imageName);
if (stlplus::file_exists(mask_filename_local))
{
stlplus::file_copy(mask_filename_local, maskName);
}
}
}
else
{
// just copy the image
stlplus::file_copy(srcImage, imageName);
if (stlplus::file_exists(mask_filename_local))
{
stlplus::file_copy(mask_filename_local, maskName);
}
}
}
if (stlplus::file_exists(mask_filename_global))
{
for (int i = 0; i < static_cast<int>(sfm_data.GetIntrinsics().size()); i++)
{
const openMVG::cameras::IntrinsicBase* cam = sfm_data.GetIntrinsics().at(i).get();
const std::string maskName = stlplus::create_filespec(sOutDir, "global_mask_" + std::to_string(i), ".png");
Image<uint8_t> imageMask;
Image<uint8_t> image_gray, image_gray_ud;
if (cam->have_disto())
{
// Try to read the global mask
if (!ReadImage(mask_filename_global.c_str(), &imageMask)||
!(imageMask.Width() == cam->w() && imageMask.Height() == cam->h()))
{
OPENMVG_LOG_ERROR
<< "Invalid global mask: " << mask_filename_global << ';';
bOk = bOk & false;
}
UndistortImage(imageMask, cam, image_gray_ud, BLACK);
const bool bRes = WriteImage(maskName.c_str(), image_gray_ud);
bOk = bOk & bRes;
}
else
{
stlplus::file_copy(mask_filename_global, maskName);
}
}
}

Expand Down