GIT-test/camera_control.py
2026-02-21 23:42:50 +08:00

368 lines
12 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- 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()