添加手动设置窗口亮度、曲线图生成

This commit is contained in:
xinzhu.yin
2026-06-08 11:39:54 +08:00
parent e4890d9d8d
commit 9ad9cf9aa0
3 changed files with 160 additions and 14 deletions

View File

@@ -8,6 +8,7 @@ import atexit
import csv import csv
import datetime import datetime
import os import os
import re
import shutil import shutil
import sys import sys
import threading import threading
@@ -15,6 +16,7 @@ import time
import tkinter as tk import tkinter as tk
from tkinter import filedialog, messagebox from tkinter import filedialog, messagebox
import matplotlib.pyplot as plt
import numpy as np import numpy as np
from PIL import Image from PIL import Image
@@ -398,15 +400,42 @@ def send_ld_window(self: "PQAutomationApp", percentage):
messagebox.showwarning("警告", "请先连接 UCD323 设备") messagebox.showwarning("警告", "请先连接 UCD323 设备")
return return
self.log_gui.log(f"🔆 发送 {percentage}% 窗口...", level="info") try:
_set_current_ld_pattern(self, "峰值亮度", f"{percentage}%窗口", percentage) luminance_percent = float(
self.ld_window_luminance_var.get()
if hasattr(self, "ld_window_luminance_var")
else 100
)
if luminance_percent < 1 or luminance_percent > 100:
raise ValueError("亮度范围应为 1-100")
except Exception as e:
messagebox.showwarning("参数错误", f"窗口亮度参数无效: {e}")
return
window_level = int(round(luminance_percent / 100.0 * 255.0))
self.log_gui.log(
f"🔆 发送 {percentage}% 窗口(亮度{luminance_percent:.0f}%...",
level="info",
)
_set_current_ld_pattern(
self,
"峰值亮度",
f"{percentage}%窗口({luminance_percent:.0f}%亮度)",
percentage,
)
def send(): def send():
if not _apply_ld_ucd_params(self): if not _apply_ld_ucd_params(self):
return return
width, height = self.signal_service.current_resolution() width, height = self.signal_service.current_resolution()
try: try:
image_path = _ensure_window_image(width, height, percentage) image_path = _ensure_window_image(
width,
height,
percentage,
window_level,
)
except Exception as e: except Exception as e:
self._dispatch_ui(self.log_gui.log, f"图像生成失败: {e}") self._dispatch_ui(self.log_gui.log, f"图像生成失败: {e}")
return return
@@ -416,14 +445,27 @@ def send_ld_window(self: "PQAutomationApp", percentage):
except Exception: except Exception:
ok = False ok = False
msg = ( msg = (
f"{percentage}% 窗口已发送" if ok f"{percentage}% 窗口({luminance_percent:.0f}%亮度)已发送" if ok
else f"{percentage}% 窗口发送失败" else f"{percentage}% 窗口({luminance_percent:.0f}%亮度)发送失败"
) )
self._dispatch_ui(self.log_gui.log, msg) self._dispatch_ui(self.log_gui.log, msg)
threading.Thread(target=send, daemon=True).start() threading.Thread(target=send, daemon=True).start()
def send_ld_manual_window(self: "PQAutomationApp"):
"""按手动输入的窗口百分比和亮度直接发送窗口图案。"""
try:
percentage = int(float(self.ld_window_percentage_var.get()))
if percentage < 1 or percentage > 100:
raise ValueError("窗口范围应为 1-100")
except Exception as e:
messagebox.showwarning("参数错误", f"窗口百分比无效: {e}")
return
self.send_ld_window(percentage)
def send_ld_checkerboard(self: "PQAutomationApp", center_white): def send_ld_checkerboard(self: "PQAutomationApp", center_white):
"""发送棋盘格图案(手动模式)。""" """发送棋盘格图案(手动模式)。"""
if not self.signal_service.is_connected: if not self.signal_service.is_connected:
@@ -797,6 +839,63 @@ def save_local_dimming_results(self: "PQAutomationApp"):
messagebox.showerror("错误", f"保存失败: {str(e)}") messagebox.showerror("错误", f"保存失败: {str(e)}")
def plot_ld_instant_peak_curve(self: "PQAutomationApp"):
"""从测试表格提取瞬时峰值曲线点并生成亮度-时间曲线图。"""
curve_points = []
pattern = re.compile(r"t\s*=\s*([0-9]+(?:\.[0-9]+)?)s")
for item in self.ld_tree.get_children():
values = self.ld_tree.item(item, "values")
if len(values) < 3:
continue
test_item = str(values[0])
pattern_text = str(values[1])
lv_text = str(values[2])
if test_item != "瞬时峰值曲线":
continue
match = pattern.search(pattern_text)
if not match:
continue
try:
t_sec = float(match.group(1))
lv = float(lv_text)
except Exception:
continue
curve_points.append((t_sec, lv))
if not curve_points:
messagebox.showinfo("提示", "没有可绘制的瞬时峰值曲线数据")
return
curve_points.sort(key=lambda x: x[0])
t_data = [p[0] for p in curve_points]
lv_data = [p[1] for p in curve_points]
fig = plt.figure(figsize=(8.6, 4.6))
ax = fig.add_subplot(111)
ax.plot(t_data, lv_data, "-o", linewidth=1.8, markersize=3.5, color="#2a9d8f")
ax.set_title("Instant Peak Luminance Curve")
ax.set_xlabel("Time (s)")
ax.set_ylabel("Luminance (cd/m²)")
ax.grid(True, linestyle="--", alpha=0.35)
peak_idx = int(np.argmax(lv_data))
ax.scatter([t_data[peak_idx]], [lv_data[peak_idx]], color="#e76f51", zorder=3)
ax.annotate(
f"Peak: {lv_data[peak_idx]:.2f} cd/m² @ {t_data[peak_idx]:.2f}s",
(t_data[peak_idx], lv_data[peak_idx]),
xytext=(8, 10),
textcoords="offset points",
fontsize=9,
color="#333333",
)
fig.tight_layout()
plt.show(block=False)
self.log_gui.log("已生成瞬时峰值曲线图", level="success")
class LocalDimmingMixin: class LocalDimmingMixin:
"""由 tools/refactor_to_mixins.py 自动生成。 """由 tools/refactor_to_mixins.py 自动生成。
把本模块的自由函数挂到 PQAutomationApp 上,便于 F12 跳转与类型推断。 把本模块的自由函数挂到 PQAutomationApp 上,便于 F12 跳转与类型推断。
@@ -805,6 +904,7 @@ class LocalDimmingMixin:
update_ld_results = update_ld_results update_ld_results = update_ld_results
stop_local_dimming_test = stop_local_dimming_test stop_local_dimming_test = stop_local_dimming_test
send_ld_window = send_ld_window send_ld_window = send_ld_window
send_ld_manual_window = send_ld_manual_window
send_ld_checkerboard = send_ld_checkerboard send_ld_checkerboard = send_ld_checkerboard
send_ld_black_pattern = send_ld_black_pattern send_ld_black_pattern = send_ld_black_pattern
send_ld_instant_peak = send_ld_instant_peak send_ld_instant_peak = send_ld_instant_peak
@@ -813,3 +913,4 @@ class LocalDimmingMixin:
measure_ld_luminance = measure_ld_luminance measure_ld_luminance = measure_ld_luminance
clear_ld_records = clear_ld_records clear_ld_records = clear_ld_records
save_local_dimming_results = save_local_dimming_results save_local_dimming_results = save_local_dimming_results
plot_ld_instant_peak_curve = plot_ld_instant_peak_curve

