Create Voronoi Mask¶
Documentation¶
- Class name:
CreateVoronoiMask
- Category:
KJNodes/masking/generate
- Output node:
False
The CreateVoronoiMask node is designed to generate dynamic Voronoi diagram-based masks. It utilizes parameters such as the number of points, line width, and speed to create evolving masks over a series of frames, allowing for the creation of complex and visually interesting patterns that can be used in various graphical applications.
Input types¶
Required¶
frames
- Specifies the number of frames over which the Voronoi mask will evolve, creating a dynamic sequence of masks.
- Comfy dtype:
INT
- Python dtype:
int
num_points
- Determines the number of points used to generate the Voronoi diagram, directly affecting the complexity and appearance of the resulting mask.
- Comfy dtype:
INT
- Python dtype:
int
line_width
- Controls the thickness of the lines in the Voronoi diagram, influencing the visual style of the mask.
- Comfy dtype:
INT
- Python dtype:
int
speed
- Adjusts the rate at which the points in the Voronoi diagram move, affecting the dynamic evolution of the mask over the frames.
- Comfy dtype:
FLOAT
- Python dtype:
float
frame_width
- Sets the width of the frame for the mask, defining the horizontal dimension of the output.
- Comfy dtype:
INT
- Python dtype:
int
frame_height
- Sets the height of the frame for the mask, defining the vertical dimension of the output.
- Comfy dtype:
INT
- Python dtype:
int
Output types¶
mask
- Comfy dtype:
MASK
- The output is a tensor representing the generated Voronoi mask, suitable for use in graphical applications.
- Python dtype:
torch.Tensor
- Comfy dtype:
mask_inverted
- Comfy dtype:
MASK
- The output is a tensor representing the inverted Voronoi mask, providing an alternative visual pattern for use in graphical applications.
- Python dtype:
torch.Tensor
- Comfy dtype:
Usage tips¶
- Infra type:
CPU
- Common nodes: unknown
Source code¶
class CreateVoronoiMask:
RETURN_TYPES = ("MASK", "MASK",)
RETURN_NAMES = ("mask", "mask_inverted",)
FUNCTION = "createvoronoi"
CATEGORY = "KJNodes/masking/generate"
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"frames": ("INT", {"default": 16,"min": 2, "max": 4096, "step": 1}),
"num_points": ("INT", {"default": 15,"min": 1, "max": 4096, "step": 1}),
"line_width": ("INT", {"default": 4,"min": 1, "max": 4096, "step": 1}),
"speed": ("FLOAT", {"default": 0.5,"min": 0.0, "max": 1.0, "step": 0.01}),
"frame_width": ("INT", {"default": 512,"min": 16, "max": 4096, "step": 1}),
"frame_height": ("INT", {"default": 512,"min": 16, "max": 4096, "step": 1}),
},
}
def createvoronoi(self, frames, num_points, line_width, speed, frame_width, frame_height):
from scipy.spatial import Voronoi
# Define the number of images in the batch
batch_size = frames
out = []
# Calculate aspect ratio
aspect_ratio = frame_width / frame_height
# Create start and end points for each point, considering the aspect ratio
start_points = np.random.rand(num_points, 2)
start_points[:, 0] *= aspect_ratio
end_points = np.random.rand(num_points, 2)
end_points[:, 0] *= aspect_ratio
for i in range(batch_size):
# Interpolate the points' positions based on the current frame
t = (i * speed) / (batch_size - 1) # normalize to [0, 1] over the frames
t = np.clip(t, 0, 1) # ensure t is in [0, 1]
points = (1 - t) * start_points + t * end_points # lerp
# Adjust points for aspect ratio
points[:, 0] *= aspect_ratio
vor = Voronoi(points)
# Create a blank image with a white background
fig, ax = plt.subplots()
plt.subplots_adjust(left=0, right=1, bottom=0, top=1)
ax.set_xlim([0, aspect_ratio]); ax.set_ylim([0, 1]) # adjust x limits
ax.axis('off')
ax.margins(0, 0)
fig.set_size_inches(aspect_ratio * frame_height/100, frame_height/100) # adjust figure size
ax.fill_between([0, 1], [0, 1], color='white')
# Plot each Voronoi ridge
for simplex in vor.ridge_vertices:
simplex = np.asarray(simplex)
if np.all(simplex >= 0):
plt.plot(vor.vertices[simplex, 0], vor.vertices[simplex, 1], 'k-', linewidth=line_width)
fig.canvas.draw()
img = np.array(fig.canvas.renderer._renderer)
plt.close(fig)
pil_img = Image.fromarray(img).convert("L")
mask = torch.tensor(np.array(pil_img)) / 255.0
out.append(mask)
return (torch.stack(out, dim=0), 1.0 - torch.stack(out, dim=0),)