From c63b9ef61534199cd5860603d98dfd7e6c8d9d35 Mon Sep 17 00:00:00 2001 From: "xinzhu.yin" Date: Wed, 27 May 2026 16:26:19 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=A7=E7=BB=AD=E4=BC=98=E5=8C=96=E8=89=B2?= =?UTF-8?q?=E5=87=86=E6=B5=8B=E8=AF=95=E7=BB=93=E6=9E=9C=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/plots/plot_accuracy.py | 66 +++++++--- app/runner/test_runner.py | 221 ++++++++++++++++++++++++++++++++ app/views/chart_frame.py | 153 +++++++++++++++++++++- app/views/panels/cct_panel.py | 10 -- app/views/panels/main_layout.py | 8 ++ settings/pq_config.json | 7 +- 6 files changed, 428 insertions(+), 37 deletions(-) diff --git a/app/plots/plot_accuracy.py b/app/plots/plot_accuracy.py index b25e973..1f017c4 100644 --- a/app/plots/plot_accuracy.py +++ b/app/plots/plot_accuracy.py @@ -75,7 +75,7 @@ def _xy_to_uv(x: float, y: float): # 子图:左侧 Calman 风格面板 # ============================================================ -def _draw_left_panel(ax, color_patches, delta_e_values): +def _draw_left_panel(ax, color_patches, delta_e_values, font_scale=1.0): """左侧仅保留大条形图。""" ax.clear() @@ -99,11 +99,12 @@ def _draw_left_panel(ax, color_patches, delta_e_values): ) ax.set_yticks(y_pos) - ax.set_yticklabels(color_patches, fontsize=7) + ax.set_yticklabels(color_patches, fontsize=max(5, 7 * font_scale)) ax.invert_yaxis() x_max = max(15.0, max(delta_e_values) * 1.15) ax.set_xlim(0, x_max) + ax.tick_params(axis="x", labelsize=max(6, 8 * font_scale)) ax.grid(axis="x", linestyle="-", linewidth=0.6, alpha=0.3, zorder=0) ax.grid(axis="y", linestyle=":", linewidth=0.35, alpha=0.15, zorder=0) @@ -117,7 +118,7 @@ def _draw_left_panel(ax, color_patches, delta_e_values): # 子图:CIE 1976 u'v' 色度图(目标 vs 实测) # ============================================================ -def _draw_uv_diagram(ax, color_patches, measurements, standards): +def _draw_uv_diagram(ax, color_patches, measurements, standards, font_scale=1.0): """绘制 CIE 1976 u'v' 上的色准对比。""" ax.clear() try: @@ -136,11 +137,11 @@ def _draw_uv_diagram(ax, color_patches, measurements, standards): ax.set_facecolor("#000") ax.set_aspect("equal", adjustable="box") - ax.set_title("CIE 1976 u'v'", fontsize=11, fontweight="bold", + ax.set_title("CIE 1976 u'v'", fontsize=max(8, 11 * font_scale), fontweight="bold", color="#111", pad=4) - ax.set_xlabel("u'", fontsize=9, color="#222", labelpad=1) - ax.set_ylabel("v'", fontsize=9, color="#222", labelpad=1) - ax.tick_params(axis="both", labelsize=8, colors="#222") + ax.set_xlabel("u'", fontsize=max(7, 9 * font_scale), color="#222", labelpad=1) + ax.set_ylabel("v'", fontsize=max(7, 9 * font_scale), color="#222", labelpad=1) + ax.tick_params(axis="both", labelsize=max(6, 8 * font_scale), colors="#222") for sp in ax.spines.values(): sp.set_color("#666") sp.set_linewidth(0.9) @@ -190,7 +191,7 @@ def _draw_uv_diagram(ax, color_patches, measurements, standards): ] leg = ax.legend( handles=legend_handles, - loc="lower right", fontsize=8, + loc="lower right", fontsize=max(6, 8 * font_scale), framealpha=0.88, labelcolor="#FFF", ) if leg is not None: @@ -199,7 +200,7 @@ def _draw_uv_diagram(ax, color_patches, measurements, standards): leg.set_zorder(50) -def _draw_result_judgement(ax, accuracy_data): +def _draw_result_judgement(ax, accuracy_data, font_scale=1.0): """底部结果条""" ax.clear() ax.set_xlim(0, 1) @@ -219,14 +220,14 @@ def _draw_result_judgement(ax, accuracy_data): 0.03, 0.50, f"Avg dE2000: {avg:.2f}", ha="left", va="center", - fontsize=20, fontweight="normal", color="#111111", + fontsize=max(11, 20 * font_scale), fontweight="normal", color="#111111", transform=ax.transAxes, ) ax.text( 0.52, 0.50, f"Max dE2000: {mx:.2f}", ha="left", va="center", - fontsize=20, fontweight="normal", color="#111111", + fontsize=max(11, 20 * font_scale), fontweight="normal", color="#111111", transform=ax.transAxes, ) @@ -241,6 +242,17 @@ def plot_accuracy(self: "PQAutomationApp", accuracy_data, test_type): fig = self.accuracy_fig fig.clear() + # 根据当前画布像素尺寸动态缩放字体,避免窗口缩小时文字挤压重叠。 + font_scale = 1.0 + try: + canvas_widget = self.accuracy_canvas.get_tk_widget() + cw = max(1, int(canvas_widget.winfo_width())) + ch = max(1, int(canvas_widget.winfo_height())) + font_scale = min(cw / 1000.0, ch / 600.0) + font_scale = max(0.60, min(1.0, font_scale)) + except Exception: + font_scale = 1.0 + color_patches = accuracy_data.get("color_patches", []) or [] delta_e_values = accuracy_data.get("delta_e_values", []) or [] measurements = accuracy_data.get("color_measurements", []) or [] @@ -259,15 +271,21 @@ def plot_accuracy(self: "PQAutomationApp", accuracy_data, test_type): else: title = f"{test_type_name} - 色准测试(全 29色 | Gamma {target_gamma})" - fig.suptitle(title, fontsize=11, y=0.975, fontweight="bold", color="#111") + fig.suptitle( + title, + fontsize=max(8, 11 * font_scale), + y=0.975, + fontweight="bold", + color="#111", + ) gs = fig.add_gridspec( 2, 2, width_ratios=[1.12, 1.0], - height_ratios=[4.0, 0.62], + height_ratios=[4.8, 0.48], left=0.08, right=0.985, - top=0.91, bottom=0.06, - wspace=0.14, hspace=0.10, + top=0.92, bottom=0.05, + wspace=0.14, hspace=0.08, ) ax_left = fig.add_subplot(gs[0, 0]) @@ -277,14 +295,26 @@ def plot_accuracy(self: "PQAutomationApp", accuracy_data, test_type): # 兼容外部对 self.accuracy_ax 的引用 self.accuracy_ax = ax_judge - _draw_left_panel(ax_left, color_patches, delta_e_values) + _draw_left_panel(ax_left, color_patches, delta_e_values, font_scale=font_scale) try: standards = get_accuracy_color_standards(test_type) except Exception: standards = {} - _draw_uv_diagram(ax_uv, color_patches, measurements, standards) - _draw_result_judgement(ax_judge, accuracy_data) + + _draw_uv_diagram( + ax_uv, + color_patches, + measurements, + standards, + font_scale=font_scale, + ) + _draw_result_judgement(ax_judge, accuracy_data, font_scale=font_scale) + + try: + self.update_accuracy_result_table(accuracy_data, standards) + except Exception: + pass self.accuracy_canvas.draw() self.chart_notebook.select(self.accuracy_chart_frame) diff --git a/app/runner/test_runner.py b/app/runner/test_runner.py index 1a16612..6693c7c 100644 --- a/app/runner/test_runner.py +++ b/app/runner/test_runner.py @@ -1073,6 +1073,226 @@ def test_color_accuracy(self: "PQAutomationApp", test_type): self.log_gui.log("色准测试完成", level="success") +def run_simulation_test(self: "PQAutomationApp"): + """运行模拟测试(无需 UCD/CA),直接在 UI 展示结果。""" + try: + test_type = self.config.current_test_type + selected_items = self.get_selected_test_items() + + if not selected_items: + self.log_gui.log("未选择测试项目,无法执行模拟测试", level="error") + messagebox.showwarning("提示", "请先勾选至少一个测试项目") + return + + self.log_gui.log("=" * 60, level="separator") + self.log_gui.log("开始执行模拟测试(无需 UCD/CA 设备)", level="info") + self.log_gui.log(f"测试类型: {self.get_test_type_name(test_type)}", level="info") + self.log_gui.log( + f"测试项目: {', '.join(self.config.get_test_item_chinese_names(selected_items))}", + level="info", + ) + + if hasattr(self, "update_chart_tabs_state"): + self.update_chart_tabs_state() + if hasattr(self, "clear_chart"): + self.clear_chart() + + self.new_pq_results(test_type, f"{self.get_test_type_name(test_type)} 模拟测试") + self.status_var.set("模拟测试进行中...") + + rng = np.random.default_rng() + + def _read_ideal_xy(): + try: + if test_type == "sdr_movie": + return float(self.sdr_cct_x_ideal_var.get()), float(self.sdr_cct_y_ideal_var.get()) + if test_type == "hdr_movie": + return float(self.hdr_cct_x_ideal_var.get()), float(self.hdr_cct_y_ideal_var.get()) + return float(self.cct_x_ideal_var.get()), float(self.cct_y_ideal_var.get()) + except Exception: + return 0.3127, 0.3290 + + def _xyY_to_xyz_row(x, y, lv): + if y <= 1e-8: + return [x, y, lv, 0.0, lv, 0.0] + X = x * lv / y + Z = (1 - x - y) * lv / y + return [x, y, lv, X, lv, Z] + + # 共享灰阶数据:用于 Gamma/EOTF/CCT/对比度 + gray_results = [] + x_ideal, y_ideal = _read_ideal_xy() + peak_lv = 900.0 if test_type == "hdr_movie" else 220.0 + gamma_shape = 2.25 if test_type == "hdr_movie" else 2.20 + + for i in range(11): + p = i / 10.0 + lv = 0.08 + peak_lv * (p ** gamma_shape) + lv *= 1.0 + float(rng.normal(0.0, 0.015)) + lv = max(lv, 0.03) + + x = x_ideal + float(rng.normal(0.0, 0.0012)) + y = y_ideal + float(rng.normal(0.0, 0.0012)) + gray_results.append(_xyY_to_xyz_row(x, y, lv)) + + if any(item in selected_items for item in ("gamma", "eotf", "cct", "contrast")): + self.results.add_intermediate_data("shared", "gray", gray_results) + + # 色域模拟 + if "gamut" in selected_items: + ref_map = { + "BT.709": [(0.6400, 0.3300), (0.3000, 0.6000), (0.1500, 0.0600)], + "DCI-P3": [(0.6800, 0.3200), (0.2650, 0.6900), (0.1500, 0.0600)], + "BT.2020": [(0.7080, 0.2920), (0.1700, 0.7970), (0.1310, 0.0460)], + "BT.601": [(0.6300, 0.3400), (0.3100, 0.5950), (0.1550, 0.0700)], + } + + if test_type == "hdr_movie": + reference = self.hdr_gamut_ref_var.get() if hasattr(self, "hdr_gamut_ref_var") else "BT.2020" + elif test_type == "sdr_movie": + reference = self.sdr_gamut_ref_var.get() if hasattr(self, "sdr_gamut_ref_var") else "BT.709" + else: + reference = self.screen_gamut_ref_var.get() if hasattr(self, "screen_gamut_ref_var") else "DCI-P3" + + if reference not in ref_map: + reference = "DCI-P3" + + gamut_results = [] + for rx, ry in ref_map[reference]: + mx = rx + float(rng.normal(0.0, 0.006)) + my = ry + float(rng.normal(0.0, 0.006)) + gamut_results.append(_xyY_to_xyz_row(mx, my, 120.0)) + + self.results.add_intermediate_data("gamut", "rgb", gamut_results) + self.results.set_test_item_result( + "gamut", + { + "area": 0.0, + "coverage": 95.0, + "uv_coverage": 93.0, + "reference": reference, + }, + ) + self.plot_gamut(gamut_results, 95.0, test_type) + + # Gamma / EOTF 模拟 + if "gamma" in selected_items and test_type != "hdr_movie": + pattern_params = self.config.default_pattern_gray.get("pattern_params", None) + results_with_gamma, L_bar = self.calculate_gamma( + gray_results, len(gray_results) - 1, pattern_params + ) + self.results.set_test_item_result("gamma", {"gamma": results_with_gamma, "L_bar": L_bar}) + try: + target_gamma = float(self.sdr_gamma_type_var.get()) if test_type == "sdr_movie" else 2.2 + except Exception: + target_gamma = 2.2 + self.plot_gamma(L_bar, results_with_gamma, target_gamma, test_type) + + if "eotf" in selected_items and test_type == "hdr_movie": + pattern_params = self.config.default_pattern_gray.get("pattern_params", None) + results_with_eotf, L_bar = self.calculate_gamma( + gray_results, len(gray_results) - 1, pattern_params + ) + self.results.set_test_item_result("eotf", {"eotf": results_with_eotf, "L_bar": L_bar}) + self.plot_eotf(L_bar, results_with_eotf, test_type) + + # CCT 模拟 + if "cct" in selected_items: + cct_values = pq_algorithm.calculate_cct_from_results(gray_results) + self.results.set_test_item_result("cct", {"cct_values": cct_values}) + self.plot_cct(test_type) + + # 对比度模拟 + if "contrast" in selected_items: + luminance_values = [row[2] for row in gray_results] + max_luminance = max(luminance_values) + min_luminance = max(min(luminance_values), 0.001) + contrast_ratio = max_luminance / min_luminance + contrast_data = { + "max_luminance": max_luminance, + "min_luminance": min_luminance, + "contrast_ratio": contrast_ratio, + "luminance_values": luminance_values, + } + self.results.set_test_item_result("contrast", contrast_data) + self.plot_contrast(contrast_data, test_type) + + # 色准模拟 + if "accuracy" in selected_items: + color_names = self.config.get_accuracy_color_names() + standards = self.get_accuracy_color_standards(test_type) + + color_patches = [] + measured_data = [] + delta_e_values = [] + + for idx, name in enumerate(color_names): + sx, sy = standards.get(name, (0.3127, 0.3290)) + + # 前 20 个色块偏差更小,后 9 个稍大,方便 UI 看出差异 + noise_sigma = 0.0008 if idx < 20 else 0.0018 + mx = sx + float(rng.normal(0.0, noise_sigma)) + my = sy + float(rng.normal(0.0, noise_sigma)) + lv = max(5.0, 40.0 + idx * 2.3 + float(rng.normal(0.0, 4.0))) + + row = _xyY_to_xyz_row(mx, my, lv) + measured_data.append(row) + color_patches.append(name) + + delta_e = self.calculate_delta_e_2000(mx, my, lv, sx, sy) + delta_e_values.append(delta_e) + + avg_delta_e = float(np.mean(delta_e_values)) if delta_e_values else 0.0 + max_delta_e = float(np.max(delta_e_values)) if delta_e_values else 0.0 + min_delta_e = float(np.min(delta_e_values)) if delta_e_values else 0.0 + + excellent_count = sum(1 for d in delta_e_values if d < 3) + good_count = sum(1 for d in delta_e_values if 3 <= d < 5) + poor_count = sum(1 for d in delta_e_values if d >= 5) + + delta_e_gray = delta_e_values[0:5] + delta_e_colorchecker = delta_e_values[5:23] + delta_e_saturated = delta_e_values[23:29] + + try: + target_gamma = float(self.sdr_gamma_type_var.get()) if test_type == "sdr_movie" else 2.2 + except Exception: + target_gamma = 2.2 + + accuracy_data = { + "color_patches": color_patches, + "delta_e_values": delta_e_values, + "color_measurements": measured_data, + "avg_delta_e": avg_delta_e, + "max_delta_e": max_delta_e, + "min_delta_e": min_delta_e, + "excellent_count": excellent_count, + "good_count": good_count, + "poor_count": poor_count, + "avg_delta_e_gray": float(np.mean(delta_e_gray)) if delta_e_gray else 0.0, + "avg_delta_e_colorchecker": float(np.mean(delta_e_colorchecker)) if delta_e_colorchecker else 0.0, + "avg_delta_e_saturated": float(np.mean(delta_e_saturated)) if delta_e_saturated else 0.0, + "target_gamma": target_gamma, + } + + self.results.add_intermediate_data("accuracy", "measured", measured_data) + self.results.set_test_item_result("accuracy", accuracy_data) + self.plot_accuracy(accuracy_data, test_type) + + self.save_btn.config(state=tk.NORMAL) + self.status_var.set("模拟测试完成") + self.log_gui.log("模拟测试完成,结果已显示到 UI", level="success") + self.log_gui.log("=" * 60, level="separator") + messagebox.showinfo("完成", "模拟测试已完成(无需 UCD/CA)") + + except Exception as e: + self.status_var.set("模拟测试失败") + self.log_gui.log(f"模拟测试失败: {str(e)}", level="error") + import traceback + self.log_gui.log(traceback.format_exc(), level="error") + messagebox.showerror("错误", f"模拟测试失败: {str(e)}") + + def on_test_completed(self: "PQAutomationApp"): """测试完成后的UI更新""" self.testing = False @@ -1310,6 +1530,7 @@ class TestRunnerMixin: test_cct = test_cct test_contrast = test_contrast test_color_accuracy = test_color_accuracy + run_simulation_test = run_simulation_test on_test_completed = on_test_completed on_custom_template_test_completed = on_custom_template_test_completed get_current_test_result = get_current_test_result diff --git a/app/views/chart_frame.py b/app/views/chart_frame.py index 3da4c97..6af3e21 100644 --- a/app/views/chart_frame.py +++ b/app/views/chart_frame.py @@ -408,20 +408,27 @@ def init_contrast_chart(self: "PQAutomationApp"): def init_accuracy_chart(self: "PQAutomationApp"): """初始化色准图表 - 固定大小,居中显示""" container = ttk.Frame(self.accuracy_chart_frame) - container.pack(expand=True) + container.pack(expand=True, fill=tk.BOTH) + container.grid_rowconfigure(0, weight=1) + container.grid_rowconfigure(1, weight=0, minsize=220) + container.grid_columnconfigure(0, weight=1) + + # 上方图表优先显示;下方表格固定高度,避免挤占图表区域。 + plot_container = ttk.Frame(container) + plot_container.grid(row=0, column=0, sticky="nsew") + + table_container = ttk.LabelFrame(container, text="色准明细") + table_container.grid(row=1, column=0, sticky="ew", padx=4, pady=(2, 4)) self.accuracy_fig = plt.Figure( figsize=(10, 6), dpi=100, tight_layout=False, ) - self.accuracy_canvas = FigureCanvasTkAgg(self.accuracy_fig, master=container) + self.accuracy_canvas = FigureCanvasTkAgg(self.accuracy_fig, master=plot_container) canvas_widget = self.accuracy_canvas.get_tk_widget() - canvas_widget.pack() - - canvas_widget.config(width=1000, height=600) - canvas_widget.pack_propagate(False) + canvas_widget.pack(fill=tk.BOTH, expand=True) self.accuracy_ax = self.accuracy_fig.add_subplot(111) self.accuracy_ax.set_xlim(0, 1) @@ -439,6 +446,134 @@ def init_accuracy_chart(self: "PQAutomationApp"): ) self.accuracy_canvas.draw() + self._init_accuracy_result_table(table_container) + + +def _init_accuracy_result_table(self: "PQAutomationApp", parent): + """创建色准结果表格(支持横向/纵向滚动)。""" + table_wrap = ttk.Frame(parent) + table_wrap.pack(fill=tk.BOTH, expand=True, padx=2, pady=2) + + self.accuracy_result_table = ttk.Treeview( + table_wrap, + show="headings", + height=7, + ) + + x_scroll = ttk.Scrollbar( + table_wrap, + orient=tk.HORIZONTAL, + command=self.accuracy_result_table.xview, + ) + y_scroll = ttk.Scrollbar( + table_wrap, + orient=tk.VERTICAL, + command=self.accuracy_result_table.yview, + ) + self.accuracy_result_table.configure( + xscrollcommand=x_scroll.set, + yscrollcommand=y_scroll.set, + ) + + self.accuracy_result_table.grid(row=0, column=0, sticky="nsew") + y_scroll.grid(row=0, column=1, sticky="ns") + x_scroll.grid(row=1, column=0, sticky="ew") + table_wrap.grid_rowconfigure(0, weight=1) + table_wrap.grid_columnconfigure(0, weight=1) + + self.clear_accuracy_result_table() + + +def clear_accuracy_result_table(self: "PQAutomationApp"): + """清空色准表格并恢复占位内容。""" + if not hasattr(self, "accuracy_result_table"): + return + + tree = self.accuracy_result_table + tree.delete(*tree.get_children()) + + columns = ("metric", "value") + tree.configure(columns=columns) + tree.heading("metric", text="项目") + tree.heading("value", text="值") + tree.column("metric", width=150, anchor="w", stretch=False) + tree.column("value", width=300, anchor="w", stretch=True) + + tree.insert("", tk.END, values=("状态", "等待色准测试数据...")) + + +def update_accuracy_result_table(self: "PQAutomationApp", accuracy_data, standards): + """更新色准表格:按指标行 + 色块列展示,可横向滚动浏览。""" + if not hasattr(self, "accuracy_result_table"): + return + + tree = self.accuracy_result_table + tree.delete(*tree.get_children()) + + color_patches = accuracy_data.get("color_patches", []) or [] + measurements = accuracy_data.get("color_measurements", []) or [] + delta_e_values = accuracy_data.get("delta_e_values", []) or [] + delta_e_itp_values = accuracy_data.get("delta_e_itp_values", []) or [] + + if not color_patches: + self.clear_accuracy_result_table() + return + + columns = ["metric"] + [f"c{i}" for i in range(len(color_patches))] + tree.configure(columns=columns) + + tree.heading("metric", text="项目") + tree.column("metric", width=140, anchor="w", stretch=False) + + for i, name in enumerate(color_patches): + col = f"c{i}" + tree.heading(col, text=name) + tree.column(col, width=96, anchor="center", stretch=False) + + def fmt(v, digits=4): + if isinstance(v, (int, float)): + return f"{v:.{digits}f}" + return "N/A" + + row_x = ["x: CIE31"] + row_y = ["y: CIE31"] + row_Y = ["Y"] + row_tx = ["Target x:CIE31"] + row_ty = ["Target y:CIE31"] + row_de2000 = ["ΔE 2000"] + + include_itp = bool(delta_e_itp_values) + row_deitp = ["ΔE ITP"] if include_itp else None + + for i, name in enumerate(color_patches): + m = measurements[i] if i < len(measurements) else None + sx, sy = standards.get(name, (None, None)) + + if m is not None and len(m) >= 3: + row_x.append(fmt(m[0], 4)) + row_y.append(fmt(m[1], 4)) + row_Y.append(fmt(m[2], 4)) + else: + row_x.append("N/A") + row_y.append("N/A") + row_Y.append("N/A") + + row_tx.append(fmt(sx, 4)) + row_ty.append(fmt(sy, 4)) + + de = delta_e_values[i] if i < len(delta_e_values) else None + row_de2000.append(fmt(de, 4)) + + if include_itp and row_deitp is not None: + ditp = delta_e_itp_values[i] if i < len(delta_e_itp_values) else None + row_deitp.append(fmt(ditp, 4)) + + rows = [row_x, row_y, row_Y, row_tx, row_ty, row_de2000] + if include_itp and row_deitp is not None: + rows.append(row_deitp) + + for row in rows: + tree.insert("", tk.END, values=row) def clear_chart(self: "PQAutomationApp"): """清空所有图表""" @@ -735,6 +870,9 @@ def clear_chart(self: "PQAutomationApp"): self.accuracy_canvas.draw() + # 清空色准明细表格 + self.clear_accuracy_result_table() + def update_chart_tabs_state(self: "PQAutomationApp"): """根据测试项目复选框状态动态增删图表 Tab(保持规范顺序)。 @@ -888,6 +1026,9 @@ class ChartFrameMixin: init_cct_chart = init_cct_chart init_contrast_chart = init_contrast_chart init_accuracy_chart = init_accuracy_chart + _init_accuracy_result_table = _init_accuracy_result_table + clear_accuracy_result_table = clear_accuracy_result_table + update_accuracy_result_table = update_accuracy_result_table clear_chart = clear_chart update_chart_tabs_state = update_chart_tabs_state create_result_chart_frame = create_result_chart_frame diff --git a/app/views/panels/cct_panel.py b/app/views/panels/cct_panel.py index 48c974f..4f89bb5 100644 --- a/app/views/panels/cct_panel.py +++ b/app/views/panels/cct_panel.py @@ -634,16 +634,6 @@ def recalculate_gamut(self: "PQAutomationApp"): # 10. 重新绘制色域图 self.plot_gamut(rgb_data, coverage_xy, test_type) - self.log_gui.log("色域图已重新绘制", level="success") - self.log_gui.log("=" * 50, level="separator") - - messagebox.showinfo( - "成功", - f"色域图已根据新参考标准 {reference_standard} 重新绘制!\n\n" - f"XY 覆盖率: {coverage_xy:.1f}%\n" - f"UV 覆盖率: {coverage_uv:.1f}%", - ) - except Exception as e: self.log_gui.log(f"重新计算失败: {str(e)}", level="error") self.log_gui.log(traceback.format_exc(), level="error") diff --git a/app/views/panels/main_layout.py b/app/views/panels/main_layout.py index 062bd20..c628c00 100644 --- a/app/views/panels/main_layout.py +++ b/app/views/panels/main_layout.py @@ -590,6 +590,14 @@ def create_operation_frame(self: "PQAutomationApp"): ) self.start_btn.pack(side=tk.LEFT, padx=5) + self.simulate_btn = ttk.Button( + operation_frame, + text="模拟测试", + command=self.run_simulation_test, + style="warning.TButton", + ) + self.simulate_btn.pack(side=tk.LEFT, padx=5) + self.stop_btn = ttk.Button( operation_frame, text="停止测试", diff --git a/settings/pq_config.json b/settings/pq_config.json index 4fe447f..50f46c1 100644 --- a/settings/pq_config.json +++ b/settings/pq_config.json @@ -24,9 +24,10 @@ "sdr_movie": { "name": "SDR Movie测试", "test_items": [ - "gamut" + "gamut", + "accuracy" ], - "timing": "DMT 1600x 1200 @ 60Hz", + "timing": "OVT 1280x 720 @ 120Hz", "color_format": "RGB", "bpc": 8, "colorimetry": "sRGB", @@ -36,7 +37,7 @@ "y_ideal": 0.329, "y_tolerance": 0.003 }, - "gamut_reference": "BT.2020" + "gamut_reference": "DCI-P3" }, "hdr_movie": { "name": "HDR Movie测试",