368 lines
12 KiB
Python
368 lines
12 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
相机控制界面
|
||
|
||
本模块提供了一个基于Tkinter的相机控制界面,用于调节相机的曝光时间、增益等参数。
|
||
"""
|
||
|
||
import tkinter as tk
|
||
from tkinter import ttk
|
||
import threading
|
||
import time
|
||
from camera import Camera
|
||
|
||
class CameraControlPanel:
|
||
"""
|
||
相机控制面板类
|
||
"""
|
||
|
||
def __init__(self, root, camera):
|
||
"""
|
||
初始化相机控制面板
|
||
|
||
Args:
|
||
root: 父窗口
|
||
camera: 相机实例
|
||
"""
|
||
self.root = root
|
||
self.camera = camera
|
||
self.root.title("相机控制面板")
|
||
self.root.geometry("500x400")
|
||
self.root.resizable(True, True)
|
||
|
||
# 创建主框架
|
||
self.main_frame = ttk.Frame(self.root, padding="10")
|
||
self.main_frame.pack(fill=tk.BOTH, expand=True)
|
||
|
||
# 相机状态
|
||
self.status_var = tk.StringVar(value="未初始化")
|
||
|
||
# 曝光时间变量
|
||
self.exp_var = tk.DoubleVar(value=5000.0)
|
||
self.exp_var.trace("w", self.on_exp_change)
|
||
|
||
# 增益变量
|
||
self.gain_var = tk.DoubleVar(value=0.0)
|
||
self.gain_var.trace("w", self.on_gain_change)
|
||
|
||
# 帧率变量
|
||
self.fps_var = tk.DoubleVar(value=30.0)
|
||
self.fps_var.trace("w", self.on_fps_change)
|
||
|
||
# 状态标签
|
||
self.create_status_section()
|
||
|
||
# 相机控制
|
||
self.create_control_section()
|
||
|
||
# 参数调节
|
||
self.create_param_section()
|
||
|
||
# 日志区域
|
||
self.create_log_section()
|
||
|
||
# 初始化相机
|
||
self.init_camera()
|
||
|
||
def create_status_section(self):
|
||
"""
|
||
创建状态显示区域
|
||
"""
|
||
status_frame = ttk.LabelFrame(self.main_frame, text="相机状态", padding="10")
|
||
status_frame.pack(fill=tk.X, pady=5)
|
||
|
||
status_label = ttk.Label(status_frame, textvariable=self.status_var, font=("Arial", 12, "bold"))
|
||
status_label.pack(anchor=tk.W)
|
||
|
||
def create_control_section(self):
|
||
"""
|
||
创建相机控制区域
|
||
"""
|
||
control_frame = ttk.LabelFrame(self.main_frame, text="相机控制", padding="10")
|
||
control_frame.pack(fill=tk.X, pady=5)
|
||
|
||
# 按钮容器
|
||
button_frame = ttk.Frame(control_frame)
|
||
button_frame.pack(fill=tk.X)
|
||
|
||
# 初始化按钮
|
||
self.init_button = ttk.Button(button_frame, text="初始化相机", command=self.init_camera)
|
||
self.init_button.pack(side=tk.LEFT, padx=5)
|
||
|
||
# 打开按钮
|
||
self.open_button = ttk.Button(button_frame, text="打开相机", command=self.open_camera, state=tk.DISABLED)
|
||
self.open_button.pack(side=tk.LEFT, padx=5)
|
||
|
||
# 开始取流按钮
|
||
self.start_button = ttk.Button(button_frame, text="开始取流", command=self.start_grabbing, state=tk.DISABLED)
|
||
self.start_button.pack(side=tk.LEFT, padx=5)
|
||
|
||
# 停止取流按钮
|
||
self.stop_button = ttk.Button(button_frame, text="停止取流", command=self.stop_grabbing, state=tk.DISABLED)
|
||
self.stop_button.pack(side=tk.LEFT, padx=5)
|
||
|
||
# 关闭按钮
|
||
self.close_button = ttk.Button(button_frame, text="关闭相机", command=self.close_camera, state=tk.DISABLED)
|
||
self.close_button.pack(side=tk.LEFT, padx=5)
|
||
|
||
def create_param_section(self):
|
||
"""
|
||
创建参数调节区域
|
||
"""
|
||
param_frame = ttk.LabelFrame(self.main_frame, text="参数调节", padding="10")
|
||
param_frame.pack(fill=tk.X, pady=5)
|
||
|
||
# 曝光时间
|
||
exp_frame = ttk.Frame(param_frame)
|
||
exp_frame.pack(fill=tk.X, pady=5)
|
||
|
||
exp_label = ttk.Label(exp_frame, text="曝光时间 (μs):")
|
||
exp_label.pack(side=tk.LEFT, padx=5)
|
||
|
||
exp_scale = ttk.Scale(exp_frame, from_=100.0, to=50000.0, orient=tk.HORIZONTAL, variable=self.exp_var, length=200)
|
||
exp_scale.pack(side=tk.LEFT, padx=5, expand=True, fill=tk.X)
|
||
|
||
exp_entry = ttk.Entry(exp_frame, textvariable=self.exp_var, width=10)
|
||
exp_entry.pack(side=tk.LEFT, padx=5)
|
||
|
||
# 增益
|
||
gain_frame = ttk.Frame(param_frame)
|
||
gain_frame.pack(fill=tk.X, pady=5)
|
||
|
||
gain_label = ttk.Label(gain_frame, text="增益 (dB):")
|
||
gain_label.pack(side=tk.LEFT, padx=5)
|
||
|
||
gain_scale = ttk.Scale(gain_frame, from_=0.0, to=48.0, orient=tk.HORIZONTAL, variable=self.gain_var, length=200)
|
||
gain_scale.pack(side=tk.LEFT, padx=5, expand=True, fill=tk.X)
|
||
|
||
gain_entry = ttk.Entry(gain_frame, textvariable=self.gain_var, width=10)
|
||
gain_entry.pack(side=tk.LEFT, padx=5)
|
||
|
||
# 帧率
|
||
fps_frame = ttk.Frame(param_frame)
|
||
fps_frame.pack(fill=tk.X, pady=5)
|
||
|
||
fps_label = ttk.Label(fps_frame, text="帧率 (fps):")
|
||
fps_label.pack(side=tk.LEFT, padx=5)
|
||
|
||
fps_scale = ttk.Scale(fps_frame, from_=1.0, to=60.0, orient=tk.HORIZONTAL, variable=self.fps_var, length=200)
|
||
fps_scale.pack(side=tk.LEFT, padx=5, expand=True, fill=tk.X)
|
||
|
||
fps_entry = ttk.Entry(fps_frame, textvariable=self.fps_var, width=10)
|
||
fps_entry.pack(side=tk.LEFT, padx=5)
|
||
|
||
def create_log_section(self):
|
||
"""
|
||
创建日志显示区域
|
||
"""
|
||
log_frame = ttk.LabelFrame(self.main_frame, text="日志", padding="10")
|
||
log_frame.pack(fill=tk.BOTH, expand=True, pady=5)
|
||
|
||
# 创建文本框
|
||
self.log_text = tk.Text(log_frame, height=10, wrap=tk.WORD)
|
||
self.log_text.pack(fill=tk.BOTH, expand=True)
|
||
|
||
# 添加滚动条
|
||
scrollbar = ttk.Scrollbar(self.log_text, command=self.log_text.yview)
|
||
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
||
self.log_text.config(yscrollcommand=scrollbar.set)
|
||
|
||
def log(self, message):
|
||
"""
|
||
添加日志信息
|
||
|
||
Args:
|
||
message: 日志消息
|
||
"""
|
||
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
||
log_message = f"[{timestamp}] {message}\n"
|
||
self.log_text.insert(tk.END, log_message)
|
||
self.log_text.see(tk.END)
|
||
|
||
def init_camera(self):
|
||
"""
|
||
初始化相机
|
||
"""
|
||
try:
|
||
self.log("正在初始化相机...")
|
||
self.status_var.set("初始化中")
|
||
|
||
# 枚举设备
|
||
device_count = self.camera.enum_devices()
|
||
if device_count == 0:
|
||
self.log("未找到相机设备")
|
||
self.status_var.set("未找到设备")
|
||
return
|
||
|
||
self.log(f"找到 {device_count} 台相机设备")
|
||
self.status_var.set("就绪")
|
||
|
||
# 启用打开按钮
|
||
self.open_button.config(state=tk.NORMAL)
|
||
self.log("相机初始化成功")
|
||
|
||
except Exception as e:
|
||
self.log(f"初始化失败: {e}")
|
||
self.status_var.set("初始化失败")
|
||
|
||
def open_camera(self):
|
||
"""
|
||
打开相机
|
||
"""
|
||
try:
|
||
self.log("正在打开相机...")
|
||
self.status_var.set("打开中")
|
||
|
||
# 打开设备(默认使用索引0)
|
||
ret = self.camera.open_device(0)
|
||
if ret != 0:
|
||
self.log(f"打开相机失败,错误码: {ret}")
|
||
self.status_var.set("打开失败")
|
||
return
|
||
|
||
self.log("相机打开成功")
|
||
self.status_var.set("已打开")
|
||
|
||
# 更新参数显示
|
||
self.exp_var.set(self.camera.current_exp)
|
||
self.gain_var.set(self.camera.current_gain)
|
||
self.fps_var.set(self.camera.current_fps)
|
||
|
||
# 启用控制按钮
|
||
self.start_button.config(state=tk.NORMAL)
|
||
self.close_button.config(state=tk.NORMAL)
|
||
self.open_button.config(state=tk.DISABLED)
|
||
|
||
except Exception as e:
|
||
self.log(f"打开相机失败: {e}")
|
||
self.status_var.set("打开失败")
|
||
|
||
def start_grabbing(self):
|
||
"""
|
||
开始取流
|
||
"""
|
||
try:
|
||
self.log("正在开始取流...")
|
||
self.status_var.set("取流中")
|
||
|
||
ret = self.camera.start_grabbing()
|
||
if ret != 0:
|
||
self.log(f"开始取流失败,错误码: {ret}")
|
||
self.status_var.set("取流失败")
|
||
return
|
||
|
||
self.log("开始取流成功")
|
||
self.status_var.set("正在取流")
|
||
|
||
# 更新按钮状态
|
||
self.start_button.config(state=tk.DISABLED)
|
||
self.stop_button.config(state=tk.NORMAL)
|
||
|
||
except Exception as e:
|
||
self.log(f"开始取流失败: {e}")
|
||
self.status_var.set("取流失败")
|
||
|
||
def stop_grabbing(self):
|
||
"""
|
||
停止取流
|
||
"""
|
||
try:
|
||
self.log("正在停止取流...")
|
||
|
||
ret = self.camera.stop_grabbing()
|
||
if ret != 0:
|
||
self.log(f"停止取流失败,错误码: {ret}")
|
||
return
|
||
|
||
self.log("停止取流成功")
|
||
self.status_var.set("已打开")
|
||
|
||
# 更新按钮状态
|
||
self.stop_button.config(state=tk.DISABLED)
|
||
self.start_button.config(state=tk.NORMAL)
|
||
|
||
except Exception as e:
|
||
self.log(f"停止取流失败: {e}")
|
||
|
||
def close_camera(self):
|
||
"""
|
||
关闭相机
|
||
"""
|
||
try:
|
||
self.log("正在关闭相机...")
|
||
|
||
self.camera.close_device()
|
||
|
||
self.log("相机关闭成功")
|
||
self.status_var.set("已关闭")
|
||
|
||
# 更新按钮状态
|
||
self.close_button.config(state=tk.DISABLED)
|
||
self.stop_button.config(state=tk.DISABLED)
|
||
self.start_button.config(state=tk.DISABLED)
|
||
self.open_button.config(state=tk.NORMAL)
|
||
|
||
except Exception as e:
|
||
self.log(f"关闭相机失败: {e}")
|
||
|
||
def on_exp_change(self, *args):
|
||
"""
|
||
曝光时间变化回调
|
||
"""
|
||
if self.camera.is_open:
|
||
try:
|
||
exp_value = self.exp_var.get()
|
||
ret = self.camera.set_exposure_time(exp_value)
|
||
if ret == 0:
|
||
self.log(f"曝光时间设置为: {exp_value} μs")
|
||
except Exception as e:
|
||
self.log(f"设置曝光时间失败: {e}")
|
||
|
||
def on_gain_change(self, *args):
|
||
"""
|
||
增益变化回调
|
||
"""
|
||
if self.camera.is_open:
|
||
try:
|
||
gain_value = self.gain_var.get()
|
||
ret = self.camera.set_gain(gain_value)
|
||
if ret == 0:
|
||
self.log(f"增益设置为: {gain_value} dB")
|
||
except Exception as e:
|
||
self.log(f"设置增益失败: {e}")
|
||
|
||
def on_fps_change(self, *args):
|
||
"""
|
||
帧率变化回调
|
||
"""
|
||
if self.camera.is_open:
|
||
try:
|
||
fps_value = self.fps_var.get()
|
||
ret = self.camera.set_frame_rate(fps_value)
|
||
if ret == 0:
|
||
self.log(f"帧率设置为: {fps_value} fps")
|
||
except Exception as e:
|
||
self.log(f"设置帧率失败: {e}")
|
||
|
||
if __name__ == "__main__":
|
||
"""
|
||
测试相机控制面板
|
||
"""
|
||
import tkinter as tk
|
||
|
||
# 创建根窗口
|
||
root = tk.Tk()
|
||
|
||
# 创建相机实例
|
||
camera = Camera()
|
||
|
||
# 创建控制面板
|
||
app = CameraControlPanel(root, camera)
|
||
|
||
# 运行主循环
|
||
try:
|
||
root.mainloop()
|
||
finally:
|
||
# 确保关闭相机
|
||
camera.close_device()
|