View File

@@ -60,6 +60,50 @@ def create_local_dimming_panel(self: "PQAutomationApp"):
style="SuccessState.TLabel", style="SuccessState.TLabel",
).pack(pady=(0, 8)) ).pack(pady=(0, 8))
window_level_row = ttk.Frame(window_frame)
window_level_row.pack(fill=tk.X, pady=(0, 8))
ttk.Label(window_level_row, text="窗口(%):").pack(side=tk.LEFT)
self.ld_window_percentage_var = tk.StringVar(value="10")
ld_window_percentage_entry = ttk.Entry(
window_level_row,
textvariable=self.ld_window_percentage_var,
width=8,
)
ld_window_percentage_entry.pack(side=tk.LEFT, padx=(6, 10))
ttk.Label(window_level_row, text="窗口亮度(%):").pack(side=tk.LEFT)
self.ld_window_luminance_var = tk.StringVar(value="100")
ld_window_luminance_entry = ttk.Entry(
window_level_row,
textvariable=self.ld_window_luminance_var,
width=8,
)
ld_window_luminance_entry.pack(side=tk.LEFT, padx=(6, 10))
ttk.Button(
window_level_row,
text="生成窗口",
command=self.send_ld_manual_window,
bootstyle="success-outline",
width=12,
).pack(side=tk.LEFT)
ld_window_percentage_entry.bind(
"<Return>",
lambda _event: self.send_ld_manual_window(),
)
ld_window_luminance_entry.bind(
"<Return>",
lambda _event: self.send_ld_manual_window(),
)
ttk.Label(
window_level_row,
text="输入后可直接点生成或回车",
style="InfoState.TLabel",
).pack(side=tk.LEFT, padx=(8, 0))
# 第一行1%, 2%, 5%, 10%, 18% # 第一行1%, 2%, 5%, 10%, 18%
row1 = ttk.Frame(window_frame) row1 = ttk.Frame(window_frame)
row1.pack(fill=tk.X, pady=(0, 5)) row1.pack(fill=tk.X, pady=(0, 5))
@@ -118,14 +162,6 @@ def create_local_dimming_panel(self: "PQAutomationApp"):
width=14, width=14,
).pack(side=tk.LEFT, padx=3) ).pack(side=tk.LEFT, padx=3)
ttk.Button(
pattern_row,
text="瞬时峰值",
command=self.send_ld_instant_peak,
bootstyle="warning",
width=12,
).pack(side=tk.LEFT, padx=3)
ttk.Button( ttk.Button(
pattern_row, pattern_row,
text="全黑画面", text="全黑画面",
@@ -285,6 +321,15 @@ def create_local_dimming_panel(self: "PQAutomationApp"):
) )
self.ld_save_btn.pack(side=tk.LEFT) self.ld_save_btn.pack(side=tk.LEFT)
self.ld_plot_btn = ttk.Button(
bottom_frame,
text="📈 生成峰值曲线",
command=self.plot_ld_instant_peak_curve,
bootstyle="warning-outline",
width=14,
)
self.ld_plot_btn.pack(side=tk.LEFT, padx=(5, 0))
# 默认隐藏 # 默认隐藏
self.local_dimming_visible = False self.local_dimming_visible = False

View File

@@ -1,5 +1,5 @@
{ {
"current_test_type": "screen_module", "current_test_type": "local_dimming",
"test_types": { "test_types": {
"screen_module": { "screen_module": {
"name": "屏模组性能测试", "name": "屏模组性能测试",