活动介绍

plt.imshow(img_arr)

时间: 2025-04-29 21:56:15 浏览: 50
### 使用 Matplotlib 的 `imshow` 函数显示图像数组 为了使用 Python 中的 Matplotlib 库显示图像数组,可以采用如下方式: 定义所需的库之后,创建或加载图像数组。对于给定的例子,假设有一个名为 `img_arr` 的 NumPy 数组表示要显示的图像。 ```python import matplotlib.pyplot as plt import numpy as np # 假设 img_arr 是已经存在的图像数组 # 对于此处演示目的,创建一个简单的彩色图像作为示例 img_arr = np.random.rand(100, 100, 3) # 创建一个随机颜色的100x100像素图像 ``` 接着,可以通过调用 `plt.imshow()` 来展示该图像,并设置合适的参数以获得期望的效果[^1]。 ```python plt.figure(figsize=(8, 6)) plt.axis('off') # 关闭坐标轴 plt.imshow(img_arr) plt.show() ``` 如果图像数据是以灰度形式存在,则可能希望指定色彩映射(colormap),比如 `'gray'` 或者 `'Greys'`,这取决于个人偏好以及具体应用需求[^2]。 ```python image_array_gray = np.random.rand(100, 100) # 创建一个单通道的灰度图像 plt.figure(figsize=(8, 6)) plt.axis('off') plt.imshow(image_array_gray, cmap='gray', interpolation='nearest') plt.colorbar() # 可选:添加颜色条帮助理解数值范围 plt.show() ``` 当遇到 PyCharm 环境下无法正常工作的情况时,确保已正确配置后台图形界面或者尝试引入额外的支持模块如 `pylab` 来辅助渲染过程[^3]。 此外,在某些情况下调整插值方法 (`interpolation`) 和其他可视化选项可以帮助改善最终呈现的质量和外观效果[^4]。 最后值得注意的是,虽然上述代码片段展示了基本操作流程,但在实际项目开发过程中还需要考虑更多细节因素,例如性能优化、异常处理等。
阅读全文

相关推荐

import time import cv2 import tkinter as tk from tkinter import filedialog, ttk, messagebox from PIL import Image, ImageTk import numpy as np from sklearn.metrics import confusion_matrix, precision_recall_curve, average_precision_score import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg import pandas as pd import subprocess import os import random from threading import Thread # 用于训练时不阻塞界面 class ObjectDetectionApp: def __init__(self): self.window = tk.Tk() self.window.title("YOLOv4训练&验证系统") self.window.geometry("1600x1000") # 模式变量(训练/验证/原评估) self.mode = tk.StringVar(value="validation") self.train_running = False # 训练状态标志 # 模型配置(可自定义) self.base_cfg = "yolov4.cfg" # 基础配置文件 self.custom_cfg = "yolov4-custom.cfg" # 训练用自定义配置 self.weights_path = "yolov4.weights" # 默认权重/训练后权重 self.classes_file = "coco.names" self.classes = self.load_classes() self.COLORS = np.random.uniform(0, 255, size=(len(self.classes), 3)) self.voc_root = None # 新增:VOC数据集根路径 # 训练参数 self.train_params = { "epochs": 100, "batch": 8, "subdivisions": 4, "learning_rate": 0.001, "data_file": "custom.data", "names_file": self.classes_file } # 摄像头初始化 self.cap = None self.image_flipped = True # 评估相关变量(验证阶段使用) self.predicted_labels = [] self.ground_truths = [] self.performance_data = {} # 创建界面 self.create_widgets() self.window.mainloop() def create_widgets(self): # -------------------- 顶部模式栏 -------------------- mode_frame = tk.Frame(self.window, padx=10, pady=5) mode_frame.pack(fill=tk.X) tk.Radiobutton(mode_frame, text="模型训练", variable=self.mode, value="training", command=self.switch_mode).pack(side=tk.LEFT, padx=10) tk.Radiobutton(mode_frame, text="实时验证", variable=self.mode, value="validation", command=self.switch_mode).pack(side=tk.LEFT, padx=10) # -------------------- 训练模块控件 -------------------- self.train_frame = tk.Frame(self.window, padx=10, pady=5) # VOC数据集选择按钮 self.select_voc_btn = tk.Button(self.train_frame, text="选择VOC数据集", command=self.select_voc_dataset) self.select_voc_btn.pack(side=tk.LEFT, padx=10) # 训练参数输入 param_frame = tk.Frame(self.train_frame) tk.Label(param_frame, text="迭代次数:").grid(row=0, column=0, padx=5) self.epochs_entry = ttk.Entry(param_frame, width=8) self.epochs_entry.grid(row=0, column=1, padx=5) self.epochs_entry.insert(0, "100") tk.Label(param_frame, text="批次大小:").grid(row=1, column=0, padx=5) self.batch_entry = ttk.Entry(param_frame, width=8) self.batch_entry.grid(row=1, column=1, padx=5) self.batch_entry.insert(0, "8") param_frame.pack(side=tk.LEFT, padx=10) # 数据集加载按钮 self.load_train_btn = tk.Button(self.train_frame, text="加载训练集", command=self.load_train_dataset) self.load_train_btn.pack(side=tk.LEFT, padx=10) self.load_val_btn = tk.Button(self.train_frame, text="加载验证集", command=self.load_val_dataset) self.load_val_btn.pack(side=tk.LEFT, padx=10) # 开始训练按钮(正确顺序:先定义,再布局) self.start_train_btn = tk.Button(self.train_frame, text="开始训练", command=self.start_training_thread) self.start_train_btn.pack(side=tk.LEFT, padx=10) # -------------------- 主显示区域 -------------------- self.main_frame = tk.Frame(self.window) self.main_frame.pack(fill=tk.BOTH, expand=True) # 视频/图像显示区 self.photo_label = tk.Label(self.main_frame, width=1000, height=600) self.photo_label.pack(side=tk.LEFT, padx=10, pady=10) # 右侧信息区 self.right_frame = tk.Frame(self.main_frame, width=400) self.right_frame.pack(side=tk.RIGHT, padx=10, pady=10, fill=tk.Y) # 日志文本框 self.log_text = tk.Text(self.right_frame, width=40, height=15) self.log_text.pack(pady=5, fill=tk.X) self.log_text.insert(tk.END, "系统日志:\n") # 性能报告区 self.report_canvas = None self.report_frame = tk.Frame(self.right_frame) self.report_frame.pack(pady=5, fill=tk.BOTH, expand=True) # 初始显示验证模式 self.switch_mode() def select_voc_dataset(self): """选择VOC数据集根目录并执行划分""" self.voc_root = filedialog.askdirectory(title="选择VOC数据集根目录(如VOCdevkit/VOC2007)") if not self.voc_root: return # 检查所选目录下是否存在JPEGImages和Annotations目录 jpeg_dir = os.path.join(self.voc_root, "JPEGImages") ann_dir = os.path.join(self.voc_root, "Annotations") if not (os.path.isdir(jpeg_dir) and os.path.isdir(ann_dir)): messagebox.showerror("错误", "所选目录不是正确的VOC数据集根目录(缺少JPEGImages或Annotations目录)") return try: # 执行VOC数据集划分(75:25) self.split_voc_dataset(self.voc_root) self.log_text.insert(tk.END, "数据集划分完成!\n") # 自动设置训练/验证集路径到参数中 self.train_params["train_images"] = os.path.join(self.voc_root, "ImageSets/Main/train.txt") self.train_params["val_images"] = os.path.join(self.voc_root, "ImageSets/Main/val.txt") self.log_text.insert(tk.END, f"训练集路径:{self.train_params['train_images']}\n") self.log_text.insert(tk.END, f"验证集路径:{self.train_params['val_images']}\n") except Exception as e: messagebox.showerror("错误", f"数据集划分失败:{str(e)}") self.log_text.insert(tk.END, f"划分错误:{str(e)}\n") def split_voc_dataset(self, voc_root, train_ratio=0.75): """VOC数据集划分核心逻辑(集成到应用中)""" img_dir = os.path.join(voc_root, "JPEGImages") ann_dir = os.path.join(voc_root, "Annotations") sets_dir = os.path.join(voc_root, "ImageSets", "Main") os.makedirs(sets_dir, exist_ok=True) img_files = [f for f in os.listdir(img_dir) if f.lower().endswith((".jpg", ".jpeg", ".png"))] valid_ids = [] for img_file in img_files: img_id = os.path.splitext(img_file)[0] ann_path = os.path.join(ann_dir, f"{img_id}.xml") if os.path.isfile(ann_path): valid_ids.append(img_file) # 保存带扩展名的图像文件名 if not valid_ids: messagebox.showerror("错误", "未找到任何有效标注文件,确保JPEGImages和Annotations目录中的文件一一对应(除扩展名外文件名相同)") return random.shuffle(valid_ids) total = len(valid_ids) train_count = int(total * train_ratio) train_ids = valid_ids[:train_count] val_ids = valid_ids[train_count:] train_txt = os.path.join(sets_dir, "train.txt") val_txt = os.path.join(sets_dir, "val.txt") # 写入完整路径(如:D:/pycharm/pythonProject/VOCdevkit/VOC2007/JPEGImages/1.jpg) with open(train_txt, "w") as f: for img_file in train_ids: img_full_path = os.path.join(voc_root, "JPEGImages", img_file) f.write(img_full_path + '\n') with open(val_txt, "w") as f: for img_file in val_ids: img_full_path = os.path.join(voc_root, "JPEGImages", img_file) f.write(img_full_path + '\n') self.log_text.insert(tk.END, f"总样本数: {total},训练集: {len(train_ids)},验证集: {len(val_ids)}\n") def switch_mode(self): """模式切换逻辑""" current_mode = self.mode.get() # 关闭摄像头 if self.cap: self.cap.release() self.cap = None self.photo_label.config(image=None) # 清空界面 self.log_text.delete(1.0, tk.END) self.log_text.insert(tk.END, "系统日志:\n") if current_mode == "training": self.train_frame.pack(fill=tk.X, pady=5) self.report_frame.pack_forget() self.log_text.insert(tk.END, "切换到训练模式\n") else: # 验证模式 self.train_frame.pack_forget() self.report_frame.pack(fill=tk.BOTH, expand=True) self.cap = cv2.VideoCapture(0) # 打开摄像头 self.update_validation_frame() # 启动实时验证 self.log_text.insert(tk.END, "切换到实时验证模式\n") def load_train_dataset(self): """加载训练数据集(图像+标注)""" img_dir = filedialog.askdirectory(title="选择训练图像文件夹") label_dir = filedialog.askdirectory(title="选择训练标注文件夹") if img_dir and label_dir: self.train_params["train_images"] = img_dir self.train_params["train_labels"] = label_dir self.log_text.insert(tk.END, f"训练集加载完成:{img_dir}\n") def load_val_dataset(self): """加载验证数据集""" img_dir = filedialog.askdirectory(title="选择验证图像文件夹") label_dir = filedialog.askdirectory(title="选择验证标注文件夹") if img_dir and label_dir: self.train_params["val_images"] = img_dir self.train_params["val_labels"] = label_dir self.log_text.insert(tk.END, f"验证集加载完成:{img_dir}\n") def start_training_thread(self): """启动训练线程(防止界面阻塞)""" if self.train_running: messagebox.showwarning("提示", "训练已在进行中") return self.train_running = True Thread(target=self.start_training, daemon=True).start() def start_training(self): """执行训练流程(调用Darknet命令)""" try: # 生成训练配置文件 self.generate_training_config() # 训练命令(示例,根据实际Darknet路径调整) cmd = [ "darknet.exe", "detector", "train", self.train_params["data_file"], self.custom_cfg, "yolov4.conv.137", # 预训练权重 "-map", # 计算mAP "-gpus", "0", "-batch", self.batch_entry.get(), "-subdivisions", "4", "-epochs", self.epochs_entry.get() ] self.log_text.insert(tk.END, "开始训练...\n") process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) # 实时输出训练日志 for line in process.stdout: self.log_text.insert(tk.END, line) self.log_text.see(tk.END) # 自动滚动 process.wait() self.train_running = False self.log_text.insert(tk.END, "训练完成!最佳权重已保存\n") # 训练完成后生成性能报告 self.generate_training_report() except Exception as e: self.log_text.insert(tk.END, f"训练错误:{str(e)}\n") self.train_running = False def generate_training_config(self): """生成自定义训练配置文件""" with open(self.base_cfg, 'r') as f: cfg_lines = f.readlines() # 修改批次和subdivisions for i, line in enumerate(cfg_lines): if line.startswith("batch="): cfg_lines[i] = f"batch={self.batch_entry.get()}\n" if line.startswith("subdivisions="): cfg_lines[i] = "subdivisions=4\n" with open(self.custom_cfg, 'w') as f: f.writelines(cfg_lines) # 生成data文件,指定训练和验证的图像列表路径 data_content = f""" train = {os.path.join(self.voc_root, "ImageSets/Main/train.txt")} # 训练集图像列表 valid = {os.path.join(self.voc_root, "ImageSets/Main/val.txt")} # 验证集图像列表 names = {self.classes_file} backup = backup/ eval = coco """ with open(self.train_params["data_file"], 'w') as f: f.write(data_content) def generate_training_report(self): """生成训练性能报告""" # 假设从训练日志或结果文件中读取数据 # 这里模拟加载验证集结果 y_true = ["car", "person", "car", "bike"] y_pred = ["car", "person", "bike", "bike"] confidences = [0.92, 0.85, 0.78, 0.91] # 计算指标 cm = confusion_matrix(y_true, y_pred, labels=self.classes) precision, recall, _ = precision_recall_curve(y_true, confidences, pos_label="car") ap = average_precision_score([1 if x == "car" else 0 for x in y_true], confidences) # 绘制报告 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5)) # 混淆矩阵 ax1.imshow(cm, cmap=plt.cm.Blues) ax1.set_title("验证集混淆矩阵") ax1.set_xticks(range(len(self.classes))) ax1.set_xticklabels(self.classes, rotation=45) ax1.set_yticks(range(len(self.classes))) ax1.set_yticklabels(self.classes) # PR曲线 ax2.plot(recall, precision) ax2.set_title(f"PR曲线 (AP={ap:.2f})") ax2.set_xlabel("召回率") ax2.set_ylabel("精确率") # 在界面显示 if self.report_canvas: self.report_canvas.get_tk_widget().destroy() self.report_canvas = FigureCanvasTkAgg(fig, master=self.report_frame) self.report_canvas.draw() self.report_canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True) def update_validation_frame(self): """实时验证摄像头画面""" if not self.cap or not self.mode.get() == "validation": return ret, frame = self.cap.read() if ret: if self.image_flipped: frame = cv2.flip(frame, 1) # 使用训练后的权重进行检测 frame, results = self.detect_objects(frame) # 显示结果 frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) pil_img = Image.fromarray(frame_rgb) tk_img = ImageTk.PhotoImage(image=pil_img) self.photo_label.config(image=tk_img) self.photo_label.image = tk_img # 记录验证结果(可选) self.record_validation_results(results) self.window.after(30, self.update_validation_frame) def detect_objects(self, frame): """使用当前权重进行目标检测""" # 改为使用实例变量 self.net 存储网络 self.net = cv2.dnn.readNetFromDarknet( self.custom_cfg if self.mode.get() == "training" else self.base_cfg, self.weights_path ) # 使用 self.net 获取层信息 layer_names = self.net.getLayerNames() output_layers = [layer_names[i - 1] for i in self.net.getUnconnectedOutLayers()] # 图像预处理 height, width = frame.shape[:2] blob = cv2.dnn.blobFromImage(frame, 0.00392, (416, 416), (0, 0, 0), True, crop=False) # 前向传播(使用 self.net) self.net.setInput(blob) outs = self.net.forward(output_layers) # 注意:output_layers 已提前计算 # 后续代码保持不变... class_ids = [] confidences = [] boxes = [] for out in outs: for detection in out: scores = detection[5:] class_id = np.argmax(scores) confidence = scores[class_id] if confidence > 0.5: # 置信度阈值 center_x = int(detection[0] * width) center_y = int(detection[1] * height) w = int(detection[2] * width) h = int(detection[3] * height) # 计算边界框坐标 x = int(center_x - w / 2) y = int(center_y - h / 2) boxes.append([x, y, w, h]) confidences.append(float(confidence)) class_ids.append(class_id) # 非极大值抑制 indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4) results = [] for i in range(len(boxes)): if i in indexes: x, y, w, h = boxes[i] label = str(self.classes[class_ids[i]]) confidence = confidences[i] results.append((label, x, y, x + w, y + h, confidence)) # 绘制边界框和标签 color = self.COLORS[class_ids[i]] cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2) cv2.putText(frame, f"{label}: {confidence:.2f}", (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2) return frame, results def record_validation_results(self, results): """记录验证结果(预测标签和置信度)""" # 从results中提取预测的标签(假设results格式为:(label, x1, y1, x2, y2, confidence)) for result in results: predicted_label = result[0] # 标签 confidence = result[5] # 置信度 self.predicted_labels.append(predicted_label) # 如果有真实标签(例如从验证集标注文件读取),可添加类似逻辑: # self.ground_truths.append(ground_truth_label) def load_classes(self): with open(self.classes_file, "r") as f: return [line.strip() for line in f.readlines()] def close_app(self): if self.cap: self.cap.release() self.window.destroy() if __name__ == "__main__": app = ObjectDetectionApp() 代码检测

