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:
@@ -6,6 +6,33 @@ from unittest.mock import patch
|
||||
from tests.anyimage.server.runtime_support import ServerTestCase
|
||||
|
||||
class ModelManagerTest(ServerTestCase):
|
||||
def test_background_cache_switches_model_directory_and_device_and_closes(self):
|
||||
from server.models import background
|
||||
|
||||
cache = self.create_cache()
|
||||
loads = []
|
||||
|
||||
def create(directory, device):
|
||||
result = object()
|
||||
loads.append((str(directory), device, result))
|
||||
return result
|
||||
|
||||
with patch.object(background, "model_adapter", return_value=SimpleNamespace(create_session=create)):
|
||||
first, _ = cache.get_background("a/birefnet-lite", "cpu")
|
||||
assert cache.get_background("a/birefnet-lite", "cpu") == (first, 0.0)
|
||||
second, _ = cache.get_background("a/BEN2-ONNX", "cpu")
|
||||
third, _ = cache.get_background("a/birefnet-hr-matting", "cpu")
|
||||
fourth, _ = cache.get_background("b/birefnet-hr-matting", "cpu")
|
||||
assert cache.get_background("b/birefnet-hr-matting", "directml") == (fourth, 0.0)
|
||||
fifth, _ = cache.get_background("b/birefnet-lite", "directml")
|
||||
assert len(loads) == 5
|
||||
assert len({id(item) for item in (first, second, third, fourth, fifth)}) == 5
|
||||
assert cache.snapshot()["background"] == "birefnet-lite"
|
||||
assert loads[2][1] == loads[3][1] == "cpu"
|
||||
cache.close()
|
||||
assert cache.background_model is None
|
||||
assert cache.snapshot()["background"] == ""
|
||||
|
||||
def test_required_model_download_skips_ready_model(self):
|
||||
manager = self.ModelManager(Path("."))
|
||||
downloads = []
|
||||
@@ -39,7 +66,7 @@ class ModelManagerTest(ServerTestCase):
|
||||
snapshot,
|
||||
{
|
||||
"loaded": {
|
||||
"ben2": "",
|
||||
"background": "",
|
||||
"geometry": "",
|
||||
"upscale": "",
|
||||
}
|
||||
@@ -49,7 +76,7 @@ class ModelManagerTest(ServerTestCase):
|
||||
self.assertNotIn("model_catalog", sys.modules)
|
||||
|
||||
|
||||
def test_ben2_model_is_reused_for_matching_runtime_key(self):
|
||||
def test_background_model_is_reused_for_matching_runtime_key(self):
|
||||
loads = []
|
||||
|
||||
ben2 = ModuleType("server.models.onnx_ben2")
|
||||
@@ -59,12 +86,12 @@ class ModelManagerTest(ServerTestCase):
|
||||
cache = self.create_cache()
|
||||
device = SimpleNamespace(type="cuda")
|
||||
with patch.dict(sys.modules, {"server.models.onnx_ben2": ben2}):
|
||||
first, _load_ms = cache.get_ben2("model", device)
|
||||
second, cached_load_ms = cache.get_ben2("model", device)
|
||||
first, _load_ms = cache.get_background("BEN2-ONNX", device)
|
||||
second, cached_load_ms = cache.get_background("BEN2-ONNX", device)
|
||||
|
||||
self.assertIs(first, second)
|
||||
self.assertEqual(loads, [("model", "cuda")])
|
||||
self.assertEqual(cache.snapshot()["ben2"], "model")
|
||||
self.assertEqual(loads, [("BEN2-ONNX", "cuda")])
|
||||
self.assertEqual(cache.snapshot()["background"], "BEN2-ONNX")
|
||||
self.assertEqual(cached_load_ms, 0.0)
|
||||
|
||||
|
||||
@@ -73,8 +100,8 @@ class ModelManagerTest(ServerTestCase):
|
||||
ben2 = object()
|
||||
old_moge = object()
|
||||
upscale = object()
|
||||
cache.ben2_model = ben2
|
||||
cache.ben2_key = ("ben2", "cuda")
|
||||
cache.background_model = ben2
|
||||
cache.background_key = ("ben2", "cuda")
|
||||
cache.moge_model = old_moge
|
||||
cache.moge_key = ("old-moge", "cuda")
|
||||
cache.upscale_model = upscale
|
||||
@@ -85,7 +112,7 @@ class ModelManagerTest(ServerTestCase):
|
||||
with patch.dict(sys.modules, {"server.models.onnx_moge2": fake_moge}):
|
||||
self.assertIs(cache.get_moge("new-moge", "cuda"), new_moge)
|
||||
|
||||
self.assertIs(cache.ben2_model, ben2)
|
||||
self.assertIs(cache.background_model, ben2)
|
||||
self.assertIs(cache.upscale_model, upscale)
|
||||
self.assertEqual(cache.snapshot()["geometry"], "new-moge")
|
||||
|
||||
@@ -160,11 +187,11 @@ class ModelManagerTest(ServerTestCase):
|
||||
"server.models.onnx_upscale": upscale,
|
||||
},
|
||||
):
|
||||
first_ben2, _load_ms = cache.get_ben2("ben2", "cuda")
|
||||
first_ben2, _load_ms = cache.get_background("BEN2-ONNX", "cuda")
|
||||
assert_reused(
|
||||
first_ben2,
|
||||
lambda: cache.get_ben2("ben2", "cuda")[0],
|
||||
"release_ben2",
|
||||
lambda: cache.get_background("BEN2-ONNX", "cuda")[0],
|
||||
"release_background",
|
||||
)
|
||||
|
||||
first_moge2 = cache.get_moge("moge2", "cuda")
|
||||
|
||||
Reference in New Issue
Block a user