"""色准测试结果绘制。 Step 2 重构:从 pqAutomationApp.PQAutomationApp.plot_accuracy 原样搬迁。 """ from matplotlib.patches import Rectangle def plot_accuracy(self, accuracy_data, test_type): """绘制色准测试结果 - 29色显示 - 简洁版布局(显示 Gamma)""" 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(self.accuracy_chart_frame)