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:
@@ -2,8 +2,8 @@ import bpy
|
||||
|
||||
from ..preferences import ADDON_PACKAGE
|
||||
from ..runtime import JobOperatorBase, runtime
|
||||
from ..server.model_catalog import DEFAULT_MODEL_KEYS
|
||||
from ..properties import (
|
||||
REQUIRED_MODEL_KEYS,
|
||||
ai_status,
|
||||
model_download_size,
|
||||
model_record,
|
||||
@@ -42,7 +42,7 @@ class SetupAIEnvironment(bpy.types.Operator):
|
||||
if not status["environment_ready"]:
|
||||
required_size = sum(
|
||||
model_download_size(model_key)
|
||||
for model_key in REQUIRED_MODEL_KEYS
|
||||
for model_key in DEFAULT_MODEL_KEYS
|
||||
)
|
||||
layout.label(
|
||||
text="AnyImage AI features run in an isolated Python environment."
|
||||
@@ -52,7 +52,7 @@ class SetupAIEnvironment(bpy.types.Operator):
|
||||
)
|
||||
layout.label(
|
||||
text=(
|
||||
"It also downloads MoGe-2 ViT-S Normal, BEN2 Base and "
|
||||
"It also downloads MoGe-2 ViT-S Normal, BiRefNet Lite and "
|
||||
"Real-ESRGAN General WDN x4v3 "
|
||||
f"({format_download_size(required_size)})."
|
||||
)
|
||||
@@ -154,7 +154,7 @@ class DownloadRequiredModels(JobOperatorBase, bpy.types.Operator):
|
||||
require_environment()
|
||||
if not bpy.app.online_access:
|
||||
raise RuntimeError("Online Access is disabled in Blender Preferences")
|
||||
return {"models": list(REQUIRED_MODEL_KEYS)}
|
||||
return {"models": list(DEFAULT_MODEL_KEYS)}
|
||||
|
||||
|
||||
class ClearModels(bpy.types.Operator):
|
||||
|
||||
@@ -6,7 +6,8 @@ from ...common.ai import invoke_ai_setup_if_needed, production_device, report_ai
|
||||
from ...common.image import is_image_empty, video_total_frames
|
||||
from ...common.color_image import prepare_material_color_input, material_analysis_input, cleanup_material_color_input
|
||||
from ...preferences import addon_preferences, configured_max_ai_input_size
|
||||
from ...properties import DEFAULT_MOGE2_MODEL_KEY
|
||||
from ...preferences import configured_geometry_model
|
||||
from ...server.model_catalog import DEFAULT_GEOMETRY_MODEL_KEY
|
||||
from ...runtime import JobOperatorBase
|
||||
from ...server.media.resolution import DEFAULT_MAX_AI_INPUT_SIZE, MAX_MAX_AI_INPUT_SIZE, MIN_MAX_AI_INPUT_SIZE
|
||||
from .object import create_panorama_from_result
|
||||
@@ -26,7 +27,7 @@ class GeneratePanorama(JobOperatorBase, bpy.types.Operator):
|
||||
source_identity: bpy.props.StringProperty(options=_HIDDEN)
|
||||
image_identity: bpy.props.StringProperty(options=_HIDDEN)
|
||||
mesh_detail: bpy.props.IntProperty(default=7, min=0, max=8, options=_HIDDEN)
|
||||
model: bpy.props.StringProperty(default=DEFAULT_MOGE2_MODEL_KEY, options=_HIDDEN)
|
||||
model: bpy.props.StringProperty(default=DEFAULT_GEOMETRY_MODEL_KEY, options=_HIDDEN)
|
||||
resolution_level: bpy.props.IntProperty(default=5, min=0, max=9, options=_HIDDEN)
|
||||
max_input_size: bpy.props.IntProperty(default=DEFAULT_MAX_AI_INPUT_SIZE,
|
||||
min=MIN_MAX_AI_INPUT_SIZE, max=MAX_MAX_AI_INPUT_SIZE, options=_HIDDEN)
|
||||
@@ -82,7 +83,7 @@ class ConvertToPanorama(bpy.types.Operator):
|
||||
input_path=str(path), color_path=str(color_path), source_object_name=source.name,
|
||||
source_identity=str(source.as_pointer()),
|
||||
image_identity=str(image.as_pointer()), mesh_detail=self.mesh_detail,
|
||||
model=getattr(preferences, "geometry_model", DEFAULT_MOGE2_MODEL_KEY),
|
||||
model=configured_geometry_model(context),
|
||||
resolution_level=int(getattr(preferences, "geometry_resolution_level", 5)),
|
||||
max_input_size=configured_max_ai_input_size(context),
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import bpy
|
||||
|
||||
from ...preferences import addon_preferences, configured_max_ai_input_size
|
||||
from ...properties import DEFAULT_MOGE2_MODEL_KEY
|
||||
from ...preferences import addon_preferences, configured_max_ai_input_size, configured_geometry_model
|
||||
from ...server.model_catalog import DEFAULT_GEOMETRY_MODEL_KEY
|
||||
from ...runtime import JobOperatorBase
|
||||
from ...server.media.resolution import (
|
||||
DEFAULT_MAX_AI_INPUT_SIZE,
|
||||
@@ -37,7 +37,7 @@ _HIDDEN = {"HIDDEN", "SKIP_SAVE"}
|
||||
def depth_plane_settings(context):
|
||||
preferences = addon_preferences(context)
|
||||
return (
|
||||
getattr(preferences, "geometry_model", DEFAULT_MOGE2_MODEL_KEY),
|
||||
configured_geometry_model(context),
|
||||
int(getattr(preferences, "geometry_resolution_level", 5)),
|
||||
)
|
||||
|
||||
@@ -59,7 +59,7 @@ class GenerateDepthPlane(JobOperatorBase, bpy.types.Operator):
|
||||
options=_HIDDEN,
|
||||
)
|
||||
mesh_detail: bpy.props.IntProperty(default=6, min=0, max=10, options=_HIDDEN)
|
||||
model: bpy.props.StringProperty(default=DEFAULT_MOGE2_MODEL_KEY, options=_HIDDEN)
|
||||
model: bpy.props.StringProperty(default=DEFAULT_GEOMETRY_MODEL_KEY, options=_HIDDEN)
|
||||
resolution_level: bpy.props.IntProperty(default=5, min=0, max=9, options=_HIDDEN)
|
||||
max_input_size: bpy.props.IntProperty(
|
||||
default=DEFAULT_MAX_AI_INPUT_SIZE,
|
||||
|
||||
@@ -6,15 +6,16 @@ import bpy
|
||||
|
||||
from ...preferences import (
|
||||
addon_preferences,
|
||||
configured_geometry_model,
|
||||
configured_max_ai_input_size,
|
||||
configured_max_cutout_mesh_resolution,
|
||||
)
|
||||
from ...properties import (
|
||||
DEFAULT_MOGE2_MODEL_KEY,
|
||||
cutout_alpha_threshold_property,
|
||||
cutout_fine_outline_property,
|
||||
)
|
||||
from ...runtime import JobOperatorBase
|
||||
from ...server.model_catalog import DEFAULT_GEOMETRY_MODEL_KEY
|
||||
from ...server.media.resolution import (
|
||||
DEFAULT_MAX_AI_INPUT_SIZE,
|
||||
MAX_MAX_AI_INPUT_SIZE,
|
||||
@@ -169,7 +170,7 @@ def _generated_color_result(input_path, source_bounds):
|
||||
|
||||
def cutout_geometry_settings(context):
|
||||
preferences = addon_preferences(context)
|
||||
model = getattr(preferences, "geometry_model", DEFAULT_MOGE2_MODEL_KEY)
|
||||
model = configured_geometry_model(context)
|
||||
return (
|
||||
model,
|
||||
int(getattr(preferences, "geometry_resolution_level", 5)),
|
||||
@@ -196,7 +197,7 @@ class CutoutSelectionToShape(JobOperatorBase, bpy.types.Operator):
|
||||
options=_HIDDEN,
|
||||
)
|
||||
model: bpy.props.StringProperty(
|
||||
default=DEFAULT_MOGE2_MODEL_KEY,
|
||||
default=DEFAULT_GEOMETRY_MODEL_KEY,
|
||||
options=_HIDDEN,
|
||||
)
|
||||
resolution_level: bpy.props.IntProperty(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import bpy
|
||||
|
||||
from ..properties import BEN2_MODEL_KEY
|
||||
from ..preferences import configured_background_model
|
||||
from ..runtime import JobOperatorBase
|
||||
from ..common.ai import (
|
||||
require_input_path,
|
||||
@@ -22,7 +22,7 @@ _HIDDEN = {"HIDDEN", "SKIP_SAVE"}
|
||||
class RemoveImageBackground(bpy.types.Operator):
|
||||
bl_idname = "anyimage.remove_image_background"
|
||||
bl_label = "Remove Background"
|
||||
bl_description = "Remove the image background with BEN2"
|
||||
bl_description = "Remove the image background with the selected AI model"
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
@classmethod
|
||||
@@ -84,11 +84,12 @@ class RunBackgroundRemoval(JobOperatorBase, bpy.types.Operator):
|
||||
|
||||
def request(self, context):
|
||||
require_environment()
|
||||
require_model(BEN2_MODEL_KEY)
|
||||
model = configured_background_model(context)
|
||||
require_model(model)
|
||||
settings = context.scene.anyimage_settings
|
||||
parameters = {
|
||||
"input": str(require_input_path(self.input_path)),
|
||||
"model": BEN2_MODEL_KEY,
|
||||
"model": model,
|
||||
"device": production_device().lower(),
|
||||
"video_frames": settings.video_frames,
|
||||
"start_frame": self._image_target.start_frame,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import bpy
|
||||
|
||||
from ..preferences import configured_max_ai_input_size
|
||||
from ..properties import configured_upscale_model, upscale_model_label
|
||||
from ..preferences import configured_upscale_model
|
||||
from ..properties import upscale_model_label
|
||||
from ..server.media.resolution import (
|
||||
DEFAULT_MAX_AI_INPUT_SIZE,
|
||||
MAX_MAX_AI_INPUT_SIZE,
|
||||
|
||||
Reference in New Issue
Block a user