from time import time #记录时间 import logging #打印程序的运行日志 import matplotlib.pyplot as plt from sklearn.cross_validation import train_test_split #划分训练集和测试集 from sklearn.datasets import fetch_lfw_people #导入数据集(名人) from sklearn.grid_search import GridSearchCV #调试函数的参数 from sklearn.metrics import classification_report #显示分类报告,显示主要的分类指标,准确率,召回率以及F1得分 from sklearn.metrics import confusion_matrix #对真实类别和预测类别做出判断,用矩阵形式表示出来 from sklearn.decomposition import RandomizedPCA #pca降维 from sklearn.svm import SVC #svm的svc方程 from sklearn.cluster.tests.test_k_means import n_samples #训练集:sklearn自带的人脸图片数据集 lfw_people = fetch_lfw_people(min_faces_per_person=70,resize=0.4) n_samples,h,w = lfw_people.images.shape #实例数目、h、w x = lfw_people.data #所有的训练数据,1288张图片,每张图片1850个特征值 n_features = x.shape[1] #特征向量的维度1850 y =lfw_people.target #对应的人脸标记 target_names = lfw_people.target_names #需要识别的人名字 n_class = target_names.shape[0] #几个人需要识别 print("total dataset size:") print("n_samples: %d" % n_samples) print("n_features: %d" % n_features) print("n_class: %d" % n_class) x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25) n_components = 150 t0 = time() #随机将高维的特征向量降低为低维的,先建立模型 pca = RandomizedPCA(n_components=n_components,whiten=True).fit(x_train) print("done in %0.3fs" %(time() - t0)) #提取人脸的特征值 eigenfaces = pca.components_.reshape((n_components,h,w)) #将人脸特征转化为特征向量集 print('projecting the input data on the eigenfaces orthonomal basis') t0 = time() #进行数据模型降维,降成了150 x_train_pca = pca.transform(x_train) x_test_pca = pca.transform(x_test) print("done in %0.3fs" % (time() - t0)) print("fitting the classfier to the training set") t0 = time() #C 是对错误部分的惩罚;gamma 合成点 para_grid = {'C':[1e3,5e3,1e4,5e4,1e5],'gamma':[0.0001,0.0005,0.0001,0.005,0.01,0.1],} #rbf处理图像较好,C和gamma组合,穷举出最好的一个组合 使用GridSearchCV进行自由组合,最终确定合适的组合 clf = GridSearchCV(SVC(kernel='rbf'),para_grid) clf = clf.fit(x_train_pca,y_train) print("done in %0.3fs" % (time() - t0)) print("best estimator found by grid search:") print(clf.best_estimator_) #最好的模型的信息 print("predict the people's name on the test set") t0 = time() y_pred = clf.predict(x_test_pca) print("done in %0.3fs" % (time() - t0)) print(classification_report(y_test,y_pred,target_names=target_names)) print(confusion_matrix(y_test,y_pred,labels=range(n_class))) def plot_gallery(images,titles,h,w,n_row = 3,n_col = 4): plt.figure(figsize=(1.8*n_col,2.4*n_row)) plt.subplots_adjust(bottom = 0,left = .01,right = .99,top = .90,hspace = .35) for i in range(n_row * n_col): plt.subplot(n_row,n_col,i+1) plt.imshow(images[i].reshape((h,w)),cmap=plt.cm.gray) plt.title(titles[i],size = 12) plt.xticks() plt.yticks() def title(y_pred,y_test,target_names,i): pred_name = target_names[y_pred[i]].rsplit(' ',1)[-1] true_name = target_names[y_test[i]].rsplit(' ',1)[-1] return 'predicted : %s \nture: %s' % (pred_name,true_name) prediction_titles = [title(y_pred,y_test,target_names,i) for i in range(y_pred.shape[0])] plot_gallery(x_test,prediction_titles,h,w) eigenface_title = ["eigenface %d" % i for i in range(eigenfaces.shape[0])] plot_gallery(eigenfaces,eigenface_title,h,w) plt.show()其中在‘D:\cxdownload\ORL人脸识别数据集’中里面有40个子文件,每个子文件中有10张图,后缀为.pgm格式,这些图为存放的人脸测试数据

