#!/usr/bin/env python3 """铸渊之眼 · 视觉分析器 · 定量对比两张图的风格一致性 用法: python3 vision-analyzer.py # 对比两张图 python3 vision-analyzer.py # 分析单张图 输出JSON: style_consistency_score, color_palettes, texture_similarity, composition_analysis """ import sys import json import colorsys from PIL import Image import numpy as np def analyze_image(path, label): """分析单张图片的视觉特征""" img = Image.open(path).convert('RGB') w, h = img.size arr = np.array(img) # 1. 整体色调分析 — HSV直方图 hsv_arr = np.array([colorsys.rgb_to_hsv(r/255, g/255, b/255) for r,g,b in arr.reshape(-1, 3)]) hue_hist = np.histogram(hsv_arr[:,0], bins=12, range=(0,1))[0] sat_hist = np.histogram(hsv_arr[:,1], bins=8, range=(0,1))[0] val_hist = np.histogram(hsv_arr[:,2], bins=8, range=(0,1))[0] # 主色调 dominant_hues = [] for i in np.argsort(hue_hist)[-3:]: hue_name = ["红","橙","黄","黄绿","绿","青绿","青","蓝","紫","品红","粉红","红"][i] dominant_hues.append(hue_name) # 2. 构图分析 — 9宫格亮度和边缘密度 grid_mask = np.zeros(h, dtype=int) for i in range(1,9): grid_mask = np.where(np.arange(h) < h*i/9, i, grid_mask) # 简化:水平/垂直分三区的平均亮度 bands_h = [arr[h*i//3:h*(i+1)//3, :, :].mean() for i in range(3)] bands_v = [arr[:, w*i//3:w*(i+1)//3, :].mean() for i in range(3)] # 3. 纹理复杂度 — 标准差 texture_std = arr.std(axis=(0,1)).mean() # 4. 色彩丰富度 color_variance = hsv_arr[:,1].std() # 5. 亮暗对比度 contrast = arr.max() - arr.min() avg_brightness = arr.mean() return { "label": label, "size": [w, h], "dominant_hues": dominant_hues, "avg_brightness": round(float(avg_brightness), 1), "contrast": round(float(contrast), 1), "texture_std": round(float(texture_std), 1), "color_variance": round(float(color_variance), 3), "horizontal_brightness": [round(float(b), 1) for b in bands_h], "vertical_brightness": [round(float(b), 1) for b in bands_v], "hue_distribution": [int(h) for h in hue_hist], "sat_distribution": [int(s) for s in sat_hist], "val_distribution": [int(v) for v in val_hist] } def compare_images(a, b): """对比两张图并给出风格一致性评分""" # 色调相似度 — hue分布的相关性 h1, h2 = np.array(a["hue_distribution"]), np.array(b["hue_distribution"]) if h1.sum() > 0 and h2.sum() > 0: h1_norm, h2_norm = h1/h1.sum(), h2/h2.sum() hue_corr = np.corrcoef(h1_norm, h2_norm)[0,1] else: hue_corr = 0 hue_score = max(0, float(hue_corr)) # 亮度相似度 bright_diff = abs(a["avg_brightness"] - b["avg_brightness"]) bright_score = max(0, 1 - bright_diff / 100) # 纹理相似度 tex_diff = abs(a["texture_std"] - b["texture_std"]) tex_score = max(0, 1 - tex_diff / 50) # 色彩丰富度相似度 cv_diff = abs(a["color_variance"] - b["color_variance"]) cv_score = max(0, 1 - cv_diff * 10) # 综合评分 consistency = round(float(hue_score * 0.35 + bright_score * 0.25 + tex_score * 0.25 + cv_score * 0.15) * 100, 1) verdict = ( "✅ 高度一致" if consistency >= 85 else "🟢 基本一致" if consistency >= 70 else "🟡 有差异" if consistency >= 50 else "🔴 严重不一致" ) return { "style_consistency_score": consistency, "verdict": verdict, "breakdown": { "色调相似度": round(float(hue_score * 100), 1), "亮度相似度": round(float(bright_score * 100), 1), "纹理相似度": round(float(tex_score * 100), 1), "色彩丰富度相似度": round(float(cv_score * 100), 1) }, "issues": [] } if __name__ == "__main__": if len(sys.argv) < 2: print(json.dumps({"error": "usage: vision-analyzer.py [image2]"})) sys.exit(1) if len(sys.argv) == 2: result = analyze_image(sys.argv[1], sys.argv[1]) else: a = analyze_image(sys.argv[1], sys.argv[1]) b = analyze_image(sys.argv[2], sys.argv[2]) comparison = compare_images(a, b) result = { "image_a": a, "image_b": b, "comparison": comparison } print(json.dumps(result, ensure_ascii=False, indent=2))