Python 写的 《监控视频存储计算器》

ops/2024/12/26 19:16:33/

代码: 

python">import tkinter as tk
from tkinter import ttk
import math
from tkinter.font import Fontclass StorageCalculator:def __init__(self, root):self.root = rootself.root.title("监控视频存储计算器")self.root.geometry("600x800")self.root.configure(bg='#f0f0f0')# 设置主题和样式self.style = ttk.Style()self.style.theme_use('clam')  # 使用clam主题作为基础# 定义颜色方案self.colors = {'primary': '#2196F3',    # 主色调'secondary': '#64B5F6',   # 次要色调'bg': '#f0f0f0',         # 背景色'text': '#212121',       # 文字颜色'success': '#4CAF50'     # 成功色}# 设置自定义字体self.title_font = Font(family="微软雅黑", size=12, weight="bold")self.normal_font = Font(family="微软雅黑", size=10)self.result_font = Font(family="微软雅黑", size=11, weight="bold")# 配置样式self.style.configure('Title.TLabel', font=self.title_font, background=self.colors['bg'],foreground=self.colors['primary'])self.style.configure('Normal.TLabel', font=self.normal_font,background=self.colors['bg'])self.style.configure('Custom.TButton',font=self.normal_font,background=self.colors['primary'],padding=(20, 10))self.style.configure('Tab.TNotebook',background=self.colors['bg'])self.style.configure('Result.TLabelframe',background=self.colors['bg'])# 创建主标题self.create_header()# 创建notebookself.notebook = ttk.Notebook(root, style='Tab.TNotebook')self.notebook.pack(fill='both', expand=True, padx=20, pady=(0, 20))# 创建计算页面self.create_forward_page()self.create_reverse_page()# 创建页脚self.create_footer()def create_header(self):"""创建头部标题区域"""header_frame = ttk.Frame(self.root)header_frame.pack(fill='x', padx=20, pady=20)title = ttk.Label(header_frame, text="监控视频存储计算器",style='Title.TLabel')title.pack()subtitle = ttk.Label(header_frame,text="专业的存储空间评估工具",style='Normal.TLabel')subtitle.pack()def create_forward_page(self):"""创建正向计算页面"""self.forward_frame = ttk.Frame(self.notebook, padding="20")self.notebook.add(self.forward_frame, text=" 计算存储需求 ")# 创建输入区域input_frame = ttk.LabelFrame(self.forward_frame, text="参数输入",padding="15")input_frame.pack(fill='x', padx=10, pady=5)# 添加输入控件self.create_input_field(input_frame, "摄像头数量:", 0, self.normal_font)self.cameras = self.entryself.create_input_field(input_frame, "每天录像时间(小时):", 1, self.normal_font)self.hours = self.entryself.hours.insert(0, "24")  # 默认24小时self.create_input_field(input_frame, "需要保存的天数:", 2, self.normal_font)self.days = self.entry# 摄像头类型选择ttk.Label(input_frame, text="摄像头类型:", font=self.normal_font).grid(row=3, column=0, sticky=tk.W, pady=5)self.camera_type = ttk.Combobox(input_frame, width=25,font=self.normal_font)self.camera_type['values'] = ['200万像素', '300万像素', '400万像素', '500万像素']self.camera_type.current(0)self.camera_type.grid(row=3, column=1, sticky=tk.W, pady=5)# 编码方式选择ttk.Label(input_frame, text="编码方式:", font=self.normal_font).grid(row=4, column=0, sticky=tk.W, pady=5)self.encoding = ttk.Combobox(input_frame, width=25,font=self.normal_font)self.encoding['values'] = ['H.264', 'H.265']self.encoding.current(1)  # 默认H.265self.encoding.grid(row=4, column=1, sticky=tk.W, pady=5)# 计算按钮btn_frame = ttk.Frame(self.forward_frame)btn_frame.pack(fill='x', pady=20)calc_btn = ttk.Button(btn_frame, text="计算存储需求",style='Custom.TButton',command=self.calculate_forward)calc_btn.pack(expand=True)# 结果显示区域self.forward_result_frame = ttk.LabelFrame(self.forward_frame,text="计算结果",padding="15",style='Result.TLabelframe')self.forward_result_frame.pack(fill='x', padx=10, pady=5)self.storage_label = ttk.Label(self.forward_result_frame,text="",font=self.result_font)self.storage_label.pack(anchor=tk.W)self.recommendation_label = ttk.Label(self.forward_result_frame,text="",font=self.result_font)self.recommendation_label.pack(anchor=tk.W)def create_reverse_page(self):"""创建反向计算页面"""self.reverse_frame = ttk.Frame(self.notebook, padding="20")self.notebook.add(self.reverse_frame, text=" 计算存储时间 ")# 创建输入区域input_frame = ttk.LabelFrame(self.reverse_frame,text="参数输入",padding="15")input_frame.pack(fill='x', padx=10, pady=5)# 添加输入控件self.create_input_field(input_frame, "硬盘容量(TB):", 0, self.normal_font)self.storage_size = self.entryself.create_input_field(input_frame, "摄像头数量:", 1, self.normal_font)self.rev_cameras = self.entryself.create_input_field(input_frame, "每天录像时间(小时):", 2, self.normal_font)self.rev_hours = self.entry# 摄像头类型选择ttk.Label(input_frame, text="摄像头类型:",font=self.normal_font).grid(row=3, column=0,sticky=tk.W, pady=5)self.rev_camera_type = ttk.Combobox(input_frame, width=25,font=self.normal_font)self.rev_camera_type['values'] = ['200万像素', '300万像素', '400万像素', '500万像素']self.rev_camera_type.current(0)self.rev_camera_type.grid(row=3, column=1, sticky=tk.W, pady=5)# 编码方式选择ttk.Label(input_frame, text="编码方式:",font=self.normal_font).grid(row=4, column=0,sticky=tk.W, pady=5)self.rev_encoding = ttk.Combobox(input_frame, width=25,font=self.normal_font)self.rev_encoding['values'] = ['H.264', 'H.265']self.rev_encoding.current(1)  # 默认H.265self.rev_encoding.grid(row=4, column=1, sticky=tk.W, pady=5)# 计算按钮btn_frame = ttk.Frame(self.reverse_frame)btn_frame.pack(fill='x', pady=20)calc_btn = ttk.Button(btn_frame,text="计算可存储天数",style='Custom.TButton',command=self.calculate_reverse)calc_btn.pack(expand=True)# 结果显示区域self.reverse_result_frame = ttk.LabelFrame(self.reverse_frame,text="计算结果",padding="15",style='Result.TLabelframe')self.reverse_result_frame.pack(fill='x', padx=10, pady=5)self.days_label = ttk.Label(self.reverse_result_frame,text="",font=self.result_font)self.days_label.pack(anchor=tk.W)def create_footer(self):"""创建页脚"""footer = ttk.Label(self.root,text="© 2024 专业视频监控存储解决方案",style='Normal.TLabel')footer.pack(pady=10)def create_input_field(self, parent, label_text, row, font):"""创建统一的输入字段"""ttk.Label(parent, text=label_text,font=font).grid(row=row, column=0,sticky=tk.W, pady=5)self.entry = ttk.Entry(parent, width=25,font=font)self.entry.grid(row=row, column=1, sticky=tk.W, pady=5)return self.entrydef calculate_storage(self, cameras, hours_per_day, days, camera_type, encoding):"""计算存储需求camera_type: 摄像头类型 (200万/300万/400万/500万)encoding: 编码方式 (H.264/H.265)"""# 每天存储空间(GB)daily_storage = {'200万像素': {'H.264': 42.19,  # 4096kbps'H.265': 21.09   # 2048kbps},'300万像素': {'H.264': 42.19,  # 4096kbps'H.265': 21.09   # 2048kbps},'400万像素': {'H.264': 42.19,  # 4096kbps'H.265': 21.09   # 2048kbps},'500万像素': {'H.264': 63.28,  # 6144kbps'H.265': 31.64   # 3072kbps}}# 计算单个摄像头每天实际存储量daily_per_camera = daily_storage[camera_type][encoding] * (hours_per_day / 24)# 计算总存储量total_storage_gb = daily_per_camera * cameras * days# 转换为TB并返回return round(total_storage_gb / 1024, 2)def calculate_days(self, storage_tb, cameras, hours_per_day, camera_type, encoding):"""计算可存储天数"""daily_storage = {'200万像素': {'H.264': 42.19,'H.265': 21.09},'300万像素': {'H.264': 42.19,'H.265': 21.09},'400万像素': {'H.264': 42.19,'H.265': 21.09},'500万像素': {'H.264': 63.28,'H.265': 31.64}}# 计算单个摄像头每天实际存储量daily_per_camera = daily_storage[camera_type][encoding] * (hours_per_day / 24)# 计算可存储天数total_gb = storage_tb * 1024days = total_gb / (daily_per_camera * cameras)return round(days, 1)def calculate_forward(self):try:cameras = int(self.cameras.get())hours = float(self.hours.get())days = int(self.days.get())camera_type = self.camera_type.get()encoding = self.encoding.get()if cameras <= 0 or hours <= 0 or days <= 0:raise ValueError("请输入大于0的数值")# 获取单个摄像头每天的存储量daily_storage = {'200万像素': {'H.264': 42.19,'H.265': 21.09},'300万像素': {'H.264': 42.19,'H.265': 21.09},'400万像素': {'H.264': 42.19,'H.265': 21.09},'500万像素': {'H.264': 63.28,'H.265': 31.64}}daily_per_camera = daily_storage[camera_type][encoding] * (hours / 24)daily_total = daily_per_camera * camerasstorage = self.calculate_storage(cameras, hours, days, camera_type, encoding)self.storage_label.config(text=f"每天存储空间: {round(daily_total, 2)} GB/天\n"f"总存储容量: {storage} TB",foreground=self.colors['success'])self.recommendation_label.config(text=f"建议配置: {math.ceil(storage)} TB 硬盘\n"f"(基于{camera_type}摄像头,{encoding}编码)\n"f"单个摄像头: {round(daily_per_camera, 2)} GB/天",foreground=self.colors['success'])except ValueError as e:self.storage_label.config(text="输入错误!",foreground='red')self.recommendation_label.config(text="请检查输入的数值是否正确",foreground='red')def calculate_reverse(self):try:storage = float(self.storage_size.get())cameras = int(self.rev_cameras.get())hours = float(self.rev_hours.get())camera_type = self.rev_camera_type.get()encoding = self.rev_encoding.get()if storage <= 0 or cameras <= 0 or hours <= 0:raise ValueError("请输入大于0的数值")# 获取单个摄像头每天的存储量daily_storage = {'200万像素': {'H.264': 42.19,'H.265': 21.09},'300万像素': {'H.264': 42.19,'H.265': 21.09},'400万像素': {'H.264': 42.19,'H.265': 21.09},'500万像素': {'H.264': 63.28,'H.265': 31.64}}daily_per_camera = daily_storage[camera_type][encoding] * (hours / 24)daily_total = daily_per_camera * camerasdays = self.calculate_days(storage, cameras, hours, camera_type, encoding)self.days_label.config(text=f"每天存储空间: {round(daily_total, 2)} GB/天\n"f"单个摄像头: {round(daily_per_camera, 2)} GB/天\n"f"可存储天数: {days} 天\n"f"约等于 {round(days/30, 1)} 个月 或 {round(days/365, 1)} 年\n"f"(基于{camera_type}摄像头,{encoding}编码)",foreground=self.colors['success'])except ValueError as e:self.days_label.config(text="输入错误!\n请检查输入的数值是否正确",foreground='red')def main():root = tk.Tk()app = StorageCalculator(root)root.mainloop()if __name__ == "__main__":main()


