refactor nodes into standalone file
This commit is contained in:
71
backend/nodes/mask_morphology.py
Normal file
71
backend/nodes/mask_morphology.py
Normal file
@@ -0,0 +1,71 @@
|
||||
from __future__ import annotations
|
||||
import numpy as np
|
||||
from backend.node_registry import register_node
|
||||
from backend.data_types import DataField, encode_preview
|
||||
from backend.nodes.helpers import _mask_overlay, _mask_structure
|
||||
|
||||
|
||||
@register_node(display_name="Mask Morphology")
|
||||
class MaskMorphology:
|
||||
"""Morphological operations on binary masks.
|
||||
|
||||
Equivalent to Gwyddion's mask_morph.c (erode, dilate, open, close).
|
||||
"""
|
||||
_CUSTOM_PREVIEW = True
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"mask": ("IMAGE",),
|
||||
"operation": (["dilate", "erode", "open", "close"],),
|
||||
"radius": ("INT", {"default": 1, "min": 1, "max": 50, "step": 1}),
|
||||
"shape": (["disk", "square"],),
|
||||
},
|
||||
"optional": {
|
||||
"field": ("DATA_FIELD",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
RETURN_NAMES = ("mask",)
|
||||
FUNCTION = "process"
|
||||
|
||||
DESCRIPTION = (
|
||||
"Apply morphological operations to a binary mask. "
|
||||
"Dilate expands regions, erode shrinks them, "
|
||||
"open (erode then dilate) removes small spots, "
|
||||
"close (dilate then erode) fills small holes. "
|
||||
"Equivalent to Gwyddion mask_morph."
|
||||
)
|
||||
|
||||
_broadcast_fn = None
|
||||
_current_node_id: str = ""
|
||||
|
||||
def process(self, mask: np.ndarray, operation: str, radius: int, shape: str,
|
||||
field: DataField | None = None) -> tuple:
|
||||
from scipy.ndimage import binary_closing, binary_dilation, binary_erosion, binary_opening
|
||||
|
||||
binary = mask > 127
|
||||
struct = _mask_structure(radius, shape)
|
||||
|
||||
if operation == "dilate":
|
||||
result = binary_dilation(binary, structure=struct)
|
||||
elif operation == "erode":
|
||||
result = binary_erosion(binary, structure=struct)
|
||||
elif operation == "open":
|
||||
result = binary_opening(binary, structure=struct)
|
||||
elif operation == "close":
|
||||
result = binary_closing(binary, structure=struct)
|
||||
else:
|
||||
raise ValueError(f"Unknown morphological operation: {operation}")
|
||||
|
||||
out = result.astype(np.uint8) * 255
|
||||
|
||||
if field is not None and MaskMorphology._broadcast_fn is not None:
|
||||
overlay = _mask_overlay(field, out)
|
||||
MaskMorphology._broadcast_fn(
|
||||
MaskMorphology._current_node_id, encode_preview(overlay),
|
||||
)
|
||||
|
||||
return (out,)
|
||||
Reference in New Issue
Block a user