Implement BiRefNet and HAT Sharper models with background removal capabilities

- Added validation documentation for AI model tiers.
- Introduced `background.py` for background removal logic, including inference functions for alpha and foreground extraction.
- Created `onnx_birefnet.py` to handle BiRefNet model sessions and alpha inference.
- Developed tests for background models, ensuring proper dispatch and session reuse.
- Added tests for BiRefNet ONNX model to validate alpha output and error handling for invalid values.
- Implemented model export scripts for BiRefNet and HAT Sharper, ensuring proper weight compression and licensing.
- Created `deform_sampling.py` for deformable convolution operations used in BiRefNet.
- Added utility functions for compressing ONNX weights without altering graph arithmetic.
- Introduced a reference plane node for depth field adjustments in geometry processing.
This commit is contained in:
2026-09-10 20:50:44 +08:00
parent 8ae3c1d5b7
commit e8129fe495
70 changed files with 1890 additions and 1208 deletions

View File

@@ -3,7 +3,9 @@
import bpy
from ..common.nodes import group_input as _group_input, interface_socket as _interface_socket
from ..common.nodes import prepare_node_group
from ..common.nodes import prepare_node_group, float_input, vector_input
from ..common.reference_plane import reference_plane_depth
from ..common.smoothing import expand_smooth
RELIEF_PLANE_NODE_GROUP_NAME = "O Image Relief Plane"
@@ -38,6 +40,8 @@ def build_image_relief_plane_group(image_plane_group):
depth_scale = _interface_socket(group, "Depth Scale", "INPUT", "NodeSocketFloat")
depth_scale.default_value = 0.5
depth_scale.min_value = 0.0
smooth = _interface_socket(group, "Smooth", "INPUT", "NodeSocketInt")
smooth.default_value, smooth.min_value, smooth.max_value = 0, 0, 20
options = group.interface.new_panel(name="Options", default_closed=True)
base_plane_depth = _interface_socket(
group,
@@ -49,6 +53,8 @@ def build_image_relief_plane_group(image_plane_group):
base_plane_depth.default_value = 1.0
base_plane_depth.min_value = 0.0
base_plane_depth.subtype = "DISTANCE"
float_input(group, "Smooth Weight", 1.0, maximum=1, subtype="FACTOR", parent=options)
vector_input(group, "Depth Direction", (0, 0, 1), subtype="DIRECTION", parent=options)
data = group.interface.new_panel(name="Data", default_closed=True)
uniform_scale = _interface_socket(
group,
@@ -78,7 +84,7 @@ def build_image_relief_plane_group(image_plane_group):
)
shape_input = _group_input(
nodes,
{"Thickness", "Depth Scale", "Reference Depth"},
{"Thickness", "Depth Scale"},
)
image_input = _group_input(
nodes,
@@ -114,7 +120,11 @@ def build_image_relief_plane_group(image_plane_group):
links.new(depth_components.outputs["Z"], metric_depth.inputs[0])
links.new(image_input.outputs["Uniform Scale"], metric_depth.inputs[1])
relative_depth = _math(nodes, "SUBTRACT")
links.new(shape_input.outputs["Reference Depth"], relative_depth.inputs[0])
reference_input = _group_input(nodes, {"Depth Direction", "Reference Depth"})
plane_depth = reference_plane_depth(
group, reference_input.outputs["Depth Direction"], reference_input.outputs["Reference Depth"],
)
links.new(plane_depth, relative_depth.inputs[0])
links.new(metric_depth.outputs[0], relative_depth.inputs[1])
full_offset = _math(nodes, "MULTIPLY")
links.new(relative_depth.outputs[0], full_offset.inputs[0])
@@ -167,7 +177,10 @@ def build_image_relief_plane_group(image_plane_group):
shade_smooth = nodes.new("GeometryNodeSetShadeSmooth")
shade_smooth.domain = "FACE"
shade_smooth.inputs["Shade Smooth"].default_value = True
links.new(set_position.outputs["Geometry"], shade_smooth.inputs["Geometry"])
geometry = expand_smooth(
group, set_position.outputs["Geometry"], iterations_name="Smooth", weight_name="Smooth Weight",
)
links.new(geometry, shade_smooth.inputs["Geometry"])
links.new(shade_smooth.outputs["Geometry"], group_output.inputs["Geometry"])
group.color_tag = "GEOMETRY"
group.description = (