http://www.ppmy.cn/ops/144638.html

相关文章

【WRF教程第3.6期】预处理系统 WPS 详解:以4.5版本为例

预处理系统 WPS 详解&#xff1a;以4.5版本为例 Geogrid/Metgrid 插值选项详解1. 插值方法的工作机制2. 插值方法的详细说明2.1 四点双线性插值&#xff08;four_pt&#xff09;2.2 十六点重叠抛物线插值&#xff08;sixteen_pt&#xff09;2.3 简单四点平均插值&#xff08;av…

【CSS】优化动画性能

最核心要开启gpu加速。 建议使用requestAnimationFrame&#xff0c;如果用js修改元素的位置&#xff0c;推荐使用这个API。 定时器时间不准确&#xff0c;requestAnimationFrame 始终在当前帧的最后执行。 利用css3 translate进行元素移动 在 CSS3 中&#xff0c;可以使用 tr…

opencv中的各种滤波器简介

在 OpenCV 中&#xff0c;滤波器是图像处理中的重要工具&#xff0c;用于对图像进行平滑、去噪、边缘检测等操作。以下是几种常见滤波器的简单介绍。 1. 均值滤波 (Mean Filter) 功能&#xff1a; 对图像进行平滑处理&#xff0c;减少噪声。 应用场景&#xff1a; 去除图像…

