Files
2025-04-27 11:22:14 +08:00

175 lines
6.3 KiB
Python

import vtracer
import tempfile
from wand.image import Image as WandImage
from PIL import Image as PILImage
import torch
import numpy as np
import os
class Vector:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"image": ("IMAGE",),
"colormode": (["color", "binary"], {
"default": "color"
}),
"hierarchical": (["stacked", "cutout"], {
"default": "stacked"
}),
"mode": (["spline", "polygon", "none"], {
"default": "spline"
}),
"filter_speckle": ("INT", {
"default": 4,
"min": 1,
"max": 128,
"step": 1
}),
"color_precision": ("INT", {
"default": 6,
"min": 1,
"max": 10,
"step": 1
}),
"layer_difference": ("INT", {
"default": 16,
"min": 1,
"max": 20,
"step": 1
}),
"corner_threshold": ("INT", {
"default": 60,
"min": 1,
"max": 100,
"step": 1
}),
"length_threshold": ("FLOAT", {
"default": 4.0,
"min": 3.5,
"max": 10.0,
"step": 0.1
}),
"max_iterations": ("INT", {
"default": 10,
"min": 1,
"max": 20,
"step": 1
}),
"splice_threshold": ("INT", {
"default": 45,
"min": 1,
"max": 100,
"step": 1
}),
"path_precision": ("INT", {
"default": 8,
"min": 1,
"max": 10,
"step": 1
}),
"output_directory": ("STRING", {
"default": ""
})
}
}
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("vector_image",)
FUNCTION = "process_image"
#OUTPUT_NODE = False
CATEGORY = "Image Vector"
def process_image(self, image, output_directory, colormode, hierarchical, mode, filter_speckle, color_precision,
layer_difference, corner_threshold, length_threshold, max_iterations, splice_threshold, path_precision):
try:
print(f"输入图像形状:{image.shape}")
# 确保输入 Tensor 是四维,具有 (B, C, H, W) 结构
if len(image.shape) == 4:
# 将图像从 (1, H, W, C) 转换为 (H, W, C)
image = image.squeeze(0)
print(f"处理后的图像形状:{image.shape}")
# 将 Tensor 转换为 PIL 图像
image_array = image.numpy()
image_array = (image_array * 255).astype(np.uint8)
pil_image = PILImage.fromarray(image_array)
print(f"转换后的 PIL 图像:{pil_image}")
# 将输入图像保存到临时文件
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as temp_img_file:
pil_image.save(temp_img_file, format="PNG")
temp_img_path = temp_img_file.name
print(f"临时 PNG 文件路径:{temp_img_path}")
base_filename = os.path.splitext(os.path.basename(temp_img_path))[0]
# 检查并创建输出目录
if not output_directory:
output_directory = tempfile.gettempdir()
elif not os.path.exists(output_directory):
os.makedirs(output_directory)
# 生成 SVG 文件路径
svg_filename = os.path.join(output_directory, f"{base_filename}.svg")
print(f"SVG 文件路径:{svg_filename}")
# 使用 vtracer 将图像转换为 SVG
vtracer.convert_image_to_svg_py(temp_img_path,
svg_filename,
colormode=colormode,
hierarchical=hierarchical,
mode=mode,
filter_speckle=filter_speckle,
color_precision=color_precision,
layer_difference=layer_difference,
corner_threshold=corner_threshold,
length_threshold=length_threshold,
max_iterations=max_iterations,
splice_threshold=splice_threshold,
path_precision=path_precision)
print("SVG 文件已成功生成")
# 使用 wand 将 SVG 转换为 PNG
with WandImage(filename=svg_filename) as wand_image:
wand_image.format = 'png'
output_png_filename = os.path.join(output_directory, f"{base_filename}.png")
wand_image.save(filename=output_png_filename)
# 读取转换后的 PNG 图像
output_image = PILImage.open(output_png_filename).convert('RGB')
print(f"转换后的图像信息: 模式={output_image.mode}, 尺寸={output_image.size}")
# 将 PIL 图像转换为 torch tensor
tensor_image = torch.from_numpy(np.array(output_image)).permute(2, 0, 1).float() / 255
print(f"tensor 图像形状: {tensor_image.shape}, 最大值: {tensor_image.max()}, 最小值: {tensor_image.min()}")
return (tensor_image,)
except Exception as e:
print(f"错误:{str(e)}")
return (None,)
NODE_CLASS_MAPPINGS = {
"Vector": Vector
}
NODE_DISPLAY_NAME_MAPPINGS = {
"Vector": "Vector"
}