Files
filliptm-comfyui-fl-penguinvl/fl_utils/tensor_utils.py
T
Machine DelusionsandClaude Opus 4.6 0bdacabcbd Initial release: FL PenguinVL v1.0.0
Vision-language model nodes for ComfyUI using Tencent's Penguin-VL.
Includes image query, video query, batch image query, and model loader nodes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 01:30:41 -07:00

48 lines
1.4 KiB
Python

"""
Tensor conversion utilities for ComfyUI <-> PIL.
"""
import torch
import numpy as np
from PIL import Image
from typing import List
def comfyui_tensor_to_pil(tensor: torch.Tensor) -> Image.Image:
"""
Convert a single ComfyUI IMAGE frame [H, W, C] (float 0-1) to PIL.
"""
np_img = (tensor.cpu().numpy() * 255).clip(0, 255).astype(np.uint8)
return Image.fromarray(np_img)
def comfyui_batch_to_pil_list(tensor: torch.Tensor) -> List[Image.Image]:
"""
Convert ComfyUI IMAGE batch [B, H, W, C] to list of PIL images.
"""
return [comfyui_tensor_to_pil(tensor[i]) for i in range(tensor.shape[0])]
def resize_long_side(img: Image.Image, max_size: int) -> Image.Image:
"""
Resize a PIL image so the long side equals max_size, preserving aspect ratio.
Returns the image unchanged if already within bounds.
"""
w, h = img.size
if max(w, h) <= max_size:
return img
scale = max_size / max(w, h)
return img.resize((int(w * scale), int(h * scale)), Image.LANCZOS)
def sample_frames_uniformly(tensor: torch.Tensor, max_frames: int) -> torch.Tensor:
"""
Uniformly sample max_frames from a batch tensor [B, H, W, C].
If B <= max_frames, returns tensor unchanged.
"""
B = tensor.shape[0]
if B <= max_frames:
return tensor
indices = torch.linspace(0, B - 1, max_frames).long()
return tensor[indices]