docker 容器的基本使用

docker 容器 一、docker是什么&#xff1f; 软件的打包技术&#xff0c;就是将算乱的多个文件打包为一个整体&#xff0c;打包技术在没有docker容器之前&#xff0c;一直是有这种需求的&#xff0c;比如上节课我把我安装的虚拟机给你们打包了&#xff0c;前面的这种打包方式是…

【Where语法全解密】.NET开源ORM框架 SqlSugar 系列

文章目录 前言一、普通表达式查询 Where二、根据SQL查询 where三、动态查询四、动态拼表达式查询 &#xff0c;拼拉姆达五、条件拼接查询六、链式条件查询七、根据Class查询&#xff0c;根据实查询八、根据Class中主键查询九、根据字典查询十、查询函数十一、Where中有子查询十…

component-后端返回图片(数据)前端进行复制到剪切板

1.前言 ‌Base64编码‌&#xff1a;将图片转换为Base64编码的字符串&#xff0c;然后通过HTTP协议传输到前端。前端接收到Base64字符串后&#xff0c;可以通过JavaScript将其解码并显示为图片。这种方式适合小图片&#xff0c;如logo或验证码&#xff0c;因为Base64编码后的字符…

【生成模型之三】ControlNet Latent Diffusion Models论文详解

论文&#xff1a;《Adding Conditional Control to Text-to-Image Diffusion Models》 我们提出了ControlNet&#xff0c;这是一种神经网络架构&#xff0c;可以将空间条件控制添加到大型预训练的文本到图像扩散模型中。ControlNet 冻结了生产就绪的大型扩散模型&#xff0c;并…

IPC协议获取签名信息

一&#xff1a;IPC协议获取签名信息详解 目录 什么是IPC协议&#xff1f;签名信息概述IPC协议中签名信息获取的流程相关知识点 数字签名原理常见签名算法数据完整性与认证签名的生成与验证IPC中的安全传输 应用场景总结 什么是IPC协议&#xff1f; IPC&#xff08;Inter-Pro…