import pickle import numpy as np import matplotlib.pyplot as plt import seaborn as sns import pandas as pd import os from sklearn.metrics import confusion_matrix from sklearn.preprocessing import LabelEncoder from sklearn.model_selection import train_test_split import torch import torch.nn as nn from torch.utils.data import TensorDataset, DataLoader from tqdm import tqdm # 设置随机种子 torch.manual_seed(42) np.random.seed(42) def load_data(file_path): """安全加载并预处理数据""" with open(file_path, 'rb') as f: data = pickle.load(f, encoding='latin1') # 调试信息 print(f"成功加载数据,总样本数: {len(data)}") sample_shape = next(iter(data.values())).shape print(f"单个样本形状: {sample_shape} (格式: [时间步长, 通道数, 特征数])") # 统一处理所有样本为相同长度(取最小长度) min_length = min(arr.shape[0] for arr in data.values()) print(f"统一长度: {min_length} (取所有样本的最小长度)") # 提取I路信号并统一长度 X = np.array([arr[:min_length, 0, 0] for arr in data.values()], dtype=np.float32) X = X.reshape(-1, min_length, 1) # 形状: (样本数, 时间步长, 特征数) # 提取调制类型标签 modulations = [key[0] for key in data.keys()] label_encoder = LabelEncoder() y = label_encoder.fit_transform(modulations) print(f"调制类型及对应标签:\n{pd.Series(label_encoder.classes_).to_frame('标签')}") # 分割数据集 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42) # 归一化 mean, std = X_train.mean(), X_train.std() X_train = (X_train - mean) / (std + 1e-8) X_test = (X_test - mean) / (std + 1e-8) return X_train, y_train, X_test, y_test, label_encoder class SignalTransformer(nn.Module): """稳健的Transformer模型""" def __init__(self, input_dim=1, num_classes=11, d_model=128, nhead=8, num_layers=3, dropout=0.1): super().__init__() self.input_proj = nn.Linear(input_dim, d_model) self.pos_encoder = nn.Parameter(torch.zeros(1, 1000, d_model)) encoder_layer = nn.TransformerEncoderLayer( d_model=d_model, nhead=nhead, dim_feedforward=512, dropout=dropout, batch_first=True) self.transformer = nn.TransformerEncoder(encoder_layer, num_layers=num_layers) self.classifier = nn.Sequential( nn.LayerNorm(d_model), nn.Dropout(dropout), nn.Linear(d_model, num_classes) ) nn.init.xavier_uniform_(self.pos_encoder) def forward(self, x): x = self.input_proj(x) seq_len = x.size(1) x = x + self.pos_encoder[:, :seq_len, :] x = self.transformer(x).mean(dim=1) return self.classifier(x) def train_model(): # 设备配置 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") print(f"\n训练设备: {device}") # 加载数据 data_path = r"D:\Anaconda\envs\DL\Lib\site-packages\caffe2\python\data\train\2016.04C.multisnr.pkl" try: X_train, y_train, X_test, y_test, label_encoder = load_data(data_path) except Exception as e: print(f"数据加载失败: {str(e)}") return # 转换为PyTorch张量 train_data = TensorDataset( torch.from_numpy(X_train).float(), torch.from_numpy(y_train).long() ) test_data = TensorDataset( torch.from_numpy(X_test).float(), torch.from_numpy(y_test).long() ) # 数据加载器 (batch size改回32) train_loader = DataLoader(train_data, batch_size=32, shuffle=True) test_loader = DataLoader(test_data, batch_size=32) # 模型初始化 model = SignalTransformer(num_classes=len(label_encoder.classes_)).to(device) criterion = nn.CrossEntropyLoss() optimizer = torch.optim.AdamW(model.parameters(), lr=3e-4, weight_decay=1e-4) # 训练记录 history = { 'epoch': [], 'train_loss': [], 'val_loss': [], 'val_acc': [], 'best_epoch': 0, 'best_acc': 0 } # 训练循环(保持5轮不变) for epoch in range(5): model.train() train_loss = 0 # 使用with语句管理进度条 with tqdm(train_loader, desc=f'Epoch {epoch+1}/5') as progress_bar: for inputs, labels in progress_bar: inputs, labels = inputs.to(device), labels.to(device) optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() train_loss += loss.item() progress_bar.set_postfix({'loss': loss.item()}) # 验证 model.eval() val_loss, correct = 0, 0 all_preds, all_labels = [], [] # 验证阶段也添加进度条 with tqdm(test_loader, desc='验证中') as val_bar: with torch.no_grad(): for inputs, labels in val_bar: inputs, labels = inputs.to(device), labels.to(device) outputs = model(inputs) val_loss += criterion(outputs, labels).item() preds = outputs.argmax(dim=1) correct += (preds == labels).sum().item() all_preds.extend(preds.cpu().numpy()) all_labels.extend(labels.cpu().numpy()) val_bar.set_postfix({'val_loss': val_loss/len(val_bar)}) # 记录结果 val_acc = correct / len(test_data) history['epoch'].append(epoch+1) history['train_loss'].append(train_loss/len(train_loader)) history['val_loss'].append(val_loss/len(test_loader)) history['val_acc'].append(val_acc) if val_acc > history['best_acc']: history['best_acc'] = val_acc history['best_epoch'] = epoch+1 torch.save(model.state_dict(), 'best_model.pth') # 使用tqdm.write确保输出不干扰进度条 tqdm.write(f"Epoch {epoch+1}: 训练损失={history['train_loss'][-1]:.4f}, " f"验证损失={history['val_loss'][-1]:.4f}, " f"准确率={val_acc:.4f}") # 保存结果 save_results(history, all_labels, all_preds, label_encoder.classes_) print(f"\n最佳模型在Epoch {history['best_epoch']}, 准确率={history['best_acc']:.4f}") def save_results(history, true_labels, pred_labels, classes): """保存所有结果并显示可视化""" os.makedirs('results', exist_ok=True) # 创建两个独立图形 fig1, ax1 = plt.subplots(figsize=(12, 10)) fig2, (ax2, ax3) = plt.subplots(1, 2, figsize=(12, 5)) # 1. 混淆矩阵 cm = confusion_matrix(true_labels, pred_labels) sns.heatmap(cm, annot=True, fmt='d', xticklabels=classes, yticklabels=classes, ax=ax1) ax1.set_title("Confusion Matrix") fig1.savefig("results/confusion_matrix.png", bbox_inches='tight') # 2. 训练曲线 ax2.plot(history['epoch'], history['train_loss'], label='Train Loss') ax2.plot(history['epoch'], history['val_loss'], label='Validation Loss') ax2.set_xlabel('Epoch') ax2.set_ylabel('Loss') ax2.legend() ax3.plot(history['epoch'], history['val_acc'], label='Validation Accuracy', color='green') ax3.set_xlabel('Epoch') ax3.set_ylabel('Accuracy') ax3.legend() fig2.savefig("results/training_metrics.png", bbox_inches='tight') # 同时显示两个窗口 plt.show(block=False) # 不阻塞代码执行 plt.pause(0.1) # 短暂暂停确保窗口创建 # 3. 训练日志表格 df = pd.DataFrame({ 'Epoch': history['epoch'], 'Training Loss': history['train_loss'], 'Validation Loss': history['val_loss'], 'Accuracy': history['val_acc'] }) df.to_csv("results/training_log.csv", index=False) print("\n训练日志摘要:") print(df.round(4)) if __name__ == "__main__": train_model() 以上代码输出的时候,混淆矩阵弹窗和损失精度曲线图弹窗一闪即逝,我需要这两个弹窗能正常显示,请你修改后发我完整代码

from tkinter import * import tkinter as tk from tkinter import ttk, filedialog, Text from tkinter import Toplevel, Entry, messagebox from tkinter.filedialog import askdirectory,askopenfilename from PIL import Image, ImageTk import cv2 #import pytesseract import threading import pyautogui import os import numpy as np import pandas as pd #import random #import sched #(计划任务) #import schedule import winsound #电脑报警音 #import pyodbc import pymysql import mysql.connector from datetime import datetime import time import matplotlib.pyplot as plt from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg,NavigationToolbar2Tk) from matplotlib.font_manager import FontProperties class MainWindow: def __init__(self, master): #self.master = master #self.master.title("登录数据库") self.master = master self.master.title("登录数据库") print('系统登录-总界面') self.flag_conn = 0 label_topic_0 = tk.Label(self.master, text="电力设备热致故障温度预警系统", font=('楷体', 22)) label_topic_0.place(x=40, y=50) #label_topic_0.attributes("-alpha", 0.5) # 设置透明度为50% label_topic_1 = ttk.Label(self.master, text="登 录 数 据 库", font=('楷体', 22)) label_topic_1.place(x=140, y=100) label_server=tk.Label(self.master,text = "Server",width=8, height=2,font=('宋体', 14)) label_server.place(x=50, y=200) self.entry_item_01 = tk.Entry(self.master,width=30, bg="white",font=('宋体', 14)) self.entry_item_01.place(x=150 , y=210) default_text1 = 'localhost' self.entry_item_01.insert(0, default_text1) label_database=tk.Label(self.master,text = "Database",width=8, height=2,font=('宋体', 14)) label_database.place(x=50, y=250) self.entry_item_02 = tk.Entry(self.master,width=30, bg="white",font=('宋体', 14)) self.entry_item_02.place(x=150 , y=260) default_text2= 'pic_temp' self.entry_item_02.insert(0, default_text2) label_Username=tk.Label(self.master,text = "Username",width=8, height=2,font=('宋体', 14)) label_Username.place(x=50, y=300) self.entry_item_03 = tk.Entry(self.master,width=30, bg="white",font=('宋体', 14)) self.entry_item_03.place(x=150 , y=310) default_text3= 'root' self.entry_item_03.insert(0, default_text3) label_Password=tk.Label(self.master,text = "Password",width=8, height=2,font=('宋体', 14)) label_Password.place(x=50, y=350) self.entry_item_04 = tk.Entry(self.master,width=30, bg="white",font=('宋体', 14)) self.entry_item_04.place(x=150 , y=360) default_text4= '******' self.entry_item_04.insert(0, default_text4) self.radio_win = tk.StringVar() # 创建一个StringVar变量,用于存储选中的值 self.radio_win.set('1') #radio_var.set(None) # 创建第一个单选框 #radio_button1 = tk.Radiobutton(self.master, text="Windows认证",variable=self.radio_win, value="1",font=('宋体', 14)) #radio_button1.place(x=150, y=400) # 创建第二个单选框 #radio_button2 = tk.Radiobutton(self.master, text="Sql认证",variable=self.radio_win, value="2",font=('宋体', 14)) #radio_button2.place(x=300, y=400) label_status=tk.Label(self.master,text = "连接状态",width=8, height=2,font=('宋体', 14)) label_status.place(x=50, y=450) self.label_conn=tk.Label(self.master,text = "------",width=15, height=2,font=('宋体', 14)) self.label_conn.place(x=150, y=450) self.button_login_sql = tk.Button(self.master, text="连接", command=self.login_sql,width=10, height=2,font=('宋体', 14)) self.button_login_sql.place(x=50, y=550) self.button_login = tk.Button(self.master, text="登录", command=self.open_window_main,width=10, height=2,font=('宋体', 14)) self.button_login.place(x=200, y=550) self.button_close = tk.Button(self.master, text="退出", command=self.close,width=10, height=2,font=('宋体', 14)) self.button_close.place(x=350, y=550) def login_sql(self): # 数据库连接字符串 server = self.entry_item_01.get() database = self.entry_item_02.get() username1 = self.entry_item_03.get() password1 = self.entry_item_04.get() # 尝试连接数据库 try: conn=pymysql.connect(host=server, user=username1, password=password1, port=3306, db=database) print("数据库连接成功!") self.label_conn.configure(bg='lightgreen',fg='blue',text='数据库连接成功') self.flag_conn = 1 except Exception as e: print("Excel连接成功:", e) self.flag_conn = 1 self.label_conn.configure(bg='lightgreen',fg='blue',text='Excel连接成功') finally: if conn: # 确保在操作完成后关闭连接: conn.close() # 关闭连接 def open_window_main(self): if self.flag_conn == 1: self.master.iconify() # 最小化窗口 # 创建新窗口的实例 self.new_window_main = tk.Toplevel(self.master) # 传递新窗口作为参数给另一个窗口类 self.app_main = NewWindow_main(self.new_window_main) self.flag_conn = 0 else: print('连接错误') messagebox.showinfo("提示", "连接错误,请重新连接") def close(self): print('关闭窗口') #self.btn_open_window_sql.config(state=tk.NORMAL) #self.btn_open_window_video.config(state=tk.NORMAL) self.master.destroy() #root.deiconify() # 显示主窗口 class NewWindow_main: def __init__(self, master): self.window_main = master # setting the title self.window_main.title('电力设备热致故障温度预警系统') self.window_main.geometry("1300x700+150+150") print('系统登录-主界面') label_topic_0 = ttk.Label(self.window_main, text="电力设备热致故障温度预警系统", font=('楷体', 36)).place(x=310, y=200) #label_topic_1 = ttk.Label(self.window_main, text="一、图片数据采集", font=('楷体', 26)).place(x=410, y=400) label_topic_2 = ttk.Label(self.window_main, text=" 图片数据采集", font=('楷体', 26)).place(x=410, y=500) #self.btn_open_window_sql = tk.Button(self.window_main, text="进入",font=('宋体', 16), command=self.open_window_sql,width=10, height=2) #self.btn_open_window_sql.place(x=820, y=390) #self.btn_open_window_sql.config(state=tk.DISABLED) self.btn_open_window_video = tk.Button(self.window_main, text="进入", font=('宋体', 16) ,command=self.open_window_video,width=10, height=2) self.btn_open_window_video.place(x=820, y=490) #self.btn_open_window_video.config(state=tk.DISABLED) self.window_main.mainloop() def open_window_sql(self): # 创建新窗口的实例 self.new_window_sql = tk.Toplevel(self.window_main) # 传递新窗口作为参数给另一个窗口类 self.app_sql = NewWindow_sql(self.new_window_sql) def open_window_video(self): # 创建新窗口的实例 self.new_window_video = tk.Toplevel(self.window_main) # 传递新窗口作为参数给另一个窗口类 self.app_video = NewWindow_video(self.new_window_video) #self.window_main.mainloop() class NewWindow_video: def __init__(self, master): #self.master_video = master #self.master_video.title("主窗口") window_video = master # 在新窗口中添加一些组件 #tk.Label(self.master_video, text="这是一个新窗口_video").pack() window_video.title('电力设备热致故障温度预警系统') self.window_video = window_video print('系统登录-视频图像') global frame1,point_count global output,fig output = None fig = None frame1 = None point_count = 0 # dimensions of the main window window_video.geometry("1300x700+150+150") label_topic_1 = Label(window_video, text="实时温度检测与预警", font=('楷体', 26)).place(x=450, y=30) def open_camera(): print('进入_摄像头开启') global cap,video_path global flag_picture,flag_video cap = cv2.VideoCapture(0,cv2.CAP_DSHOW) # 激活摄像头 flag_video = 1 flag_picture = 0 if not cap.isOpened(): print("无法打开摄像头") return play_display() def close_camera(): print('进入_摄像头关闭') global cap,video_path if cap: cap.release() # 释放摄像头 #cap = None canvas1.delete("all") # 清空Canvas上的所有内容 time.sleep(1) cv2.destroyAllWindows() # 销毁窗口 if cap: cap.release() # 释放摄像头 #cap = None canvas1.delete("all") # 清空Canvas上的所有内容 time.sleep(1) cv2.destroyAllWindows() # 销毁窗口 def record_camera(): print('进入_保存视频') global cap,video_path #flag_save_camera = 1 def record_camera1(): fourcc = cv2.VideoWriter_fourcc(*'XVID') fps = 20.0 width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 获取当前时间 now = datetime.now() # 格式化时间 current_datetime = now.strftime("%Y%m%d_%H%M%S") print("当前日期和时间:", current_datetime) #file_name = 'pic_temp'+str(current_datetime)+'.avi' file_name = 'pic_temp_'+str(current_datetime)+'.mp4' out = cv2.VideoWriter(file_name, fourcc, fps, (width, height)) #out = cv2.VideoWriter('pic_temp.avi', fourcc, fps,(620,300)) # 捕获视频帧并保存 while cap.isOpened(): ret, frame = cap.read() if not ret: print("无法读取视频帧") break out.write(frame) cv2.imshow('Record_video', frame) if cv2.waitKey(10) & 0xFF == ord('q'): # 释放资源 #cap.release() #out.release() #cv2.destroyAllWindows() break #th_record_camera1 = threading.Thread(target=record_camera1,args=sstime) th_record_camera1 = threading.Thread(target=record_camera1) th_record_camera1.start() #threading.Thread(target=save_camera1).start() def select_file(): print('进入_选择文件') global cap,video_path global flag_picture,flag_video path_ = askopenfilename() path.set(path_) video_path = path_ print('video_path:',video_path) suffix = os.path.splitext(video_path)[1] #_, ext = os.path.splitext(video_path) #print('ext:',_, ext) ## 读取图像,解决imread不能读取中文路径的问题 def cv_imread(filePath): cv_img = cv2.imdecode(np.fromfile(filePath, dtype=np.uint8), -1) ## imdecode读取的是rgb,如果后续需要opencv处理的话,需要转换成bgr,转换后图片颜色会变化 ##cv_img=cv2.cvtColor(cv_img,cv2.COLOR_RGB2BGR) return cv_img if suffix in ['.jpg', '.png', '.jpeg']: # 根据需要添加其他图片格式 #cap = cv2.imread('87.jpg') cap = cv_imread(video_path) if cap is None: print("图像文件未找到或路径错误") flag_picture = 1 flag_video = 0 #cv2.imshow('Image', cap) #cv2.waitKey(0) #cv2.destroyAllWindows() else: flag_video = 1 flag_picture = 0 cap = cv2.VideoCapture(video_path) #cap = cv2.VideoCapture(0,cv2.CAP_DSHOW) # 显示画面 def play_display(): print('进入_显示画面') global flag_picture,flag_video,cap if flag_picture == 1 and flag_video == 0: play_pic() if flag_picture == 0 and flag_video==1: play_video1() def play_pic(): global cap #cap = cv2.imread(video_path) selected_option = radio_var.get() if selected_option == '3': # 定义矩形的左上角和右下角坐标 x11=entry_x41.get() y11=entry_y41.get() #x=int(x11)-130 # 存在偏差,进行校正 #y=int(y11)-260 x=int(x11) # 存在偏差,进行校正 y=int(y11) print('x_y:',x,'_',y) w=50 h=50 #x, y, w, h = 280, 240, 70,70 # 例如,从(100, 100)到(300, 300) # 在图片上绘制矩形框 #print('1111') cv2.rectangle(cap, (x, y), (x+w, y+h), (0, 255, 0), 2) # 颜色为绿色,线宽为2 # 将OpenCV的图像数据转换为PIL图像格式,因为Tkinter需要PIL图像 #img_pil = Image.fromarray(cap) # 使用Pillow将PIL图像转换为Tkinter兼容的PhotoImage格式 #img_tk = ImageTk.PhotoImage(img_pil) #img_tk = Image.fromarray(img_tk) #img_tk = img_tk.resize((width, height),Image.LANCZOS) # 调整视频帧大小以适应Canvas大小 #canvas1.create_image(0, 0, anchor=tk.NW, image=cap) # 保持对图像的引用,防止被垃圾回收 #canvas1.image = img_tk # 将视频帧显示在Canvas上 img = cv2.cvtColor(cap, cv2.COLOR_BGR2RGB) img = Image.fromarray(img) img = img.resize((width, height),Image.LANCZOS) # 调整视频帧大小以适应Canvas大小 # 将PIL图像转换为ImageTk图像 img = ImageTk.PhotoImage(image=img) canvas1.create_image(0, 0, anchor=tk.NW, image=img) canvas1.img = img # 显示图片 #cv2.imshow('Image with Rectangle', cap) #cv2.waitKey(0) #cv2.destroyAllWindows() # 如果需要保存图片 #cv2.imwrite('image_with_rectangle.jpg', cap) def play_video1(): global cap,frame1,video_path #global stop_event,thread_video #cap = cv2.VideoCapture(video_path) def play(): #print('cap:',cap) ret, frame = cap.read() #print('ret1:',ret) #print('frame:',frame) if ret: # 确定矩形的位置和大小 #print('ret2:',ret) selected_option = radio_var.get() if selected_option == '3': #x = 800 #y = 300 x11=entry_x41.get() y11=entry_y41.get() x=int(x11) # 存在偏差,进行校正 y=int(y11) w =50 h = 50 #print('1111+++') try: cv2.rectangle(frame,(x, y), (x+w, y+h), (0,255, 0), thickness=6) # 使用FILLED来填充矩形 绿色 except OSError as err: print("OS error: {0}".format(err)) #print('2222') frame1=frame #out.write(frame) # 将视频帧显示在Canvas上 img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) img = Image.fromarray(img) img = img.resize((width, height),Image.LANCZOS) # 调整视频帧大小以适应Canvas大小 # 将PIL图像转换为ImageTk图像 img = ImageTk.PhotoImage(image=img) canvas1.create_image(0, 0, anchor=tk.NW, image=img) canvas1.img = img canvas1.after(10, play_video1) #threading.Thread(target=play).start() #stop_event = threading.Event() #thread_video = threading.Thread(target=play,args=(stop_event,)) thread_video = threading.Thread(target=play, daemon=True) #daemon=True 守护线程 thread_video.start() """ while thread.is_alive(): print("Thread is still running") time.sleep(1) print("Thread has finished") """ def stop_play(): print('进入_停止播放') global cap #global stop_event,thread_video #stop_event.set() #thread_video.join() cap.release() cv2.destroyAllWindows() """ def delayed_action(): time.sleep(3) # 延时5秒 get_rgb_point(event) print("延时结束") """ """ def on_canvas1_click(event): global cap,frame1 print('frame1:',frame1) if frame1 is not None: x, y = int(event.x), int(event.y) # 获取点击坐标(注意转换坐标系) pixel = frame1[y, x] # 获取RGB值,注意opencv的BGR顺序,此处已转换为RGB显示,所以直接取用即可 print(f"Clicked pixel RGB: {pixel}") # 打印RGB值,注意这里是BGR顺序,但因为我们用的是Pillow显示,所以已经是RGB顺序了。 # 注意:如果要保持与原始视频帧的一致性(BGR),则应使用pixel[::-1]来获取RGB顺序的元组。 print(f"Clicked pixel BGR: {pixel[::-1]}") # 打印原始BGR顺序的RGB值(如果需要) """ def get_rgb_at_mouse(event): print('进入_获取RGB') selected_option = radio_var.get() print('selected_option:',selected_option) if selected_option == '1': print('进入_鼠标“点击”获取RGB') get_rgb_point(event) elif selected_option == '2': print('进入_选定“点”获取RGB') def print_number(number): get_rgb_point(event) count21 = entry_c21.get() # 获取输入框内容 count21_int = int(count21) if number < count21_int-1: # 假设我们想输出10次 threading.Timer(3, print_number, args=[number+1]).start()# 3秒 print_number(0) elif selected_option == '3': print('进入_选定“面”获取RGB') def print_number1(number): get_rgb_point(event) count31 = entry_c31.get() # 获取输入框内容 count31_int = int(count31) if number < count31_int-1: # 假设我们想输出10次 threading.Timer(5, print_number1, args=[number+1]).start() # 5秒 print_number1(0) else: print('请选择选取方式') def get_rgb_point(event): print('----- 进入_获取RGB -----') global flag_picture,flag_video # 获取当前时间 #now = datetime.now() # 格式化时间 #current_datetime = now.strftime("%Y-%m-%d %H:%M:%S") #print("当前日期和时间:", current_datetime) try: #while True: # 获取当前鼠标的位置 #xx = int(event.x) # yy = int(event.y) #print('xx:',xx,'_yy:',yy) selected_option = radio_var.get() print('selected_option:',selected_option) if selected_option == '1': x, y = pyautogui.position() # 截取当前屏幕图像 screenshot = pyautogui.screenshot() # 获取鼠标位置的 RGB 值 rgb = screenshot.getpixel((x, y)) # 打印 RGB 值 print(f"鼠标位置: ({x}, {y}) -> RGB: {rgb}") #print('RGB:',rgb,type(rgb)) display_point_item(x,y,rgb) elif selected_option == '2': x21 = entry_x21.get() # 获取输入框内容 y21 = entry_y21.get() # 获取输入框内容 x=int(x21) y=int(y21) #pyautogui.click(x=x,y=y) pyautogui.moveTo(x=x,y=y) #x, y = pyautogui.position() # 截取当前屏幕图像 screenshot = pyautogui.screenshot() # 获取鼠标位置的 RGB 值 rgb = screenshot.getpixel((x, y)) # 打印 RGB 值 print(f"鼠标位置: ({x}, {y}) -> RGB: {rgb}") #print('RGB:',rgb,type(rgb)) display_point_item(x,y,rgb) elif selected_option == '3': if flag_picture == 1 and flag_video == 0: ccc = 40 else: ccc = 0 #print('3333') x1=0 x2=0 x3=0 x4=0 y1=0 y2=0 y3=0 y4=0 x31 = entry_x31.get() # 获取输入框内容 y31 = entry_y31.get() # 获取输入框内容 x1=int(x31)-25 # 方框点 y1=int(y31)-25 ## 第1点 ## pyautogui.moveTo(x=x1,y=y1) #pyautogui.moveRel(100,500,duration=4) # 第一个参数是左右移动像素值,第二个是上下移动像素值 #pyautogui.moveRel(x,y,duration=4) # 截取当前屏幕图像 screenshot = pyautogui.screenshot() # 获取鼠标位置的 RGB 值 rgb1 = screenshot.getpixel((x1, y1)) # 打印 RGB 值 #print(f"鼠标位置: ({x}, {y}) -> RGB: {rgb}") #print('RGB1:',rgb1,type(rgb1)) ## 第2点 ## x2=x1+50 # 方框点 y2=y1 pyautogui.moveTo(x=x2,y=y2) screenshot = pyautogui.screenshot() rgb2 = screenshot.getpixel((x2, y2)) #print('RGB2:',rgb2,type(rgb2)) ## 第3点 ## x3=int(x31)+25 # 方框点 y3=int(y31)+25 # 方框点 pyautogui.moveTo(x=x3,y=y3) screenshot = pyautogui.screenshot() rgb3 = screenshot.getpixel((x3, y3)) #print('RGB3:',rgb3,type(rgb3)) ## 第4点 ## x4=x1 y4=y1+50 # 方框点 pyautogui.moveTo(x=x4,y=y4) screenshot = pyautogui.screenshot() rgb4 = screenshot.getpixel((x4, y4)) #print('RGB4:',rgb4,type(rgb4)) ## 第5点 ## x5=int(x31) # 方框点中心 y5=int(y31) # 方框点中心 pyautogui.moveTo(x=x5,y=y5) screenshot = pyautogui.screenshot() rgb5 = screenshot.getpixel((x5, y5)) #print('RGB5:',rgb5,type(rgb5)) rgb1_list = list(rgb1) rgb2_list = list(rgb2) rgb3_list = list(rgb3) rgb4_list = list(rgb4) rgb5_list = list(rgb5) #print('1:',int(rgb1_list[0])) #print('2:',int(rgb2_list[0])) #print('3:',int(rgb3_list[0])) #print('4:',int(rgb4_list[0])) #print('5:',int(rgb5_list[0])) r_avg =(int(rgb1_list[0]) +int(rgb2_list[0]) +int(rgb3_list[0]) +int(rgb4_list[0]) +int(rgb5_list[0]) )/5 g_avg =(int(rgb1_list[1]) +int(rgb2_list[1]) +int(rgb3_list[1]) +int(rgb4_list[1]) +int(rgb5_list[1]) )/5 b_avg =( int(rgb1_list[2]) +int(rgb2_list[2]) +int(rgb3_list[2]) +int(rgb4_list[2]) +int(rgb5_list[2]) )/5 rgb_list = [] rgb_list.append(int(r_avg)) rgb_list.append(int(g_avg)) rgb_list.append(int(b_avg)) x=x5 y=y5 rgb=tuple(rgb_list) #print('rgb:',rgb,type(rgb)) # 截取当前屏幕图像 #screenshot = pyautogui.screenshot() # 获取鼠标位置的 RGB 值 #rgb = screenshot.getpixel((x, y)) # 打印 RGB 值 print(f"鼠标位置: ({x}, {y}) -> RGB: {rgb}") #print('RGB:',rgb,type(rgb)) display_point_item(x,y,rgb) # 暂停一段时间,避免过于频繁的输出 #time.sleep(0.5) except KeyboardInterrupt: print("\n程序已结束。") def display_point_item(x,y,rgb): #print('x_y_rgb:',x,'_',y,'_',rgb) ### 显示RGB ### selected_option = radio_var.get() #print('selected_option:',selected_option) if selected_option == '1': #text_11 =str(xx) text_11 =str(x) label_item_11.configure(text=text_11) #text_12 =str(yy) text_12 =str(y) label_item_12.configure(text=text_12) text_13 =str(rgb[0]) label_item_13.configure(text=text_13) text_14 =str(rgb[1]) label_item_14.configure(text=text_14) text_15 =str(rgb[2]) label_item_15.configure(text=text_15) r=int(text_13) g=int(text_14) b=int(text_15) elif selected_option == '2': """ text_11 =str(x) label_item_11.configure(text=text_11) #text_12 =str(yy) text_12 =str(y) label_item_12.configure(text=text_12) """ text_23 =str(rgb[0]) label_item_23.configure(text=text_23) text_24 =str(rgb[1]) label_item_24.configure(text=text_24) text_25 =str(rgb[2]) label_item_25.configure(text=text_25) r=int(text_23) g=int(text_24) b=int(text_25) elif selected_option == '3': """ text_11 =str(x) label_item_11.configure(text=text_11) #text_12 =str(yy) text_12 =str(y) label_item_12.configure(text=text_12) """ text_33 =str(rgb[0]) label_item_33.configure(text=text_33) text_34 =str(rgb[1]) label_item_34.configure(text=text_34) text_35 =str(rgb[2]) label_item_35.configure(text=text_35) r=int(text_33) g=int(text_34) b=int(text_35) #print('r1_g1_b1:',r,'_',g,'_',b,'_') temp_data_calculate(x,y,r,g,b) def temp_data_calculate(x,y,r,g,b): file_path = 'temp_data_spec.txt' # TXT文件路径 #read_txt_file(file_path) temp_spec = [] with open(file_path, 'r') as file: for line in file: parts = line.strip().split(',') if len(parts) == 6: temp_spec.append((parts[0], parts[1],parts[2],parts[3],parts[4],parts[5])) #print('temp_spec1:',temp_spec) #r=249 #g=100 #b=100 #print('rgb:',r,'-',g,'-',b) list_1 = [] list_2 = [] list_a=[] list_b=[] del temp_spec[0] #print('temp_spec2:',temp_spec) temp_spec_list = [] i=0 while i<len(temp_spec): temp_spec_list_0 = [] temp_spec_list_0.append(temp_spec[i][0]) # 序号 temp_spec_list_0.append(temp_spec[i][1]) # 温度标准 temp_spec_list_0.append(str(int(temp_spec[i][3])+int(temp_spec[i][4])/1000+int(temp_spec[i][5])/(1000*1000))) # 色度标准折算 temp_spec_list.append(temp_spec_list_0) i=i+1 #print('temp_spec_list:',temp_spec_list) rgb_real_data = int(r)+int(g)/1000+int(b)/(1000*1000) print('rgb_real_data:',rgb_real_data) rgb_real_data_str = str(rgb_real_data) # 色度实时值 折算 #print('rgb_real_data_str:',rgb_real_data_str) if rgb_real_data < float(temp_spec_list[-1][2]): print('低于标准最小值') temp_real_data = float(temp_spec_list[-1][1]) * rgb_real_data / float(temp_spec_list[-1][2]) elif rgb_real_data == float(temp_spec_list[-1][2]): print('等于标准最小值') temp_real_data = float(temp_spec_list[-1][1]) elif rgb_real_data > float(temp_spec_list[0][2]): print('高于标准最大值') temp_real_data = float(temp_spec_list[0][1]) * rgb_real_data / float(temp_spec_list[0][2]) elif rgb_real_data == float(temp_spec_list[0][2]): print('等于标准最大值') temp_real_data = float(temp_spec_list[0][1]) else: print('在最小值-最大值之间') """ i=0 while i <len(temp_spec_list): print('float(rgb_real_data_str) :',float(rgb_real_data_str) ) print('float(temp_spec_list[i][2]) :',float(temp_spec_list[i][2])) if float(rgb_real_data_str) == float(temp_spec_list[i][2]): print('111') temp_real_data = temp_spec_list[i][1] i=i+1 """ #print('222') a=0 list_a = [] while a < len(temp_spec_list): if float(rgb_real_data_str) < float(temp_spec_list[a][2]): #print('lower') list_a.append(temp_spec_list[a]) # 所有大于实际值的数值 #print('list_a:',list_a) a=a+1 temp_spec_higher = list_a[-1] # 最后1个,为上限值 print('======temp_spec_higher:',temp_spec_higher) c=0 while c<len(temp_spec_list): #print('temp_data[c][3]:',temp_data[i][3]) if (int(temp_spec_higher[0])+1) == int(temp_spec_list[c][0]): # 上限值+1,为下限值 temp_spec_lower_0 = temp_spec_list[c] c=c+1 temp_spec_lower = list(temp_spec_lower_0) print('======temp_spec_lower:',temp_spec_lower) rgb_spec_data_lower = float(temp_spec_lower[2]) rgb_spec_data_higher = float(temp_spec_higher[2]) temp_spec_data_lower = float(temp_spec_lower[1]) temp_spec_data_higher = float(temp_spec_higher[1]) data_middle = (float(rgb_real_data_str)-rgb_spec_data_lower)/(rgb_spec_data_higher-rgb_spec_data_lower) temp_real_data = (temp_spec_data_higher - temp_spec_data_lower)*data_middle+temp_spec_data_lower print('temp_real_data:',temp_real_data) temp_display(x,y,r,g,b,temp_real_data) def temp_display(x,y,r,g,b,temp_real_data): print('进入_温度显示') #global tree ### 显示温度值 ### selected_option = radio_var.get() #print('selected_option:',selected_option) if selected_option == '1': text_16 =str(int(temp_real_data)) label_item_16.configure(text=text_16) elif selected_option == '2': text_26 =str(int(temp_real_data)) label_item_26.configure(text=text_26) if selected_option == '3': text_36 =str(int(temp_real_data)) label_item_36.configure(text=text_36) temp_spec_lower = (entry_lower11.get()) # 获取输入框内容 temp_spec_higher = (entry_higher11.get()) # 获取输入框内容 print('temp_spec_lower:',temp_spec_lower) temp_spec_higher_int = int(temp_spec_higher) temp_spec_lower_int = int(temp_spec_lower) flag_lower = 0 flag_higher = 0 if temp_real_data < temp_spec_lower_int : print('温度低异常') flag_lower = 1 ### 显示判定值&报警 ### selected_option = radio_var.get() #print('selected_option:',selected_option) if selected_option == '1': text_17 ='异常' #label_item_17.configure(bg='white',fg='red',text='异常') #label_item_17.configure(bg='white',fg='red',text=text_17) text_18 ='温度低' #label_item_18.configure(bg='red',fg='white',text='报警') label_item_18.configure(bg='red',fg='white',text=text_18) label_topic_4.configure(bg='red',fg='white',text='温度偏低') elif selected_option == '2': text_27 ='异常' #label_item_17.configure(bg='white',fg='red',text='异常') #label_item_27.configure(bg='white',fg='red',text=text_27) text_28 ='温度低' #label_item_18.configure(bg='red',fg='white',text='报警') label_item_28.configure(bg='red',fg='white',text=text_28) label_topic_4.configure(bg='red',fg='white',text='温度偏低') elif selected_option == '3': text_37 ='异常' #label_item_17.configure(bg='white',fg='red',text='异常') #label_item_37.configure(bg='white',fg='red',text=text_37) text_38 ='温度低' #label_item_18.configure(bg='red',fg='white',text='报警') label_item_38.configure(bg='red',fg='white',text=text_38) label_topic_4.configure(bg='red',fg='white',text='温度偏低') #messagebox.showwarning(title = "异常!", message="温度偏低......") # 播放系统默认警告声音 #winsound.Beep(1000, 1000) # 频率为1000Hz,时长为1000毫秒 elif temp_real_data > temp_spec_higher_int: print('温度高异常') flag_higher = 1 ### 显示判定值&报警 ### selected_option = radio_var.get() #print('selected_option:',selected_option) if selected_option == '1': text_17 ='异常' #label_item_17.configure(bg='white',fg='red',text='异常') #label_item_17.configure(bg='white',fg='red',text=text_17) text_18 ='温度高' #label_item_18.configure(bg='red',fg='white',text='报警') label_item_18.configure(bg='red',fg='white',text=text_18) label_topic_4.configure(bg='red',fg='white',text='温度偏高') elif selected_option == '2': text_27 ='异常' #label_item_17.configure(bg='white',fg='red',text='异常') #label_item_27.configure(bg='white',fg='red',text=text_27) text_28 ='温度高' #label_item_18.configure(bg='red',fg='white',text='报警') label_item_28.configure(bg='red',fg='white',text=text_28) label_topic_4.configure(bg='red',fg='white',text='温度偏高') elif selected_option == '3': text_37 ='异常' #label_item_17.configure(bg='white',fg='red',text='异常') #label_item_37.configure(bg='white',fg='red',text=text_37) text_38 ='温度高' #label_item_18.configure(bg='red',fg='white',text='报警') label_item_38.configure(bg='red',fg='white',text=text_38) label_topic_4.configure(bg='red',fg='white',text='温度偏高') else: selected_option = radio_var.get() #print('selected_option:',selected_option) if selected_option == '1': print('温度正常') text_17 ='正常' #label_item_17.configure(bg='white',fg='green',text=text_17) text_18 ='正常' label_item_18.configure(bg='green',fg='white',text=text_18) label_topic_4.configure(bg='green',fg='white',text='温度正常') elif selected_option == '2': print('温度正常') text_27 ='正常' #label_item_27.configure(bg='white',fg='green',text=text_27) text_28 ='正常' label_item_28.configure(bg='green',fg='white',text=text_28) label_topic_4.configure(bg='green',fg='white',text='温度正常') elif selected_option == '3': print('温度正常') text_37 ='正常' #label_item_37.configure(bg='white',fg='green',text=text_37) text_38 ='正常' label_item_38.configure(bg='green',fg='white',text=text_38) label_topic_4.configure(bg='green',fg='white',text='温度正常') data_ttl = [] data_ttl_0 = [] # 获取当前时间 now = datetime.now() # 格式化时间 current_datetime = now.strftime("%Y-%m-%d %H:%M:%S") print("当前日期和时间:", current_datetime) global point_count point_count = point_count+1 data_ttl_0.append(str(point_count)) data_ttl_0.append(str(current_datetime)) data_ttl_0.append(str(x)) data_ttl_0.append(str(y)) data_ttl_0.append(str(r)) data_ttl_0.append(str(g)) data_ttl_0.append(str(b)) data_ttl_0.append(str(int(temp_real_data))) data_ttl_0.append(str(temp_spec_lower)) data_ttl_0.append(str(temp_spec_higher)) selected_option = radio_var.get() #print('selected_option:',selected_option) if selected_option == '1': #data_ttl_0.append(str(text_17)) data_ttl_0.append(str(text_18)) elif selected_option == '2': #data_ttl_0.append(str(text_27)) data_ttl_0.append(str(text_28)) elif selected_option == '3': #data_ttl_0.append(str(text_37)) data_ttl_0.append(str(text_38)) data_ttl.append(data_ttl_0) print('data_ttl:',data_ttl) # 插入数据项 for item in data_ttl: tree.insert('', '0', values=item) #tree.insert('', 'end', values=item) """ # 获取第一列的所有数据 for item in tree.get_children(): date_tree = tree.item(item, 'values') # 获取第一列的值 print('date_tree:',date_tree) """ date_tree = [] data_tree = [] count_tree = [] for item in tree.get_children(): count_tree_0 = tree.set(item, 'c1') # 获取第一列的值 count_tree.append(int(count_tree_0)) #print('count_tree:',count_tree) for item in tree.get_children(): date_tree_0 = tree.set(item, 'c2') # 获取第一列的值 date_tree.append(date_tree_0) #print('date_tree:',date_tree) # 获取第一列的所有数据 for item in tree.get_children(): data_tree_0 = tree.set(item, 'c8') # 获取第一列的值 data_tree.append(int(data_tree_0)) #print('data_tree:',data_tree) plot_curve(count_tree,date_tree,data_tree) if selected_option == '1' and flag_higher == 1: # 播放系统默认警告声音 winsound.Beep(1000, 1000) # 频率为1000Hz,时长为1000毫秒 messagebox.showwarning(title = "异常!", message="温度偏高......") if selected_option == '1' and flag_lower == 1: # 播放系统默认警告声音 winsound.Beep(1000, 1000) # 频率为1000Hz,时长为1000毫秒 messagebox.showwarning(title = "异常!", message="温度偏低......") elif selected_option == '2' and flag_lower == 1: #messagebox.showwarning(title = "异常!", message="温度偏低......") # 播放系统默认警告声音 winsound.Beep(500, 500) # 频率为1000Hz,时长为1000毫秒 elif selected_option == '2' and flag_higher == 1: #messagebox.showwarning(title = "异常!", message="温度偏低......") # 播放系统默认警告声音 winsound.Beep(500, 500) # 频率为1000Hz,时长为1000毫秒 elif selected_option == '3' and flag_lower == 1: #messagebox.showwarning(title = "异常!", message="温度偏低......") # 播放系统默认警告声音 winsound.Beep(500, 500) # 频率为1000Hz,时长为1000毫秒 elif selected_option == '3' and flag_higher == 1: #messagebox.showwarning(title = "异常!", message="温度偏低......") # 播放系统默认警告声音 winsound.Beep(500, 500) # 频率为1000Hz,时长为1000毫秒 def plot_curve(count_tree,date_tree,data_tree): print('进入_曲线绘图') global output, fig output = None x = count_tree y= data_tree fig = Figure(figsize=(6.4, 3.1), dpi=100) # adding the subplot plot1 = fig.add_subplot(111) # plotting the graph #plot1.plot(x,y_higher,'ro-', label='H_Line', markersize=1) plot1.plot(x,y, 'bo-', label='Value',markersize=5) #plot1.plot(x,y_lower,'ro-', label='L_Line', markersize=1) # 添加图例 plot1.legend() # 设置字体,避免出现方块 plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体为黑体 plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题 # 设置图表标题和坐标轴标签 #plot1.set_title('变化趋势图', fontsize=14) plot1.set_xlabel('序号') plot1.set_ylabel('数值') #plot1.set_rotation(180) #plot1.set_xticks(fontname='Times New Roman', fontsize=14) #plot1.set_yticks(fontname='Times New Roman', fontsize=14) output = FigureCanvasTkAgg(fig, master=canvas2) print('FigureCanvasTkAgg:',FigureCanvasTkAgg) #messagebox.showinfo("提示", "绘图中,请稍后......") output.draw() output.get_tk_widget().place(x=0, y=0) def clear_video_plot(): count_tree =[] date_tree=[] data_tree=[] plot_curve(count_tree,date_tree,data_tree) tree.delete(*tree.get_children()) global point_count point_count=0 def page_to_main(): print('page_to_main') #window_video.place_forget() window_video.iconify() # 最小化窗口 #self.open_window_sql() def page_to_sql(): print('page_to_sql') #window_video.iconify() # 最小化窗口 window_video.destroy() NewWindow_sql(master) #self.open_window_sql() # 连接到MySQL数据库 def connect_to_database(): return mysql.connector.connect( host="localhost", user="root", password="123456", database="pic_temp" ) # 将Treeview中的数据保存到数据库 def save_to_database(): print('进入_保存数据到Mysql') # 连接到数据库并保存数据到数据库的按钮 conn = connect_to_database() database_name = "pic_temp" cursor = conn.cursor() items = tree.get_children() flag_save_ok = 0 for item in items[::-1] : # 从 tree 最后1条开始读取 values = tree.item(item, 'values') #print('values:',values) try: query = "SELECT COUNT(*) FROM temp_real WHERE date = %s" # 查询测试记录是否存在,避免重复保存 cursor.execute(query, (values[1],)) results = cursor.fetchone()[0] if results == 0: sql_01 = "INSERT INTO temp_real (date, x,y,r,g,b,temp,lower,higher,alarm) "+\ "VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)" cursor.execute(sql_01, (values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], values[9], values[10])) conn.commit() # 提交更改到数据库 flag_save_ok = 1 else: flag_save_ok = 2 print("数据重复保存!") messagebox.showinfo("提示", "数据重复保存!") except mysql.connector.Error as err: print("Error: ", err) flag_save_ok = 0 conn.rollback() if flag_save_ok == 1: print("保存数据库完成!") messagebox.showinfo("提示", "保存数据库完成!\n数据表名:"+database_name) elif flag_save_ok == 0: print("保存数据库异常!") messagebox.showinfo("提示", "保存数据库异常!\n异常名:"+err) cursor.close() conn.close() def output_excel(): #global tree print('进入_导出数据到EXCEL') #file_path = filedialog.asksaveasfilename(defaultextension='.xlsx') #if file_path: # 获取所有行数据 records = tree.get_children() data = [tree.item(r)['values'] for r in records] df = pd.DataFrame(data, columns=['序号', '时间', 'X','Y', 'R', 'G', 'B','温度', '下限', '上限','报警']) # 获取当前时间 now = datetime.now() # 格式化时间 current_datetime = now.strftime("%Y%m%d_%H%M%S") print("当前日期和时间:", current_datetime) # 将DataFrame导出到Excel文件 file_path = 'Temp_output_'+str(current_datetime)+'.xlsx' df.to_excel(file_path, index=False) print("导出Excel完成!") messagebox.showinfo("提示", "导出Excel完成!\n文件名:"+file_path) #else: #print("未选择保存文件路径") #messagebox.showinfo("提示", "未选择保存文件路径!") ### 界面 ### path = StringVar() ### 左侧 ### #radio_button_camera = tk.Radiobutton(window_video, text="摄像头",variable=radio_var_path, value="1",font=('宋体', 11)) #radio_button1.place(x=30, y=80) #radio_button_pic = tk.Radiobutton(window_video, text="照片图像",variable=radio_var_path, value="2",font=('宋体', 11)) #radio_button1.place(x=30, y=130) label_topic_2 = Label(window_video, text="照片图像", font=('宋体', 18)) label_topic_2.place(x=30, y=130) #button_camera_open = tk.Button(window_video, text="开启\n摄像头", command=open_camera,width=5, height=2) #button_camera_open.place(x=10, y=120) button_select = tk.Button(window_video, text="选择\n文件", command=select_file,width=5, height=2) button_select.place(x=150, y=120) label_path=tk.Label(window_video,text = "目标路径:",width=10, height=2) label_path.place(x=200, y=110) entry_path=tk.Entry(window_video, textvariable = path,width=25, font=('宋体', 10)) entry_path.place(x=200, y=145) button_play = tk.Button(window_video, text="显示\n画面", command=play_display,width=5, height=2) button_play.place(x=390, y=120) button_camera_open = tk.Button(window_video, text="开启\n摄像头", command=open_camera,width=5, height=2) button_camera_open.place(x=450, y=120) button_stop = tk.Button(window_video, text="停止\n播放", command=stop_play,width=5, height=2) button_stop.place(x=500, y=120) button_camera_save = tk.Button(window_video, text="录制\n视频", command=record_camera,width=5, height=2) button_camera_save.place(x=550, y=120) button_camera_stop = tk.Button(window_video, text="关闭\n摄像头", command=close_camera,width=5, height=2) button_camera_stop.place(x=600, y=120) width = 630 height = 300 # 调整窗口大小以适应视频 canvas1 = tk.Canvas(window_video, width=630, height=300,bg='lightgreen') canvas1.place(x=10, y=185) #canvas1.bind("<Button-1>", on_canvas1_click) canvas1.bind("<Button-1>", get_rgb_at_mouse) ### 第0行 ### label_item_01 = Label(window_video, text="选择方式", font=('宋体', 11)) label_item_01.place(x=10, y=500) label_item_0B = Label(window_video, text="次数", font=('宋体', 11)) label_item_0B.place(x=90, y=500) label_item_07 = Label(window_video, text="X", font=('宋体', 11)) label_item_07.place(x=150, y=500) label_item_08 = Label(window_video, text="Y", font=('宋体', 11)) label_item_08.place(x=200, y=500) label_item_09 = Label(window_video, text="R", font=('宋体', 11)) label_item_09.place(x=250, y=500) label_item_10 = Label(window_video, text="G", font=('宋体', 11)) label_item_10.place(x=300, y=500) label_item_0A = Label(window_video, text="B", font=('宋体', 11)) label_item_0A.place(x=350, y=500) label_item_02 = Label(window_video, text="温度", font=('宋体', 11)) label_item_02.place(x=400, y=500) label_item_03 = Label(window_video, text="下限值", font=('宋体', 11)) label_item_03.place(x=470, y=500) label_item_04 = Label(window_video, text="上限值", font=('宋体', 11)) label_item_04.place(x=540, y=500) #label_item_05 = Label(window_video, text="数据质量", font=('宋体', 11)) #label_item_05.place(x=710, y=500) label_item_06 = Label(window_video, text="报警", font=('宋体', 11)) label_item_06.place(x=610, y=500) #label_item_11 = Label(window, text="温度1", font=('宋体', 12)) #label_item_11.place(x=250, y=700) ### 第1行 ### label_item_1B = Label(window_video, text="1", font=('宋体', 11)) label_item_1B.place(x=90, y=550) label_item_11 = Label(window_video, text="X1", font=('宋体', 11)) label_item_11.place(x=150, y=550) label_item_12 = Label(window_video, text="Y1", font=('宋体', 11)) label_item_12.place(x=200, y=550) label_item_13 = Label(window_video, text="R1", font=('宋体', 11)) label_item_13.place(x=250, y=550) label_item_14 = Label(window_video, text="G1", font=('宋体', 11)) label_item_14.place(x=300, y=550) label_item_15 = Label(window_video, text="B1", font=('宋体', 11)) label_item_15.place(x=350, y=550) label_item_16 = Label(window_video, text="温度1", font=('宋体', 11)) label_item_16.place(x=400, y=550) entry_lower11= Entry(window_video, width=5, font=('宋体', 11)) entry_lower11.place(x=470, y=550) entry_lower11.insert(0, "48") entry_higher11 = Entry(window_video, width=5, font=('宋体', 11)) entry_higher11.place(x=540, y=550) entry_higher11.insert(0, "58") #label_item_17 = Label(window_video, text="数据质量", font=('宋体', 11)) #label_item_17.place(x=750, y=550) label_item_18 = Label(window_video, text="报警", font=('宋体', 11)) label_item_18.place(x=610, y=550) #label_item_21 = Label(window, text="温度2", font=('宋体', 12)) #label_item_21.place(x=250, y=750) ### 第2行 ### entry_c21 = Entry(window_video, width=5, font=('宋体', 11)) entry_c21.place(x=90, y=600) entry_c21.insert(0, "3") entry_x21 = Entry(window_video, width=5, font=('宋体', 11)) entry_x21.place(x=150, y=600) entry_x21.insert(0, "410") entry_y21 = Entry(window_video, width=5, font=('宋体', 11)) entry_y21.place(x=200, y=600) entry_y21.insert(0, "490") label_item_23 = Label(window_video, text="R2", font=('宋体', 11)) label_item_23.place(x=250, y=600) label_item_24 = Label(window_video, text="G2", font=('宋体', 11)) label_item_24.place(x=300, y=600) label_item_25 = Label(window_video, text="B2", font=('宋体', 11)) label_item_25.place(x=350, y=600) label_item_26 = Label(window_video, text="温度2", font=('宋体', 11)) label_item_26.place(x=400, y=600) entry_lower22 = Entry(window_video,width=5, font=('宋体', 11)) entry_lower22.place(x=470, y=600) entry_lower22.insert(0, "48") entry_higher22 = Entry(window_video, width=5, font=('宋体', 11)) entry_higher22.place(x=540, y=600) entry_higher22.insert(0, "58") #label_item_27 = Label(window_video, text="数据质量", font=('宋体', 11)) #label_item_27.place(x=750, y=600) label_item_28 = Label(window_video, text="报警", font=('宋体', 11)) label_item_28.place(x=610, y=600) ### 第3行 ### entry_c31 = Entry(window_video, width=5, font=('宋体', 11)) entry_c31.place(x=90, y=650) entry_c31.insert(0, "3") entry_x31 = Entry(window_video, width=5, font=('宋体', 11)) entry_x31.place(x=150, y=650) entry_x31.insert(0, "410") entry_y31 = Entry(window_video, width=5, font=('宋体', 11)) entry_y31.place(x=200, y=650) entry_y31.insert(0, "490") label_item_33 = Label(window_video, text="R3", font=('宋体', 11)) label_item_33.place(x=250, y=650) label_item_34 = Label(window_video, text="G3", font=('宋体', 11)) label_item_34.place(x=300, y=650) label_item_35 = Label(window_video, text="B3", font=('宋体', 11)) label_item_35.place(x=350, y=650) label_item_36 = Label(window_video, text="温度3", font=('宋体', 11)) label_item_36.place(x=400, y=650) entry_lower32 = Entry(window_video, width=5, font=('宋体', 11)) entry_lower32.place(x=470, y=650) entry_lower32.insert(0, "48") entry_higher32 = Entry(window_video, width=5, font=('宋体', 11)) entry_higher32.place(x=540, y=650) entry_higher32.insert(0, "58") #label_item_37 = Label(window_video, text="数据质量", font=('宋体', 11)) #label_item_37.place(x=750, y=650) label_item_38 = Label(window_video, text="报警", font=('宋体', 11)) label_item_38.place(x=610, y=650) ### 第4行 ### label_item_41 = Label(window_video, text="方框", font=('宋体', 11)) label_item_41.place(x=90, y=675) entry_x41 = Entry(window_video, width=5, font=('宋体', 11)) entry_x41.place(x=150, y=675) entry_x41.insert(0, "300") entry_y41 = Entry(window_video, width=5, font=('宋体', 11)) entry_y41.place(x=200, y=675) entry_y41.insert(0, "250") # 单选框 radio_var = tk.StringVar() # 创建一个StringVar变量,用于存储选中的值 radio_var.set('1') #radio_var.set(None) # 创建第一个单选框 radio_button1 = tk.Radiobutton(window_video, text="任意点",variable=radio_var, value="1",font=('宋体', 11)) radio_button1.place(x=10, y=545) # 创建第二个单选框 radio_button2 = tk.Radiobutton(window_video, text="选定点",variable=radio_var, value="2",font=('宋体', 11)) radio_button2.place(x=10, y=595) # 创建第三个单选框 radio_button3 = tk.Radiobutton(window_video, text="选定面",variable=radio_var, value="3",font=('宋体', 11)) radio_button3.place(x=10, y=645) ### 右侧 ### label_topic_3 = Label(window_video, text="数据曲线", font=('宋体', 18)) label_topic_3.place(x=750, y=130) label_topic_4 = Label(window_video, text="设备状况", font=('宋体', 18)) label_topic_4.place(x=950, y=130) button_clear = tk.Button(window_video, text="清除\n数据", command=clear_video_plot,width=5, height=2) #button_clear.place(x=900, y=680) button_clear.place(x=1100, y=120) button_clear = tk.Button(window_video, text="保存到\n数据库", command=save_to_database,width=5, height=2) #button_clear.place(x=900, y=680) button_clear.place(x=1150, y=120) button_clear = tk.Button(window_video, text="导出到\nExcel", command=output_excel,width=5, height=2) #button_clear.place(x=900, y=680) button_clear.place(x=1200, y=120) canvas2 = tk.Canvas(window_video, width=630, height=300,bg='lightyellow') canvas2.place(x=650, y=185) # 列表 # 创建Treeview控件 tree = ttk.Treeview(window_video, columns=('c1','c2', 'c3', 'c4', 'c5', 'c6', 'c7','c8','c9','c10','c11'), show='headings') # 创建滚动条 scrollbar = ttk.Scrollbar(window_video, orient="vertical", command=tree.yview) tree.configure(yscrollcommand=scrollbar.set) # 放置Treeview到窗口中 tree.place(x=680, y=500, width=590, height=180) # 在窗口的特定位置放置 # 将滚动条与树形控件关联 #tree.place(x=0, y=0, relwidth=1, relheight=1) # 让树形控件填满整个窗口 #scrollbar.place(x=375, y=0, relheight=1) # 将滚动条放置在右侧,宽度固定为25像素(可根据需要调整) scrollbar.place(x=1270, y=500,height=180) # 将滚动条放置在右侧,宽度固定为25像素(可根据需要调整) tree.column('c1', width=30, minwidth=30) # 配置第1列的宽度和最小宽度 tree.column('c2', width=130, minwidth=130) # 配置第2列的宽度和最小宽度 tree.column('c3', width=30, minwidth=30) # 配置第3列的宽度和最小宽度 tree.column('c4', width=30, minwidth=30) # 配置第4列的宽度和最小宽度 tree.column('c5', width=30, minwidth=30) # 配置第5列的宽度和最小宽度 tree.column('c6', width=30, minwidth=30) # 配置第6列的宽度和最小宽度 tree.column('c7', width=30, minwidth=30) # 配置第7列的宽度和最小宽度 tree.column('c8', width=30, minwidth=30) # 配置第8列的宽度和最小宽度 tree.column('c9', width=30, minwidth=30) # 配置第9列的宽度和最小宽度 tree.column('c10', width=30, minwidth=30) # 配置第10列的宽度和最小宽度 #tree.column('c11', width=30, minwidth=30) # 配置第11列的宽度和最小宽度 tree.column('c11', width=30, minwidth=30) # 配置第12列的宽度和最小宽度 # 设置列标题 tree.heading('c1', text='序号') tree.heading('c2', text='时间') tree.heading('c3', text='X') tree.heading('c4', text='Y') tree.heading('c5', text='R') tree.heading('c6', text='G') tree.heading('c7', text='B') tree.heading('c8', text='温度') tree.heading('c9', text='下限') tree.heading('c10', text='上限') #tree.heading('c11', text='质量') tree.heading('c11', text='报警') window_video.mainloop() if __name__ == "__main__": # 创建主窗口实例 root = tk.Tk() app = MainWindow(root) #root.geometry("1550x800+150+150") root.geometry("510x650+600+150") root.mainloop() 帮我解析各部分代码的功能

