educelab / volume-cartographer

Volumetric processing toolkit and C++ libraries for the recovery and restoration of damaged cultural materials
GNU General Public License v3.0
63 stars 21 forks source link

Automatically align UV map to specified volume axis #57

Closed stephenrparsons closed 1 year ago

stephenrparsons commented 1 year ago

Fixes #56.

This provides an implementation for automatically rotating UV maps such that they align as best as possible with a specified volume axis. The intention is that it will be easier to automatically render segments with the text oriented correctly.

The algorithm randomly samples 500 points (or all points, whichever is smaller) from the UV map, since sampling all points in a UV map is typically far over-constrained. It then checks a series of trial rotations. Since it is fast to do so, right now it just checks every half degree around the circle (so 720 rotations). For each trial angle, it rotates the original UV map by that amount, and then measures the Pearson correlation between the negative V value of the UV map ("up" axis in the texture image) with the specified volume axis for the mesh points that correspond to the UV points. For example, if AlignmentAxis::ZPos is the axis of choice, decreases in UV map V values should lead to increases in volume Z values.

There are --uv-align-to-axis options for positive and negative alignments to each volume axis: X, Y, and Z. This change makes positive Z the default, since by CT convention it is common that an upright object in the scanner would lead to higher Z values higher up the page. But it is also possible to set --uv-align-to-axis 0 to disable this orientation step. --uv-rotate and --uv-flip can still be specified, and if so specified, will be applied in that order following --uv-align-to-axis.

Here are some sample UV map outputs for Vesuvius Challenge segment 20230526002441 from Scroll 1, to illustrate the effect on rotation.

--uv-align-to-axis 0 (no alignment, fallback to previous orientation method) 0 --uv-align-to-axis 1 (default - positive Z) 1 --uv-align-to-axis 2 (negative Z, notice it is 180 degrees from positive Z) 2 --uv-align-to-axis 3 (positive Y) 3 --uv-align-to-axis 4 (negative Y) 4 --uv-align-to-axis 5 (positive X) 5 --uv-align-to-axis 6 (negative X) 6 The text on this segment (taken from Vesuvius Challenge Segment Browser) confirms that +Z is the desired axis alignment (here shown unrotated, look back at --uv-align-to-axis 1): image Here's how the default option orients Vesuvius Challenge segment 20231012173610: smaller

csparker247 commented 1 year ago

Finished my review of the core code. It all looks good. Just need to do the arg stuff and run some tests.

csparker247 commented 1 year ago

I've updated vc_render so that it accepts strings for the new argument rather than an int. I know that's what the other flags use, but I'm getting pretty tired of remembering those options. Anyway, usage is now something like this:

vc_render ... --uv-align-to-axis none
vc_render ... --uv-align-to-axis +z
vc_render ... --uv-align-to-axis -z
vc_render ... --uv-align-to-axis +y
vc_render ... --uv-align-to-axis -y
vc_render ... --uv-align-to-axis +x
vc_render ... --uv-align-to-axis -x