in source/mesh_stream/ConvertToBinary.cpp [148:243]
void convertDepth(
const Camera& cam,
const std::string& frameName,
const bool saveIdx,
const bool saveVtx,
const bool savePfm,
const bool saveObj) {
if (!saveIdx && !saveVtx && !savePfm && !saveObj) {
return;
}
const std::string& camId = cam.id;
LOG(INFO) << folly::sformat("Converting depth: frame {}, camera {}...", frameName, camId);
cv::Mat_<float> disparity = image_util::loadPfmImage(FLAGS_disparity, camId, frameName);
cv::Mat_<float> depth = 1.0f / disparity;
if (FLAGS_depth_scale < 1) {
// nearest neighbor resize filter since we don't want to do any averaging of depths here
cv::resize(depth, depth, cv::Size(), FLAGS_depth_scale, FLAGS_depth_scale, cv::INTER_NEAREST);
}
Eigen::MatrixXd vertexes = mesh_util::getVertexesEquiError(depth, cam);
static const bool kWrapHorizontally = false;
static const bool kIsSpherical = false;
Eigen::MatrixXi faces = mesh_util::getFaces(
vertexes, depth.cols, depth.rows, kWrapHorizontally, kIsSpherical, FLAGS_tear_ratio);
// Remove geometry where we don't have valid depth data
cv::Mat_<bool> vertexMask(depth.size());
for (int i = 0; i < depth.rows; ++i) {
for (int j = 0; j < depth.cols; ++j) {
vertexMask(i, j) = !std::isnan(depth(i, j));
}
}
if (!FLAGS_foreground_masks.empty()) {
cv::Mat_<bool> foregroundMask =
image_util::loadImage<bool>(FLAGS_foreground_masks, camId, frameName);
cv::resize(foregroundMask, foregroundMask, depth.size(), 0, 0, cv::INTER_NEAREST);
vertexMask = vertexMask & foregroundMask;
}
const int originalFaceCount = faces.rows();
mesh_util::applyMaskToVertexesAndFaces(vertexes, faces, vertexMask);
const int numFacesRemoved = originalFaceCount - faces.rows();
LOG(INFO) << folly::sformat(
"Removed {} of {} faces ({:.2f}%) corresponding to invalid depths and masked vertexes",
numFacesRemoved,
originalFaceCount,
100.f * numFacesRemoved / (float)originalFaceCount);
if (FLAGS_triangles > 0) {
LOG(INFO) << folly::sformat("Target number of faces: {}", FLAGS_triangles);
static const bool kIsEquierror = true;
static const int kThreads = 1;
render::MeshSimplifier ms(vertexes, faces, kIsEquierror, kThreads);
static const float kStrictness = 0.2;
static const bool kRemoveBoundaryEdges = false;
ms.simplify(FLAGS_triangles, kStrictness, kRemoveBoundaryEdges);
vertexes = ms.getVertexes();
faces = ms.getFaces();
// If depth is slightly negative, the viewer will take it to -infinity (it
// does the inverse). We force this values to the minimum positive value
for (int i = 0; i < vertexes.rows(); ++i) {
if (vertexes.row(i).z() < 0) {
vertexes.row(i).z() = FLT_MIN;
}
}
}
const filesystem::path vertexFilename =
image_util::imagePath(FLAGS_bin, camId, frameName, ".vtx");
filesystem::create_directories(vertexFilename.parent_path());
const filesystem::path indexFilename = image_util::imagePath(FLAGS_bin, camId, frameName, ".idx");
filesystem::create_directories(indexFilename.parent_path());
if (saveIdx || saveVtx) {
mesh_util::writeDepth(vertexes, faces, vertexFilename, indexFilename);
}
if (savePfm) {
const filesystem::path depthFilename =
image_util::imagePath(FLAGS_bin, camId, frameName, ".pfm");
filesystem::create_directories(depthFilename.parent_path());
mesh_util::writePfm(depth, cam.resolution, vertexes, faces, depthFilename);
}
if (saveObj) {
LOG(INFO) << folly::sformat("Exporting obj: frame {}, camera {}...", frameName, camId);
const filesystem::path objFilename = image_util::imagePath(FLAGS_bin, camId, frameName, ".obj");
filesystem::create_directories(objFilename.parent_path());
mesh_util::writeObj(
mesh_util::readVertexes(vertexFilename), mesh_util::readFaces(indexFilename), objFilename);
}
}