最新推荐

recommend-type

基于MATLAB Simulink的六轴机器人阻抗力控制算法仿真与应用 · 机器人技术

六轴机器人阻抗力控制算法的实现方法及其在MATLAB Simscape平台上的仿真应用。文章首先解释了六轴机器人和阻抗力控制算法的基本概念,然后展示了如何在Simscape环境中构建虚拟机器人模型,并通过M文件设置Simulink参数,实现对机器人运动轨迹和阻抗参数的精确控制。文中还提供了视频演示,直观展示了期望轨迹与实际轨迹的对比,验证了算法的有效性。最后,强调了一键运行的功能,简化了工程实践的操作流程,提升了效率。 适合人群:对机器人技术和控制算法感兴趣的科研人员、工程师和技术爱好者。 使用场景及目标:适用于需要深入了解六轴机器人阻抗力控制算法的工作原理及其实现方法的人群,旨在提高他们对该领域的理论认知和实际操作能力。 其他说明:通过本项目的实践,读者不仅可以掌握机器人阻抗力控制算法的关键技术点,还能学会利用MATLAB工具进行高效建模和仿真的方法。这对于后续的研究和开发工作具有重要的指导意义。
recommend-type

(2025)《劳动合同法》知识竞赛试题库及答案(通用版).docx

