Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
chenpangpang
ComfyUI
Commits
8c730dc4
Commit
8c730dc4
authored
Aug 12, 2023
by
comfyanonymous
Browse files
Add an ImageCompositeMasked node.
parent
c8a23ce9
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
52 additions
and
27 deletions
+52
-27
comfy_extras/nodes_mask.py
comfy_extras/nodes_mask.py
+52
-27
No files found.
comfy_extras/nodes_mask.py
View file @
8c730dc4
...
@@ -2,6 +2,35 @@ import torch
...
@@ -2,6 +2,35 @@ import torch
from
nodes
import
MAX_RESOLUTION
from
nodes
import
MAX_RESOLUTION
def
composite
(
destination
,
source
,
x
,
y
,
mask
=
None
,
multiplier
=
8
):
x
=
max
(
-
source
.
shape
[
3
]
*
multiplier
,
min
(
x
,
destination
.
shape
[
3
]
*
multiplier
))
y
=
max
(
-
source
.
shape
[
2
]
*
multiplier
,
min
(
y
,
destination
.
shape
[
2
]
*
multiplier
))
left
,
top
=
(
x
//
multiplier
,
y
//
multiplier
)
right
,
bottom
=
(
left
+
source
.
shape
[
3
],
top
+
source
.
shape
[
2
],)
if
mask
is
None
:
mask
=
torch
.
ones_like
(
source
)
else
:
mask
=
mask
.
clone
()
mask
=
torch
.
nn
.
functional
.
interpolate
(
mask
[
None
,
None
],
size
=
(
source
.
shape
[
2
],
source
.
shape
[
3
]),
mode
=
"bilinear"
)
mask
=
mask
.
repeat
((
source
.
shape
[
0
],
source
.
shape
[
1
],
1
,
1
))
# calculate the bounds of the source that will be overlapping the destination
# this prevents the source trying to overwrite latent pixels that are out of bounds
# of the destination
visible_width
,
visible_height
=
(
destination
.
shape
[
3
]
-
left
+
min
(
0
,
x
),
destination
.
shape
[
2
]
-
top
+
min
(
0
,
y
),)
mask
=
mask
[:,
:,
:
visible_height
,
:
visible_width
]
inverse_mask
=
torch
.
ones_like
(
mask
)
-
mask
source_portion
=
mask
*
source
[:,
:,
:
visible_height
,
:
visible_width
]
destination_portion
=
inverse_mask
*
destination
[:,
:,
top
:
bottom
,
left
:
right
]
destination
[:,
:,
top
:
bottom
,
left
:
right
]
=
source_portion
+
destination_portion
return
destination
class
LatentCompositeMasked
:
class
LatentCompositeMasked
:
@
classmethod
@
classmethod
def
INPUT_TYPES
(
s
):
def
INPUT_TYPES
(
s
):
...
@@ -25,36 +54,31 @@ class LatentCompositeMasked:
...
@@ -25,36 +54,31 @@ class LatentCompositeMasked:
output
=
destination
.
copy
()
output
=
destination
.
copy
()
destination
=
destination
[
"samples"
].
clone
()
destination
=
destination
[
"samples"
].
clone
()
source
=
source
[
"samples"
]
source
=
source
[
"samples"
]
output
[
"samples"
]
=
composite
(
destination
,
source
,
x
,
y
,
mask
,
8
)
return
(
output
,)
x
=
max
(
-
source
.
shape
[
3
]
*
8
,
min
(
x
,
destination
.
shape
[
3
]
*
8
))
class
ImageCompositeMasked
:
y
=
max
(
-
source
.
shape
[
2
]
*
8
,
min
(
y
,
destination
.
shape
[
2
]
*
8
))
@
classmethod
def
INPUT_TYPES
(
s
):
left
,
top
=
(
x
//
8
,
y
//
8
)
return
{
right
,
bottom
=
(
left
+
source
.
shape
[
3
],
top
+
source
.
shape
[
2
],)
"required"
:
{
"destination"
:
(
"IMAGE"
,),
"source"
:
(
"IMAGE"
,),
if
mask
is
None
:
"x"
:
(
"INT"
,
{
"default"
:
0
,
"min"
:
0
,
"max"
:
MAX_RESOLUTION
,
"step"
:
1
}),
mask
=
torch
.
ones_like
(
source
)
"y"
:
(
"INT"
,
{
"default"
:
0
,
"min"
:
0
,
"max"
:
MAX_RESOLUTION
,
"step"
:
1
}),
else
:
},
mask
=
mask
.
clone
()
"optional"
:
{
mask
=
torch
.
nn
.
functional
.
interpolate
(
mask
[
None
,
None
],
size
=
(
source
.
shape
[
2
],
source
.
shape
[
3
]),
mode
=
"bilinear"
)
"mask"
:
(
"MASK"
,),
mask
=
mask
.
repeat
((
source
.
shape
[
0
],
source
.
shape
[
1
],
1
,
1
))
}
}
# calculate the bounds of the source that will be overlapping the destination
RETURN_TYPES
=
(
"IMAGE"
,)
# this prevents the source trying to overwrite latent pixels that are out of bounds
FUNCTION
=
"composite"
# of the destination
visible_width
,
visible_height
=
(
destination
.
shape
[
3
]
-
left
+
min
(
0
,
x
),
destination
.
shape
[
2
]
-
top
+
min
(
0
,
y
),)
mask
=
mask
[:,
:,
:
visible_height
,
:
visible_width
]
inverse_mask
=
torch
.
ones_like
(
mask
)
-
mask
source_portion
=
mask
*
source
[:,
:,
:
visible_height
,
:
visible_width
]
destination_portion
=
inverse_mask
*
destination
[:,
:,
top
:
bottom
,
left
:
right
]
destination
[:,
:,
top
:
bottom
,
left
:
right
]
=
source_portion
+
destination_portion
output
[
"samples"
]
=
destination
CATEGORY
=
"image"
def
composite
(
self
,
destination
,
source
,
x
,
y
,
mask
=
None
):
destination
=
destination
.
clone
().
movedim
(
-
1
,
1
)
output
=
composite
(
destination
,
source
.
movedim
(
-
1
,
1
),
x
,
y
,
mask
,
1
).
movedim
(
1
,
-
1
)
return
(
output
,)
return
(
output
,)
class
MaskToImage
:
class
MaskToImage
:
...
@@ -253,6 +277,7 @@ class FeatherMask:
...
@@ -253,6 +277,7 @@ class FeatherMask:
NODE_CLASS_MAPPINGS
=
{
NODE_CLASS_MAPPINGS
=
{
"LatentCompositeMasked"
:
LatentCompositeMasked
,
"LatentCompositeMasked"
:
LatentCompositeMasked
,
"ImageCompositeMasked"
:
ImageCompositeMasked
,
"MaskToImage"
:
MaskToImage
,
"MaskToImage"
:
MaskToImage
,
"ImageToMask"
:
ImageToMask
,
"ImageToMask"
:
ImageToMask
,
"SolidMask"
:
SolidMask
,
"SolidMask"
:
SolidMask
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment