319 lines
8.6 KiB
Python
319 lines
8.6 KiB
Python
|
|
"""色准测试结果绘制。
|
|||
|
|
|
|||
|
|
Step 2 重构:从 pqAutomationApp.PQAutomationApp.plot_accuracy 原样搬迁。
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
from matplotlib.patches import Rectangle
|
|||
|
|
|
|||
|
|
|
|||
|
|
def plot_accuracy(app, accuracy_data, test_type):
|
|||
|
|
"""绘制色准测试结果 - 29色显示 - 简洁版布局(显示 Gamma)"""
|
|||
|
|
self = app
|
|||
|
|
|
|||
|
|
self.accuracy_ax.clear()
|
|||
|
|
self.accuracy_ax.set_xlim(0, 1)
|
|||
|
|
self.accuracy_ax.set_ylim(0, 1)
|
|||
|
|
self.accuracy_ax.axis("off")
|
|||
|
|
|
|||
|
|
self.accuracy_fig.subplots_adjust(
|
|||
|
|
left=0.05,
|
|||
|
|
right=0.95,
|
|||
|
|
top=0.95,
|
|||
|
|
bottom=0.02,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 获取色准数据
|
|||
|
|
color_patches = accuracy_data.get("color_patches", [])
|
|||
|
|
delta_e_values = accuracy_data.get("delta_e_values", [])
|
|||
|
|
avg_delta_e = accuracy_data.get("avg_delta_e", 0)
|
|||
|
|
max_delta_e = accuracy_data.get("max_delta_e", 0)
|
|||
|
|
min_delta_e = accuracy_data.get("min_delta_e", 0)
|
|||
|
|
excellent_count = accuracy_data.get("excellent_count", 0)
|
|||
|
|
good_count = accuracy_data.get("good_count", 0)
|
|||
|
|
poor_count = accuracy_data.get("poor_count", 0)
|
|||
|
|
|
|||
|
|
# 获取 Gamma 值
|
|||
|
|
target_gamma = accuracy_data.get("target_gamma", 2.2)
|
|||
|
|
|
|||
|
|
test_type_name = self.get_test_type_name(test_type)
|
|||
|
|
|
|||
|
|
# ========== 标题(动态显示 Gamma)==========
|
|||
|
|
if test_type == "sdr_movie":
|
|||
|
|
title = f"{test_type_name} - 色准测试(全 29色 | Gamma {target_gamma})"
|
|||
|
|
elif test_type == "hdr_movie":
|
|||
|
|
title = f"{test_type_name} - 色准测试(全 29色 | PQ EOTF)"
|
|||
|
|
else: # screen_module
|
|||
|
|
title = f"{test_type_name} - 色准测试(全 29色 | Gamma {target_gamma})"
|
|||
|
|
|
|||
|
|
self.accuracy_fig.suptitle(
|
|||
|
|
title,
|
|||
|
|
fontsize=11,
|
|||
|
|
y=0.98,
|
|||
|
|
fontweight="bold",
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# ========== 29色:6行5列布局 ==========
|
|||
|
|
cols = 5
|
|||
|
|
rows = 6
|
|||
|
|
|
|||
|
|
patch_width = 0.135
|
|||
|
|
patch_height = 0.085
|
|||
|
|
x_start = 0.08
|
|||
|
|
y_start = 0.90
|
|||
|
|
x_gap = 0.035
|
|||
|
|
y_gap = 0.050
|
|||
|
|
|
|||
|
|
# ========== 绘制色块 ==========
|
|||
|
|
for i, (color_name, delta_e) in enumerate(zip(color_patches, delta_e_values)):
|
|||
|
|
row = i // cols
|
|||
|
|
col = i % cols
|
|||
|
|
|
|||
|
|
x = x_start + col * (patch_width + x_gap)
|
|||
|
|
y = y_start - row * (patch_height + y_gap)
|
|||
|
|
|
|||
|
|
# 颜色映射
|
|||
|
|
color_map = {
|
|||
|
|
# 灰阶
|
|||
|
|
"White": "#FFFFFF",
|
|||
|
|
"Gray 80": "#E6E6E6",
|
|||
|
|
"Gray 65": "#D1D1D1",
|
|||
|
|
"Gray 50": "#BABABA",
|
|||
|
|
"Gray 35": "#9E9E9E",
|
|||
|
|
# 饱和色
|
|||
|
|
"100% Red": "#FF0000",
|
|||
|
|
"100% Green": "#00FF00",
|
|||
|
|
"100% Blue": "#0000FF",
|
|||
|
|
"100% Cyan": "#00FFFF",
|
|||
|
|
"100% Magenta": "#FF00FF",
|
|||
|
|
"100% Yellow": "#FFFF00",
|
|||
|
|
# ColorChecker 颜色
|
|||
|
|
"Dark Skin": "#735242",
|
|||
|
|
"Light Skin": "#C29682",
|
|||
|
|
"Blue Sky": "#5E7A9C",
|
|||
|
|
"Foliage": "#596B42",
|
|||
|
|
"Blue Flower": "#8280B0",
|
|||
|
|
"Bluish Green": "#63BDA8",
|
|||
|
|
"Orange": "#D97829",
|
|||
|
|
"Purplish Blue": "#4A5CA3",
|
|||
|
|
"Moderate Red": "#C25461",
|
|||
|
|
"Purple": "#5C3D6B",
|
|||
|
|
"Yellow Green": "#9EBA40",
|
|||
|
|
"Orange Yellow": "#E6A12E",
|
|||
|
|
"Blue (Legacy)": "#333D96",
|
|||
|
|
"Green (Legacy)": "#479447",
|
|||
|
|
"Red (Legacy)": "#B0303B",
|
|||
|
|
"Yellow (Legacy)": "#EDC721",
|
|||
|
|
"Magenta (Legacy)": "#BA5491",
|
|||
|
|
"Cyan (Legacy)": "#0085A3",
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
patch_color = color_map.get(color_name, "#808080")
|
|||
|
|
|
|||
|
|
# ΔE 等级颜色
|
|||
|
|
if delta_e < 3:
|
|||
|
|
edge_color = "green"
|
|||
|
|
elif delta_e < 5:
|
|||
|
|
edge_color = "orange"
|
|||
|
|
else:
|
|||
|
|
edge_color = "red"
|
|||
|
|
|
|||
|
|
# 绘制色块
|
|||
|
|
rect = Rectangle(
|
|||
|
|
(x, y),
|
|||
|
|
patch_width,
|
|||
|
|
patch_height,
|
|||
|
|
transform=self.accuracy_ax.transAxes,
|
|||
|
|
facecolor=patch_color,
|
|||
|
|
edgecolor=edge_color,
|
|||
|
|
linewidth=1.8,
|
|||
|
|
)
|
|||
|
|
self.accuracy_ax.add_patch(rect)
|
|||
|
|
|
|||
|
|
# ========== 标注色块名称(上方)==========
|
|||
|
|
self.accuracy_ax.text(
|
|||
|
|
x + patch_width / 2,
|
|||
|
|
y + patch_height + 0.015,
|
|||
|
|
color_name,
|
|||
|
|
ha="center",
|
|||
|
|
va="bottom",
|
|||
|
|
fontsize=5.5,
|
|||
|
|
fontweight="bold",
|
|||
|
|
transform=self.accuracy_ax.transAxes,
|
|||
|
|
clip_on=False,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# ========== 标注 ΔE 值(中心)==========
|
|||
|
|
dark_colors = [
|
|||
|
|
"100% Red",
|
|||
|
|
"100% Green",
|
|||
|
|
"100% Blue",
|
|||
|
|
"Gray 35",
|
|||
|
|
"Dark Skin",
|
|||
|
|
"Foliage",
|
|||
|
|
"Purple",
|
|||
|
|
"Purplish Blue",
|
|||
|
|
"Blue (Legacy)",
|
|||
|
|
"Green (Legacy)",
|
|||
|
|
"Red (Legacy)",
|
|||
|
|
"Magenta (Legacy)",
|
|||
|
|
"Cyan (Legacy)",
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
text_color = "white" if color_name in dark_colors else "black"
|
|||
|
|
|
|||
|
|
self.accuracy_ax.text(
|
|||
|
|
x + patch_width / 2,
|
|||
|
|
y + patch_height / 2,
|
|||
|
|
f"ΔE\n{delta_e:.2f}",
|
|||
|
|
ha="center",
|
|||
|
|
va="center",
|
|||
|
|
fontsize=5.2,
|
|||
|
|
fontweight="bold",
|
|||
|
|
color=text_color,
|
|||
|
|
transform=self.accuracy_ax.transAxes,
|
|||
|
|
bbox=dict(
|
|||
|
|
boxstyle="round,pad=0.22",
|
|||
|
|
facecolor="white" if text_color == "black" else "black",
|
|||
|
|
alpha=0.75,
|
|||
|
|
edgecolor=edge_color,
|
|||
|
|
linewidth=1.0,
|
|||
|
|
),
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# ========== 统计信息卡片(只保留外框)==========
|
|||
|
|
card_width = 0.84
|
|||
|
|
card_height = 0.15
|
|||
|
|
card_x = 0.08
|
|||
|
|
card_y = 0.01
|
|||
|
|
|
|||
|
|
info_card = Rectangle(
|
|||
|
|
(card_x, card_y),
|
|||
|
|
card_width,
|
|||
|
|
card_height,
|
|||
|
|
transform=self.accuracy_ax.transAxes,
|
|||
|
|
facecolor="#F0F0F0",
|
|||
|
|
edgecolor="black",
|
|||
|
|
linewidth=1.5,
|
|||
|
|
)
|
|||
|
|
self.accuracy_ax.add_patch(info_card)
|
|||
|
|
|
|||
|
|
# ========== 标题(带说明)==========
|
|||
|
|
self.accuracy_ax.text(
|
|||
|
|
card_x + card_width / 2,
|
|||
|
|
card_y + card_height - 0.008,
|
|||
|
|
"色准统计(5灰阶 + 18 ColorChecker + 6饱和色 | ΔE 2000 标准)",
|
|||
|
|
ha="center",
|
|||
|
|
va="top",
|
|||
|
|
fontsize=7.5,
|
|||
|
|
fontweight="bold",
|
|||
|
|
transform=self.accuracy_ax.transAxes,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# ========== 统计内容(无内部框)==========
|
|||
|
|
stats_y = card_y + card_height * 0.55
|
|||
|
|
|
|||
|
|
# 左侧:ΔE 统计
|
|||
|
|
left_x = card_x + 0.02
|
|||
|
|
stats_text = [
|
|||
|
|
f"平均 ΔE: {avg_delta_e:.2f}",
|
|||
|
|
f"最大 ΔE: {max_delta_e:.2f}",
|
|||
|
|
f"最小 ΔE: {min_delta_e:.2f}",
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
for i, text in enumerate(stats_text):
|
|||
|
|
self.accuracy_ax.text(
|
|||
|
|
left_x,
|
|||
|
|
stats_y - i * 0.030,
|
|||
|
|
text,
|
|||
|
|
ha="left",
|
|||
|
|
va="center",
|
|||
|
|
fontsize=7,
|
|||
|
|
fontweight="bold",
|
|||
|
|
transform=self.accuracy_ax.transAxes,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 中间:色块统计
|
|||
|
|
middle_x = card_x + card_width * 0.32
|
|||
|
|
|
|||
|
|
self.accuracy_ax.text(
|
|||
|
|
middle_x,
|
|||
|
|
stats_y,
|
|||
|
|
f"优秀 (ΔE<3): {excellent_count} 个",
|
|||
|
|
ha="left",
|
|||
|
|
va="center",
|
|||
|
|
fontsize=7,
|
|||
|
|
color="green",
|
|||
|
|
fontweight="bold",
|
|||
|
|
transform=self.accuracy_ax.transAxes,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
self.accuracy_ax.text(
|
|||
|
|
middle_x,
|
|||
|
|
stats_y - 0.030,
|
|||
|
|
f"良好 (3≤ΔE<5): {good_count} 个",
|
|||
|
|
ha="left",
|
|||
|
|
va="center",
|
|||
|
|
fontsize=7,
|
|||
|
|
color="orange",
|
|||
|
|
fontweight="bold",
|
|||
|
|
transform=self.accuracy_ax.transAxes,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
self.accuracy_ax.text(
|
|||
|
|
middle_x,
|
|||
|
|
stats_y - 0.060,
|
|||
|
|
f"偏差 (ΔE≥5): {poor_count} 个",
|
|||
|
|
ha="left",
|
|||
|
|
va="center",
|
|||
|
|
fontsize=7,
|
|||
|
|
color="red",
|
|||
|
|
fontweight="bold",
|
|||
|
|
transform=self.accuracy_ax.transAxes,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 右侧:总体评价
|
|||
|
|
right_x = card_x + card_width - 0.02
|
|||
|
|
|
|||
|
|
if avg_delta_e < 2:
|
|||
|
|
grade = "专业级"
|
|||
|
|
grade_icon = "★★★"
|
|||
|
|
grade_color = "darkgreen"
|
|||
|
|
elif avg_delta_e < 3:
|
|||
|
|
grade = "优秀"
|
|||
|
|
grade_icon = "✓✓"
|
|||
|
|
grade_color = "green"
|
|||
|
|
elif avg_delta_e < 5:
|
|||
|
|
grade = "良好"
|
|||
|
|
grade_icon = "✓"
|
|||
|
|
grade_color = "orange"
|
|||
|
|
else:
|
|||
|
|
grade = "需要校准"
|
|||
|
|
grade_icon = "✗"
|
|||
|
|
grade_color = "red"
|
|||
|
|
|
|||
|
|
self.accuracy_ax.text(
|
|||
|
|
right_x,
|
|||
|
|
stats_y + 0.020,
|
|||
|
|
"总体评价:",
|
|||
|
|
ha="right",
|
|||
|
|
va="bottom",
|
|||
|
|
fontsize=7,
|
|||
|
|
fontweight="bold",
|
|||
|
|
transform=self.accuracy_ax.transAxes,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
self.accuracy_ax.text(
|
|||
|
|
right_x,
|
|||
|
|
stats_y - 0.025,
|
|||
|
|
f"{grade} {grade_icon}",
|
|||
|
|
ha="right",
|
|||
|
|
va="top",
|
|||
|
|
fontsize=11,
|
|||
|
|
fontweight="bold",
|
|||
|
|
color=grade_color,
|
|||
|
|
transform=self.accuracy_ax.transAxes,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
self.accuracy_canvas.draw()
|
|||
|
|
self.chart_notebook.select(4)
|