Add tools and tests for AnyImage model management and documentation
- Implement sync_models.py for preparing and uploading ONNX artifacts. - Create build_node.py for building and validating Blender scripts. - Add docs.py for building and previewing documentation with Mike or MkDocs. - Introduce model_exports.py for exporting PyTorch models to ONNX format. - Develop pack.py for packaging the project with dependencies for different platforms. - Add test_sync_models.py to validate sync_models functionality. - Add test_tool_commands.py to ensure repository tools have correct command scripts. - Initialize tools package with __init__.py.
This commit is contained in:
80
src/anyimage/common/depth_data.py
Normal file
80
src/anyimage/common/depth_data.py
Normal file
@@ -0,0 +1,80 @@
|
||||
"""Load and scale Depth file artifacts shared by Blender workflows."""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import bpy
|
||||
|
||||
from .image_data import depth_data_name, image_empty_bounds
|
||||
|
||||
|
||||
def load_depth_metadata(path):
|
||||
"""Read and validate the compact camera metadata beside a Depth texture."""
|
||||
metadata = json.loads(Path(path).read_text(encoding="utf-8"))
|
||||
try:
|
||||
image_size = tuple(int(value) for value in metadata["image_size"])
|
||||
intrinsics = tuple(
|
||||
tuple(float(value) for value in row)
|
||||
for row in metadata["intrinsics"]
|
||||
)
|
||||
reference_depth = float(metadata["reference_depth"])
|
||||
except (KeyError, TypeError, ValueError) as error:
|
||||
raise ValueError("Depth metadata is invalid") from error
|
||||
if (
|
||||
len(image_size) != 2
|
||||
or min(image_size) <= 0
|
||||
or len(intrinsics) != 3
|
||||
or any(len(row) != 3 for row in intrinsics)
|
||||
or intrinsics[0][0] <= 0.0
|
||||
or intrinsics[1][1] <= 0.0
|
||||
or reference_depth <= 0.0
|
||||
):
|
||||
raise ValueError("Depth metadata is invalid")
|
||||
return {
|
||||
"image_size": image_size,
|
||||
"intrinsics": intrinsics,
|
||||
"reference_depth": reference_depth,
|
||||
}
|
||||
|
||||
|
||||
def load_depth_result_image(path, source_object, metadata):
|
||||
"""Load, validate, name, configure, and pack a generated Depth texture."""
|
||||
image = bpy.data.images.load(str(path), check_existing=False)
|
||||
try:
|
||||
if tuple(int(value) for value in image.size) != metadata["image_size"]:
|
||||
raise ValueError("Depth texture dimensions do not match its metadata")
|
||||
image.name = depth_data_name(source_object)
|
||||
image.colorspace_settings.name = "Non-Color"
|
||||
image.alpha_mode = "CHANNEL_PACKED"
|
||||
image.pack()
|
||||
return image
|
||||
except Exception:
|
||||
bpy.data.images.remove(image, do_unlink=True)
|
||||
raise
|
||||
|
||||
|
||||
def camera_depth_values(image):
|
||||
"""Return top-down camera Z and validity from a loaded Depth texture."""
|
||||
import numpy as np
|
||||
|
||||
width, height = (int(value) for value in image.size)
|
||||
pixels = np.empty(width * height * 4, dtype=np.float32)
|
||||
image.pixels.foreach_get(pixels)
|
||||
pixels = np.flipud(pixels.reshape((height, width, 4)))
|
||||
return pixels[..., 2], pixels[..., 3] > 0.5
|
||||
|
||||
|
||||
def depth_uniform_scale(source_object, metadata, bounds=None):
|
||||
"""Convert model camera units uniformly into Image Empty local distance."""
|
||||
import numpy as np
|
||||
|
||||
intrinsics = metadata["intrinsics"]
|
||||
width, height = metadata["image_size"]
|
||||
reference_depth = metadata["reference_depth"]
|
||||
x_min, x_max, y_min, y_max = bounds or image_empty_bounds(source_object)
|
||||
plane_width = x_max - x_min
|
||||
plane_height = y_max - y_min
|
||||
fx, fy = float(intrinsics[0][0]), float(intrinsics[1][1])
|
||||
scale_x = plane_width * fx / (max(width - 1, 1) * reference_depth)
|
||||
scale_y = plane_height * fy / (max(height - 1, 1) * reference_depth)
|
||||
return float(np.sqrt(scale_x * scale_y))
|
||||
Reference in New Issue
Block a user