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

@@ -7,6 +7,7 @@ from ..common.nodes import (
menu_switch, read_float_attribute, store_float_attribute, prepare_node_group,
)
from ..common.smoothing import expand_smooth
from ..common.reference_plane import reference_plane_depth
from ..common.cutout import _extrude_layers, _island_cleanup, _position_field, _profile_field, _remove_zero_thickness, _set_layer_z, _shade_output
@@ -29,35 +30,6 @@ def _set_geometry_z(group, geometry, z_value):
return set_position.outputs["Geometry"]
def _plane_depth(group, direction, reference_depth):
nodes = group.nodes
links = group.links
normal = nodes.new("ShaderNodeVectorMath")
normal.operation = "NORMALIZE"
links.new(direction, normal.inputs[0])
normal_components = nodes.new("ShaderNodeSeparateXYZ")
links.new(normal.outputs["Vector"], normal_components.inputs["Vector"])
position = nodes.new("GeometryNodeInputPosition")
position_components = nodes.new("ShaderNodeSeparateXYZ")
links.new(position.outputs["Position"], position_components.inputs["Vector"])
x_term = math_node(nodes, "MULTIPLY")
links.new(position_components.outputs["X"], x_term.inputs[0])
links.new(normal_components.outputs["X"], x_term.inputs[1])
y_term = math_node(nodes, "MULTIPLY")
links.new(position_components.outputs["Y"], y_term.inputs[0])
links.new(normal_components.outputs["Y"], y_term.inputs[1])
point_dot = math_node(nodes, "ADD")
links.new(x_term.outputs[0], point_dot.inputs[0])
links.new(y_term.outputs[0], point_dot.inputs[1])
divide = math_node(nodes, "DIVIDE")
links.new(point_dot.outputs[0], divide.inputs[0])
links.new(normal_components.outputs["Z"], divide.inputs[1])
plane = math_node(nodes, "ADD")
links.new(reference_depth, plane.inputs[0])
links.new(divide.outputs[0], plane.inputs[1])
return plane.outputs[0]
def _build_depth_balloon(
group,
geometry,
@@ -78,7 +50,7 @@ def _build_depth_balloon(
metric_depth = math_node(nodes, "MULTIPLY")
links.new(separate_camera.outputs["Z"], metric_depth.inputs[0])
links.new(uniform_scale, metric_depth.inputs[1])
plane_depth = _plane_depth(
plane_depth = reference_plane_depth(
group,
depth_direction,
depth_reference,