(2025)《劳动合同法》知识竞赛试题库及答案(通用版).docx
recommend-type

快速浏览Hacker News热门故事的浏览器扩展

Hacker News Browser-crx插件是一款专为浏览器设计的扩展程序,它允许用户从任何网页上浏览Hacker News上的热门故事,该网站是科技界尤其是编程和创业圈子中非常受欢迎的信息交流平台。Hacker News上的内容主要包括编程、科技创业、互联网趣闻以及相关的讨论。它由Y Combinator(一家知名的硅谷创业孵化器)所维护。 ### 关键知识点解析: 1. **扩展程序(Extension)**: - 扩展程序是一种软件,旨在为浏览器提供额外功能和定制选项。它们可以增强用户的浏览体验,提高效率和安全性。扩展程序通常开发于HTML、CSS和JavaScript技术栈,可以针对不同的浏览器开发,如Chrome、Firefox、Safari等。 2. **Hacker News简介**: - Hacker News(也称为Hacker News或者HN)是一个新闻社交网站,由Paul Graham和Trevor Blackwell等人于2007年发起,隶属于Y Combinator。它提供了一个平台,让用户分享、讨论技术新闻和创业公司的相关文章。Hacker News社区以其高质量的讨论和新闻而闻名,吸引了大量程序员、企业家和科技爱好者。 3. **Hacker News Browser-crx插件功能**: - **浏览过去24小时的热门故事**:插件允许用户查看Hacker News中最近24小时内的热门内容。这为用户提供了快速获取当前科技界热门话题的途径。 - **保存故事到Pocket**:Pocket是一个服务,允许用户保存文章、视频和网页以便离线阅读。Hacker News Browser-crx插件可以与用户的Pocket账户集成,方便用户保存他们感兴趣的内容到自己的Pocket列表中。 - **直接从扩展发推文**:社交媒体是现代信息传播的一个重要渠道。通过这个功能,用户可以将他们在Hacker News上的发现直接通过Twitter分享给他们的关注者。 - **搜索特定主题**:用户可以使用这个功能来搜索Hacker News上的特定主题或关键词,从而快速定位他们感兴趣的内容。 4. **如何使用Hacker News Browser-crx插件**: - 安装扩展:用户需要从浏览器的扩展商店下载并安装Hacker News Browser-crx插件。由于给定信息中提供的文件名为Hacker_News_Browser.crx,这表明这可能是一个Chrome扩展。 - 启用扩展:安装完成后,用户需要在浏览器的扩展管理界面启用该插件。 - 进行配置(可选):根据需要,用户可能需要对插件进行一些基本配置,比如设置Pocket账户等。 - 使用功能:安装并配置完成后,用户可以开始使用扩展提供的各项功能,包括浏览热门故事、保存内容到Pocket、发推文和搜索特定主题。 ### 总结: Hacker News Browser-crx插件作为一个扩展程序,为用户提供了便捷的途径去浏览和参与Hacker News上的讨论。该插件整合了多种功能,让读者能够实时关注科技动态,并与他人分享讨论。对于科技爱好者以及相关行业的专业人士,这是一个极具价值的工具,它能够帮助他们保持信息的及时更新和知识的持续吸收。
recommend-type

