添加手动设置窗口亮度、曲线图生成
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"current_test_type": "screen_module",
|
"current_test_type": "local_dimming",
|
||||||
"test_types": {
|
"test_types": {
|
||||||
"screen_module": {
|
"screen_module": {
|
||||||
"name": "屏模组性能测试",
|
"name": "屏模组性能测试",
|
||||||
|
|||||||
Reference in New Issue
Block a user