20#include <lagrange/Logger.h>
21#include <lagrange/scene/internal/shared_utils.h>
22#include <lagrange/texproc/TextureRasterizer.h>
24#include <tbb/parallel_for.h>
26namespace lagrange::texproc {
28using scene::internal::Array3Df;
29using scene::internal::ConstView3Df;
30using scene::internal::View3Df;
32template <
typename Scalar,
typename Index>
33std::vector<CameraOptions> cameras_from_scene(
const scene::Scene<Scalar, Index>& scene)
35 using ElementId = scene::ElementId;
37 std::vector<CameraOptions> cameras;
38 for (ElementId node_id = 0; node_id < scene.nodes.size(); ++node_id) {
39 const auto& node = scene.nodes[node_id];
40 if (!node.cameras.empty()) {
41 auto world_from_node = scene::utils::compute_global_node_transform(scene, node_id);
42 for (
auto camera_id : node.cameras) {
43 const auto& scene_camera = scene.cameras[camera_id];
46 scene::utils::camera_view_transform(scene_camera, world_from_node);
47 camera.projection_transform =
48 scene::utils::camera_projection_transform(scene_camera);
49 cameras.push_back(camera);
57template <
typename Scalar,
typename Index>
58std::vector<std::pair<Array3Df, Array3Df>> rasterize_textures_from_renders(
59 const lagrange::scene::Scene<Scalar, Index>& scene,
60 std::optional<Array3Df> base_texture_in,
61 const std::vector<ConstView3Df>& renders,
62 const std::optional<size_t> tex_width,
63 const std::optional<size_t> tex_height,
64 const float low_confidence_ratio,
65 const std::optional<float> base_confidence)
68 auto [mesh, base_texture] = scene::internal::single_mesh_from_scene(scene);
69 auto cameras = cameras_from_scene(scene);
70 lagrange::logger().info(
"Found {} cameras in the input scene", cameras.size());
72 if (base_texture_in.has_value()) {
73 if (base_texture.has_value()) {
75 "Input scene already contains a base texture. Overriding with user-provided "
78 base_texture = std::move(base_texture_in);
83 for (
const auto& render : renders) {
84 size_t img_width = render.extent(0);
85 size_t img_height = render.extent(1);
86 size_t img_channels = render.extent(2);
87 la_runtime_assert(img_width == renders.front().extent(0),
"Render width must all be equal");
89 img_height == renders.front().extent(1),
90 "Render height must all be equal");
92 img_channels == renders.front().extent(2),
93 "Render num channels must all be equal");
96 renders.size() == cameras.size(),
97 "Number of renders must match number of cameras");
99 std::vector<std::pair<Array3Df, Array3Df>> textures_and_weights;
102 if (base_confidence.has_value() && base_confidence.value() == 0) {
103 if (base_texture.has_value()) {
105 "Base confidence is 0, ignoring base texture in the input scene.");
108 if (base_texture.has_value()) {
109 const float default_confidence = base_confidence.value_or(0.3f);
111 "Using base texture with uniform confidence: {}",
113 const auto base_image = base_texture.value();
115 base_image.extent(0),
116 base_image.extent(1),
118 for (
size_t i = 0; i < base_weights.extent(0); ++i) {
119 for (
size_t j = 0; j < base_weights.extent(1); ++j) {
120 base_weights(i, j, 0) = default_confidence;
123 textures_and_weights.emplace_back(base_image, std::move(base_weights));
125 if (base_confidence.has_value()) {
127 "No base texture was found in the input scene. Ignoring user-provided base "
129 base_confidence.value());
136 if (textures_and_weights.empty()) {
137 rasterizer_options.width = tex_width.value_or(1024);
138 rasterizer_options.height = tex_height.value_or(1024);
140 "No base texture found. Using rasterization size: {}x{}",
141 rasterizer_options.width,
142 rasterizer_options.height);
144 const auto& base_image = textures_and_weights.front().first;
145 la_runtime_assert(!tex_width.has_value() || base_image.extent(0) == tex_width.value());
146 la_runtime_assert(!tex_height.has_value() || base_image.extent(1) == tex_height.value());
147 rasterizer_options.width = base_image.extent(0);
148 rasterizer_options.height = base_image.extent(1);
150 renders.front().extent(2) == base_image.extent(2),
152 "Input render image num channels (={}) must match base texture num channels (={})",
153 renders.front().extent(2),
154 base_image.extent(2)));
156 "Using base texture size for rasterization: {}x{}",
157 rasterizer_options.width,
158 rasterizer_options.height);
162 size_t offset = textures_and_weights.size();
163 textures_and_weights.resize(offset + cameras.size());
165 lagrange::logger().info(
"Computing confidence maps for {} cameras", cameras.size());
166 tbb::parallel_for(
size_t(0), cameras.size(), [&](
size_t i) {
167 textures_and_weights[offset + i] =
168 rasterizer.weighted_texture_from_render(renders[i], cameras[i]);
173 "Filtering low confidence values using ratio threshold: {}",
174 low_confidence_ratio);
177 return textures_and_weights;
Given a mesh with UVs, unproject rendered images into a UV texture and confidence map.
Definition TextureRasterizer.h:72
LA_CORE_API spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:40
#define la_runtime_assert(...)
Runtime assertion check.
Definition assert.h:174
Array3D< T > create_image(size_t width, size_t height, size_t num_channels)
Create an image with the given dimensions and number of channels.
Definition Array3D.h:46
void filter_low_confidences(span< std::pair< image::experimental::Array3D< float >, image::experimental::Array3D< float > > > textures_and_weights, float low_ratio_threshold)
Discard low-confidence values.
Parameters for computing the rendering of a mesh.
Definition TextureRasterizer.h:29
Eigen::Affine3f view_transform
Camera view transform (world space -> view space).
Definition TextureRasterizer.h:31
Options for computing the texture map and confidence from a rendering.
Definition TextureRasterizer.h:44