Files
2026-04-22 16:26:26 +08:00

100 lines
3.5 KiB
Python

import torch
import json
class GrayBalanceFromPoint:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
"positive_coords": ("*", {"tooltip": "Connect PointsEditor positive_coords output"}), # 无文本框,仅连线
}
}
RETURN_TYPES = ("IMAGE", "STRING")
RETURN_NAMES = ("image", "balance_data")
FUNCTION = "apply"
CATEGORY = "image/color"
def apply(self, images, positive_coords):
# 如果 positive_coords 不是字符串,尝试转换(安全起见)
if not isinstance(positive_coords, str):
# 可能是 bytes 或其他类型,转为字符串
try:
positive_coords = str(positive_coords)
except:
raise ValueError("positive_coords must be a JSON string from PointsEditor")
if not positive_coords or not positive_coords.strip():
raise ValueError("positive_coords is empty. Please connect PointsEditor output.")
try:
points = json.loads(positive_coords)
if not isinstance(points, list) or len(points) == 0:
raise ValueError("positive_coords must be a non-empty list")
except Exception as e:
raise ValueError(f"Failed to parse positive_coords: {e}")
# 取批次中的第一张图像作为参考(所有图像使用相同的增益)
ref_img = images[0] # (H, W, C)
H, W, _ = ref_img.shape
# 提取所有点的 RGB 值
r_sum = 0.0
g_sum = 0.0
b_sum = 0.0
n = len(points)
for pt in points:
x = pt.get("x")
y = pt.get("y")
if x is None or y is None:
raise ValueError("Invalid point format, missing x or y")
xi = min(max(x, 0), W-1)
yi = min(max(y, 0), H-1)
rgb = ref_img[yi, xi, :3]
r_sum += rgb[0].item()
g_sum += rgb[1].item()
b_sum += rgb[2].item()
avg_r = r_sum / n
avg_g = g_sum / n
avg_b = b_sum / n
# 目标灰值:三个通道的平均值
target_gray = (avg_r + avg_g + avg_b) / 3.0
# 计算增益,避免除零
eps = 1e-6
gain_r = target_gray / (avg_r + eps)
gain_g = target_gray / (avg_g + eps)
gain_b = target_gray / (avg_b + eps)
# 记录增益数据
data = {
"r_gain": round(gain_r, 6),
"g_gain": round(gain_g, 6),
"b_gain": round(gain_b, 6),
"avg_source_rgb": [round(avg_r, 4), round(avg_g, 4), round(avg_b, 4)],
"target_gray": round(target_gray, 4),
"points_count": n
}
data_json = json.dumps(data, indent=2)
# 应用到所有输入图像
batch = []
for img in images:
corrected = img.clone()
corrected[..., 0] = torch.clamp(img[..., 0] * gain_r, 0.0, 1.0)
corrected[..., 1] = torch.clamp(img[..., 1] * gain_g, 0.0, 1.0)
corrected[..., 2] = torch.clamp(img[..., 2] * gain_b, 0.0, 1.0)
batch.append(corrected.unsqueeze(0))
return (torch.cat(batch, dim=0), data_json)
NODE_CLASS_MAPPINGS = {
"GrayBalanceFromPoint": GrayBalanceFromPoint,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"GrayBalanceFromPoint": "Gray Balance from Point (Multi-point)",
}