【MATLAB通信建模秘籍】:5个技巧让你为通信系统打下坚实基础

# 1. MATLAB通信建模基础概览 MATLAB(矩阵实验室)作为一种强大的科学计算软件,在通信系统建模和仿真领域扮演着重要角色。对于初学者而言,了解MATLAB的基础操作和通信建模的基本概念是开启深入学习之旅的第一步。 ## 1.1 MATLAB简介及其在通信领域的应用 MATLAB是一个高性能的数值计算和可视化软件,广泛应用于工程计算、算法开发、数据分析等领域。在通
recommend-type

汽车车载通讯技术

<think>我们正在讨论汽车车载通讯技术。根据之前的引用,我们知道汽车通信网络分为车内(有线)和车外(无线)两部分。同时,车载SOA架构使用多种通信技术(如CAN总线、以太网、MQTT等)来实现模块化和可扩展的通信。 用户的问题:汽车车载通讯技术原理及应用 回答结构: 1. 概述:简要介绍汽车车载通讯技术的定义和分类。 2. 原理部分:分别介绍车内网络和车外网络的主要技术原理。 2.1 车内网络:重点介绍CAN总线、LIN总线、FlexRay、MOST、Automotive Ethernet等。 2.2 车外网络:介绍V2X(包括V2V、V2I、V2P、V2N)及相
recommend-type

