auto-size masks during mask add

fix some limits on transform node
fix inversion in pixel merge
This commit is contained in:
Alexander G. Morano
2025-03-06 15:25:58 -05:00
parent 7de8224225
commit d71e4db764
5 changed files with 25 additions and 21 deletions
+3 -3
View File
@@ -274,7 +274,7 @@ Perform single function operations like absolute value, mean, median, mode, magn
d = super().INPUT_TYPES()
d = deep_merge(d, {
"optional": {
Lexicon.IN_A: (JOV_TYPE_FULL, {"default": None}),
Lexicon.IN_A: (JOV_TYPE_NUMERICAL, {"default": None}),
Lexicon.FUNC: (EnumUnaryOperation._member_names_, {"default": EnumUnaryOperation.ABS.name})
}
})
@@ -377,9 +377,9 @@ Execute binary operations like addition, subtraction, multiplication, division,
d = super().INPUT_TYPES()
d = deep_merge(d, {
"optional": {
Lexicon.IN_A: (JOV_TYPE_FULL, {"default": None,
Lexicon.IN_A: (JOV_TYPE_NUMERICAL, {"default": None,
"tooltip":"Passes a raw value directly, or supplies defaults for any value inputs without connections"}),
Lexicon.IN_B: (JOV_TYPE_FULL, {"default": None,
Lexicon.IN_B: (JOV_TYPE_NUMERICAL, {"default": None,
"tooltip":"Passes a raw value directly, or supplies defaults for any value inputs without connections"}),
Lexicon.FUNC: (EnumBinaryOperation._member_names_, {"default": EnumBinaryOperation.ADD.name, "tooltip":"Arithmetic operation to perform"}),
Lexicon.TYPE: (names_convert, {"default": names_convert[2],
+13 -12
View File
@@ -786,13 +786,14 @@ Combines individual color channels (red, green, blue) along with an optional mas
_, _, w_max, h_max = image_minmax(img)
for i, x in enumerate(img):
img[i] = x
if x is None:
img[i] = np.full((h_max, w_max), matte[i], dtype=np.uint8)
x = np.full((h_max, w_max), matte[i], dtype=np.uint8)
if flip[i] > 0:
img[i] = image_invert(x, flip[i])
x = image_invert(x, flip[i])
img[i] = x
img = channel_merge(img)
img = image_invert(img, 1)
if mode != EnumScaleMode.MATTE:
w, h = wihi
@@ -1008,16 +1009,16 @@ Apply various geometric transformations to images, including translation, rotati
"optional": {
Lexicon.PIXEL: (JOV_TYPE_IMAGE, {}),
Lexicon.MASK: (JOV_TYPE_IMAGE, {}),
Lexicon.XY: ("VEC2", {"default": (0, 0,), "mij": -1, "maj": 1, "step": 0.01, "label": [Lexicon.X, Lexicon.Y]}),
Lexicon.ANGLE: ("FLOAT", {"default": 0, "step": 0.01}),
Lexicon.XY: ("VEC2", {"default": (0., 0.,), "mij": -1., "maj": 1., "step": 0.01, "label": [Lexicon.X, Lexicon.Y]}),
Lexicon.ANGLE: ("FLOAT", {"default": 0., "step": 0.1}),
Lexicon.SIZE: ("VEC2", {"default": (1., 1.), "mij": 0.001, "step": 0.01, "label": [Lexicon.X, Lexicon.Y]}),
Lexicon.TILE: ("VEC2", {"default": (1., 1.), "mij": 1, "step": 0.01, "label": [Lexicon.X, Lexicon.Y]}),
Lexicon.TILE: ("VEC2", {"default": (1., 1.), "mij": 1., "step": 0.01, "label": [Lexicon.X, Lexicon.Y]}),
Lexicon.EDGE: (EnumEdge._member_names_, {"default": EnumEdge.CLIP.name}),
Lexicon.MIRROR: (EnumMirrorMode._member_names_, {"default": EnumMirrorMode.NONE.name}),
Lexicon.PIVOT: ("VEC2", {"default": (0.5, 0.5), "step": 0.005, "label": [Lexicon.X, Lexicon.Y]}),
Lexicon.PROJECTION: (EnumProjection._member_names_, {"default": EnumProjection.NORMAL.name}),
Lexicon.TLTR: ("VEC4", {"default": (0, 0, 1, 0), "step": 0.005, "label": [Lexicon.TOP, Lexicon.LEFT, Lexicon.TOP, Lexicon.RIGHT]}),
Lexicon.BLBR: ("VEC4", {"default": (0, 1, 1, 1), "step": 0.005, "label": [Lexicon.BOTTOM, Lexicon.LEFT, Lexicon.BOTTOM, Lexicon.RIGHT]}),
Lexicon.TLTR: ("VEC4", {"default": (0., 0., 1., 0.), "mij": 0., "maj": 1., "step": 0.005, "label": [Lexicon.TOP, Lexicon.LEFT, Lexicon.TOP, Lexicon.RIGHT]}),
Lexicon.BLBR: ("VEC4", {"default": (0., 1., 1., 1.), "mij": 0., "maj": 1., "step": 0.005, "label": [Lexicon.BOTTOM, Lexicon.LEFT, Lexicon.BOTTOM, Lexicon.RIGHT]}),
Lexicon.STRENGTH: ("FLOAT", {"default": 1, "min": 0, "step": 0.005}),
Lexicon.MODE: (EnumScaleMode._member_names_, {"default": EnumScaleMode.MATTE.name}),
Lexicon.WH: ("VEC2INT", {"default": (512, 512), "mij":MIN_IMAGE_SIZE, "label": [Lexicon.W, Lexicon.H]}),
@@ -1030,16 +1031,16 @@ Apply various geometric transformations to images, including translation, rotati
def run(self, **kw) -> Tuple[torch.Tensor, ...]:
pA = parse_param(kw, Lexicon.PIXEL, EnumConvertType.IMAGE, None)
mask = parse_param(kw, Lexicon.MASK, EnumConvertType.IMAGE, None)
offset = parse_param(kw, Lexicon.XY, EnumConvertType.VEC2, [(0, 0)], -2.5, 2.5)
offset = parse_param(kw, Lexicon.XY, EnumConvertType.VEC2, [(0., 0.)], -2.5, 2.5)
angle = parse_param(kw, Lexicon.ANGLE, EnumConvertType.FLOAT, 0)
size = parse_param(kw, Lexicon.SIZE, EnumConvertType.VEC2, [(1, 1)], 0.001)
size = parse_param(kw, Lexicon.SIZE, EnumConvertType.VEC2, [(1., 1.)], 0.001)
edge = parse_param(kw, Lexicon.EDGE, EnumEdge, EnumEdge.CLIP.name)
mirror = parse_param(kw, Lexicon.MIRROR, EnumMirrorMode, EnumMirrorMode.NONE.name)
mirror_pivot = parse_param(kw, Lexicon.PIVOT, EnumConvertType.VEC2, [(0.5, 0.5)], 0, 1)
tile_xy = parse_param(kw, Lexicon.TILE, EnumConvertType.VEC2, [(1., 1.)], 1)
proj = parse_param(kw, Lexicon.PROJECTION, EnumProjection, EnumProjection.NORMAL.name)
tltr = parse_param(kw, Lexicon.TLTR, EnumConvertType.VEC4, [(0, 0, 1, 0)], 0, 1)
blbr = parse_param(kw, Lexicon.BLBR, EnumConvertType.VEC4, [(0, 1, 1, 1)], 0, 1)
tltr = parse_param(kw, Lexicon.TLTR, EnumConvertType.VEC4, [(0., 0., 1., 0.)], 0, 1)
blbr = parse_param(kw, Lexicon.BLBR, EnumConvertType.VEC4, [(0., 1., 1., 1.)], 0, 1)
strength = parse_param(kw, Lexicon.STRENGTH, EnumConvertType.FLOAT, 1, 0, 1)
mode = parse_param(kw, Lexicon.MODE, EnumScaleMode, EnumScaleMode.MATTE.name)
wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, [(512, 512)], MIN_IMAGE_SIZE)
+2
View File
@@ -216,6 +216,8 @@ def image_mask_add(image:TYPE_IMAGE, mask:TYPE_IMAGE=None, alpha:float=255) -> T
"""
image = image_convert(image, 4)
mask = image_mask(image, alpha) if mask is None else image_convert(mask, 1)
h, w, c = image.shape
mask = cv2.resize(mask, (w, h))
image[..., 3] = mask if mask.ndim == 2 else mask[:, :, 0]
return image
+2
View File
@@ -472,6 +472,8 @@ def image_translate(image: TYPE_IMAGE, offset: TYPE_fCOORD2D=(0.0, 0.0),
height, width = img.shape[:2]
scalarX = 0.333 if edge in [EnumEdge.WRAP, EnumEdge.WRAPX] else 1.0
scalarY = 0.333 if edge in [EnumEdge.WRAP, EnumEdge.WRAPY] else 1.0
scalarX = 1.0
scalarY = 1.0
M = np.float32([[1, 0, offset[0] * width * scalarX], [0, 1, offset[1] * height * scalarY]])
if edge == EnumEdge.CLIP:
+5 -6
View File
@@ -1,6 +1,4 @@
/**
* File: widget_vector.js
*/
/**/
import { app } from "../../../scripts/app.js"
import { $el } from "../../../scripts/ui.js"
@@ -164,8 +162,9 @@ const VectorWidget = (app, inputName, options, initial, desc='') => {
pointer.onClick = (eUp) => {
/* if click on header, reset to defaults */
if (index == -1) {
widget.value = Object.assign({}, widget.options.default);
if (index == -1 && eUp.shiftKey) {
widget.value = Object.assign([], widget.options.default);
return;
}
else if (index >= 0 && index < size) {
const pos = [eUp.canvasX - node.pos[0], eUp.canvasY - node.pos[1]]
@@ -200,7 +199,7 @@ const VectorWidget = (app, inputName, options, initial, desc='') => {
}
if (!this.options?.rgb) return;
const rgba = Object.values(this?.value || []);
const rgba = widget.value;
const color = colorRGB2Hex(rgba.slice(0, 3));
if (index != size && (x < 0 && rgba.length > 2)) {