Dev Context Menu Utils (beta)-快速开发浏览器扩展

Dev Context Menu Utils (beta)-crx插件是一款面向开发者群体的浏览器扩展程序,其beta版本的命名暗示了它目前还在开发的早期阶段,可能尚未完全稳定或者未包含全部功能。从标题来看,这款扩展程序旨在为开发者提供便捷的上下文菜单功能。 上下文菜单(Context Menu)通常指的是当用户在软件或网页上右键点击时弹出的菜单。上下文菜单的内容根据点击的位置和对象会有所不同,它可以为用户提供快捷、针对当前情境的操作选项。在浏览器中,上下文菜单经常被用于快速访问开发者工具、页面操作、或是网页内容处理等功能。 标题中提到的“CNPJ”和“CPF”是巴西的法人和自然人的税务识别代码。CNPJ(Cadastro Nacional de Pessoas Jurídicas)是巴西所有公司和企业的全国性注册代码,而CPF(Cadastro de Pessoas Físicas)是巴西公民的个人税务识别码。在Dev Context Menu Utils (beta)中加入这两个菜单项,可能意味着插件能够让开发者在遇到需要验证或输入这些税务识别码的场景时,通过浏览器的右键菜单快速生成示例代码或进行其他相关操作。 “Lorem Ipsum”是设计和排版行业常用的一种占位文本,它起源于拉丁文学,经常用于设计软件的文本预览,以便设计师在不影响最终版式的情况下测试页面布局。在这款插件的上下文菜单中加入这一项,可能允许用户快速生成一段Lorem Ipsum文本,用于测试网页布局或者排版效果,从而让开发者在设计过程中获得更真实的视觉体验。 “电话”菜单项则可能用于提供快速生成或者验证电话号码格式的功能,这对于处理与电话相关的用户输入或数据录入工作非常有用。考虑到不同国家和地区的电话号码格式可能有所不同,这一功能可能允许用户选择特定的地区代码,从而生成相应格式的电话号码样例。 【标签】中提到的“扩展程序”一词,是指能够被浏览器安装并添加额外功能的软件。扩展程序可以改变浏览器的基本界面、行为和功能,是Web开发和测试中常见的工具。它们通常由浏览器的开发者或者第三方开发者创建,对于提升开发效率、调试和测试网站有着重要的作用。 【压缩包子文件的文件名称列表】中的“Dev_Context_Menu_Utils_(beta).crx”是这款插件的文件名,CRX是Chrome扩展程序的文件格式,类似于Windows平台上的.exe可执行文件格式,只不过CRX是为Chrome浏览器特别设计的。扩展程序开发者需要通过Chrome Web Store或者其他途径将CRX文件分发给用户,用户可以通过下载并安装CRX文件来使用扩展程序。 总体来说,Dev Context Menu Utils (beta) 插件通过为开发者提供便捷的上下文菜单项来增强开发效率,允许快速生成重要的代码片段和数据格式,从而简化开发过程中的常见任务。对于那些在开发阶段需要频繁使用这些功能的开发者来说,这款插件将是一个非常有价值的工具。然而,由于它目前还是beta版本,使用时可能需要注意可能存在的一些错误或功能限制,并建议开发者在实际项目中使用前先在测试环境中进行充分的测试。
recommend-type

【Coz进阶秘籍】:解锁工作流高级功能,提升效率的终极技巧

# 1. Coz工作流基础概述 工作流系统是现代IT运营不可或缺的一部分,它通过自动化执行任务和协调业务流程来提高效率。在本章节中,我们将首先介绍Coz工作流的基础概念和其在业务流程自动化中的应用。Coz工作流利用一系列预定义的任务、规则以及任务之间的依赖关系,按照既定规
recommend-type

HR和HRBP区别

<think>首先,用户意图是了解HR和HRBP的区别。用户问题是“HR和HRBP的区别”。我需要根据任务要求进行网络搜索。 任务要求: 1. 调用网络搜索工具进行检索。 2. 整合检索到的内容,生成详细且清晰的回答。 3. 禁止将所有引用内容集中在回答末尾。 4. 避免使用第一人称如“我”。 5. 避免步骤词汇如“首先”、“然后”。 6. 尽量将答案组织为多个方法或步骤,并在每个步骤间换行。 7. 对于代码和公式:如果有,必须使用指定格式。 8. 在回答最后添加相关问题部分,标题为“§§相关问题§§:”,后跟至少3个相关问题,每个用阿拉伯数字标号。 由于问题是关于HR和HRBP的区别,不
recommend-type

阻止Web加密货币挖掘的Miner Away扩展

### 知识点分析 #### 标题:“Miner Away-crx插件” **知识点**: 1. **CRX插件格式**:CRX是Chrome扩展程序的文件格式,它是一个ZIP压缩包,包含了扩展程序的所有文件和文件夹,例如HTML、JavaScript、CSS文件,以及扩展程序的清单文件(manifest.json)。CRX文件可以直接在Chrome浏览器的扩展管理界面拖拽安装。 2. **扩展程序(Extension)**:浏览器扩展程序是一种增加或改进浏览器功能的软件模块。它可以通过第三方开发者创建,用以提供特定的功能,比如用户界面定制、广告拦截、内容过滤等。 #### 描述:“在网上停止硬币矿工!” **知识点**: 3. **加密货币挖掘(Cryptocurrency Mining)**:指的是利用计算机的处理能力来计算加密货币的交易并维护区块链的过程。传统的加密货币挖掘需要大量的计算资源和电力消耗,近年来出现了基于Web的挖矿,即在网页中嵌入JavaScript代码,利用访问者的浏览器进行挖掘。 4. **矿工拒绝(Cryptominer Blocking)**:矿工拒绝功能的扩展通常用于识别和阻止这类JavaScript代码运行,从而保护用户设备的性能不受影响。这类扩展程序通常会维护一个黑名单,其中包含已知的挖矿脚本或网站地址。 5. **Opera Web Store**:Opera浏览器的官方扩展商店,类似于Chrome Web Store或Firefox Add-ons,是用户下载、安装和管理Opera浏览器扩展程序的平台。 6. **特征(Features)**: - **阻止JavaScript或Web矿工**:扩展能够检测并阻止网页加载的挖矿脚本。 - **域名选择性允许**:用户可以自行选择允许哪些特定网站加载JavaScript。 - **状态显示**:扩展程序会实时显示当前是否有挖矿行为发生。 - **通知功能**:当有网站尝试进行挖矿时,用户会即时收到桌面通知。 7. **技术实现细节**: - **黑名单机制**:扩展使用黑名单文件(*blacklist.txt*),其中包含被识别为执行挖矿行为的域名。 - **请求拦截**:对与黑名单中域名匹配的网站请求进行拦截,从而防止挖矿脚本运行。 #### 标签:“扩展程序” **知识点**: 8. **浏览器扩展程序的分类**:扩展程序通常根据其功能进行分类,如广告拦截器、密码管理器、下载管理器等。 9. **扩展程序的管理**:用户通常可以在浏览器的扩展管理界面中开启/关闭扩展、管理扩展权限、删除扩展等。 #### 压缩包子文件的文件名称列表:“Miner_Away.crx” **知识点**: 10. **文件命名约定**:扩展程序的文件名通常与其功能相关,例如本例中的“Miner_Away”暗示了该扩展用于阻止挖矿行为。 11. **文件的安装**:CRX文件可以通过多种方式进行安装,最常见的方式是直接从浏览器的扩展管理界面导入(通常通过拖拽文件到浏览器窗口),或者从扩展商店下载安装。 12. **文件的安全性**:用户应从可信来源下载扩展程序,避免下载可能含有恶意软件的非官方版本。 总结以上知识点,Miner Away扩展程序是一种专门设计用于阻止Web矿工的浏览器扩展,它通过黑名单机制拦截和阻止网站加载的加密货币挖掘脚本,保护用户的设备免受未经授权的资源消耗。该扩展还提供实时状态通知和请求拦截功能,为用户提供了更为安全和高效的网络浏览体验。
recommend-type

量子计算模拟与硬件发展:NISQ时代的探索

# 量子计算模拟与硬件发展:NISQ时代的探索 ## 1. 分布式计算在量子模拟中的应用 在量子计算领域,充分利用经典资源是一个重要的课题。分布式计算框架为我们提供了一种有效的途径,如今,这些框架在各大组织中广泛存在。例如,Apache Spark和Ray等分布式计算框架,已被广泛应用于大数据处理和深度学习模型训练。 量子计算模拟器也可以借助分布式生态系统,通过拆分需要执行的数学运算来实现。不过,将一个整体系统拆分为一组独立操作,需要我们深入理解当前问题的可拆分性。目前,处理分布式量子计算模拟的框架大多来自研究团队,像英特尔和百度等大型组织也有相关研究。 随着量子硬件的不断成熟,设备无关