From 4f0bfdfbd8b062298c5a08943b967762e75fd84a Mon Sep 17 00:00:00 2001 From: hzd123456 <3149142602@qq.com> Date: Fri, 11 Jul 2025 20:26:42 +0800 Subject: [PATCH] 1 --- src/test/CameraTest.py | 46 + src/test/VideoTest.py | 37 + src/test/detect_tools.py | 222 + src/test/imgTest.py | 21 + src/test/train.py | 23 + src/ui/MainProgram.py | 623 + src/ui/UIProgram/QssLoader.py | 8 + src/ui/UIProgram/UiMain.py | 519 + src/ui/UIProgram/UiMain.ui | 1226 + src/ui/UIProgram/__init__.py | 0 .../__pycache__/QssLoader.cpython-313.pyc | Bin 0 -> 845 bytes .../__pycache__/QssLoader.cpython-39.pyc | Bin 0 -> 683 bytes .../__pycache__/UiMain.cpython-313.pyc | Bin 0 -> 52045 bytes .../__pycache__/UiMain.cpython-39.pyc | Bin 0 -> 13367 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 132 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 159 bytes .../__pycache__/precess_bar.cpython-313.pyc | Bin 0 -> 3201 bytes .../__pycache__/precess_bar.cpython-39.pyc | Bin 0 -> 1730 bytes .../__pycache__/ui_sources_rc.cpython-39.pyc | Bin 0 -> 535496 bytes src/ui/UIProgram/precess_bar.py | 47 + src/ui/UIProgram/style.css | 16 + src/ui/UIProgram/ui_imgs/bg13.png | Bin 0 -> 1053 bytes src/ui/UIProgram/ui_imgs/bg14.png | Bin 0 -> 1053 bytes src/ui/UIProgram/ui_imgs/icons/camera.png | Bin 0 -> 28928 bytes src/ui/UIProgram/ui_imgs/icons/face.png | Bin 0 -> 50982 bytes src/ui/UIProgram/ui_imgs/icons/folder.png | Bin 0 -> 15800 bytes src/ui/UIProgram/ui_imgs/icons/img.png | Bin 0 -> 21254 bytes src/ui/UIProgram/ui_imgs/icons/video.png | Bin 0 -> 20208 bytes src/ui/UIProgram/ui_imgs/icons/保存.png | Bin 0 -> 30628 bytes .../UIProgram/ui_imgs/icons/目标检测.png | Bin 0 -> 31727 bytes src/ui/UIProgram/ui_imgs/icons/退出.png | Bin 0 -> 25988 bytes src/ui/UIProgram/ui_sources.py | 10 + src/ui/UIProgram/ui_sources.qrc | 13 + src/ui/UIProgram/ui_sources_rc.py | 33465 ++++++++++++++++ 34 files changed, 36276 insertions(+) create mode 100644 src/test/CameraTest.py create mode 100644 src/test/VideoTest.py create mode 100644 src/test/detect_tools.py create mode 100644 src/test/imgTest.py create mode 100644 src/test/train.py create mode 100644 src/ui/MainProgram.py create mode 100644 src/ui/UIProgram/QssLoader.py create mode 100644 src/ui/UIProgram/UiMain.py create mode 100644 src/ui/UIProgram/UiMain.ui create mode 100644 src/ui/UIProgram/__init__.py create mode 100644 src/ui/UIProgram/__pycache__/QssLoader.cpython-313.pyc create mode 100644 src/ui/UIProgram/__pycache__/QssLoader.cpython-39.pyc create mode 100644 src/ui/UIProgram/__pycache__/UiMain.cpython-313.pyc create mode 100644 src/ui/UIProgram/__pycache__/UiMain.cpython-39.pyc create mode 100644 src/ui/UIProgram/__pycache__/__init__.cpython-313.pyc create mode 100644 src/ui/UIProgram/__pycache__/__init__.cpython-39.pyc create mode 100644 src/ui/UIProgram/__pycache__/precess_bar.cpython-313.pyc create mode 100644 src/ui/UIProgram/__pycache__/precess_bar.cpython-39.pyc create mode 100644 src/ui/UIProgram/__pycache__/ui_sources_rc.cpython-39.pyc create mode 100644 src/ui/UIProgram/precess_bar.py create mode 100644 src/ui/UIProgram/style.css create mode 100644 src/ui/UIProgram/ui_imgs/bg13.png create mode 100644 src/ui/UIProgram/ui_imgs/bg14.png create mode 100644 src/ui/UIProgram/ui_imgs/icons/camera.png create mode 100644 src/ui/UIProgram/ui_imgs/icons/face.png create mode 100644 src/ui/UIProgram/ui_imgs/icons/folder.png create mode 100644 src/ui/UIProgram/ui_imgs/icons/img.png create mode 100644 src/ui/UIProgram/ui_imgs/icons/video.png create mode 100644 src/ui/UIProgram/ui_imgs/icons/保存.png create mode 100644 src/ui/UIProgram/ui_imgs/icons/目标检测.png create mode 100644 src/ui/UIProgram/ui_imgs/icons/退出.png create mode 100644 src/ui/UIProgram/ui_sources.py create mode 100644 src/ui/UIProgram/ui_sources.qrc create mode 100644 src/ui/UIProgram/ui_sources_rc.py diff --git a/src/test/CameraTest.py b/src/test/CameraTest.py new file mode 100644 index 0000000..fac501a --- /dev/null +++ b/src/test/CameraTest.py @@ -0,0 +1,46 @@ +#coding:utf-8 +import cv2 +from ultralytics import YOLO + +# 所需加载的模型目录 +path = 'models/best.pt' + +# Load the YOLOv8 model +model = YOLO(path) + +ID = 0 +while(ID<10): + cap = cv2.VideoCapture(ID) + # get a frame + ret, frame = cap.read() + if ret == False: + ID += 1 + else: + print('摄像头ID:',ID) + break + +# Loop through the video frames +while cap.isOpened(): + # Read a frame from the video + success, frame = cap.read() + + if success: + # Run YOLOv8 inference on the frame + results = model(frame) + + # Visualize the results on the frame + annotated_frame = results[0].plot() + + # Display the annotated frame + cv2.imshow("YOLOv8 Inference", annotated_frame) + + # Break the loop if 'q' is pressed + if cv2.waitKey(1) & 0xFF == ord("q"): + break + else: + # Break the loop if the end of the video is reached + break + +# Release the video capture object and close the display window +cap.release() +cv2.destroyAllWindows() \ No newline at end of file diff --git a/src/test/VideoTest.py b/src/test/VideoTest.py new file mode 100644 index 0000000..955e45a --- /dev/null +++ b/src/test/VideoTest.py @@ -0,0 +1,37 @@ +#coding:utf-8 +import cv2 +from ultralytics import YOLO + +# 所需加载的模型目录 +path = 'models/best.pt' +# 需要检测的图片地址 +video_path = "TestFiles/1.mp4" + +# Load the YOLOv8 model +model = YOLO(path) +cap = cv2.VideoCapture(video_path) +# Loop through the video frames +while cap.isOpened(): + # Read a frame from the video + success, frame = cap.read() + + if success: + # Run YOLOv8 inference on the frame + results = model(frame) + + # Visualize the results on the frame + annotated_frame = results[0].plot() + + # Display the annotated frame + cv2.imshow("YOLOv8 Inference", annotated_frame) + + # Break the loop if 'q' is pressed + if cv2.waitKey(1) & 0xFF == ord("q"): + break + else: + # Break the loop if the end of the video is reached + break + +# Release the video capture object and close the display window +cap.release() +cv2.destroyAllWindows() \ No newline at end of file diff --git a/src/test/detect_tools.py b/src/test/detect_tools.py new file mode 100644 index 0000000..23dfefb --- /dev/null +++ b/src/test/detect_tools.py @@ -0,0 +1,222 @@ +# encoding:utf-8 +import cv2 +from PyQt5.QtGui import QPixmap, QImage +import numpy as np +from PIL import Image,ImageDraw,ImageFont +import csv +import os + +# fontC = ImageFont.truetype("Font/platech.ttf", 20, 0) + +# 绘图展示 +def cv_show(name,img): + cv2.imshow(name, img) + cv2.waitKey(0) + cv2.destroyAllWindows() + + +def drawRectBox(image, rect, addText, fontC, color): + """ + 绘制矩形框与结果 + :param image: 原始图像 + :param rect: 矩形框坐标, int类型 + :param addText: 类别名称 + :param fontC: 字体 + :return: + """ + # 绘制位置方框 + cv2.rectangle(image, (rect[0], rect[1]), + (rect[2], rect[3]), + color, 2) + + # 绘制字体背景框 + cv2.rectangle(image, (rect[0] - 1, rect[1] - 25), (rect[0] + 60, rect[1]), color, -1, cv2.LINE_AA) + # 图片 添加的文字 位置 字体 字体大小 字体颜色 字体粗细 + # cv2.putText(image, addText, (int(rect[0])+2, int(rect[1])-3), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 2) + + img = Image.fromarray(image) + draw = ImageDraw.Draw(img) + draw.text((rect[0]+2, rect[1]-27), addText, (255, 255, 255), font=fontC) + imagex = np.array(img) + return imagex + + +def img_cvread(path): + # 读取含中文名的图片文件 + # img = cv2.imread(path) + img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_COLOR) + return img + + +def draw_boxes(img, boxes): + for each in boxes: + x1 = each[0] + y1 = each[1] + x2 = each[2] + y2 = each[3] + cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) + return img + + + +def cvimg_to_qpiximg(cvimg): + height, width, depth = cvimg.shape + cvimg = cv2.cvtColor(cvimg, cv2.COLOR_BGR2RGB) + qimg = QImage(cvimg.data, width, height, width * depth, QImage.Format_RGB888) + qpix_img = QPixmap(qimg) + return qpix_img + + +def save_video(): + # VideoCapture方法是cv2库提供的读取视频方法 + cap = cv2.VideoCapture('C:\\Users\\xxx\\Desktop\\sweet.mp4') + # 设置需要保存视频的格式“xvid” + # 该参数是MPEG-4编码类型,文件名后缀为.avi + fourcc = cv2.VideoWriter_fourcc(*'XVID') + # 设置视频帧频 + fps = cap.get(cv2.CAP_PROP_FPS) + # 设置视频大小 + size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))) + # VideoWriter方法是cv2库提供的保存视频方法 + # 按照设置的格式来out输出 + out = cv2.VideoWriter('C:\\Users\\xxx\\Desktop\\out.avi', fourcc, fps, size) + + # 确定视频打开并循环读取 + while (cap.isOpened()): + # 逐帧读取,ret返回布尔值 + # 参数ret为True 或者False,代表有没有读取到图片 + # frame表示截取到一帧的图片 + ret, frame = cap.read() + if ret == True: + # 垂直翻转矩阵 + frame = cv2.flip(frame, 0) + + out.write(frame) + + cv2.imshow('frame', frame) + if cv2.waitKey(1) & 0xFF == ord('q'): + break + else: + break + + # 释放资源 + cap.release() + out.release() + # 关闭窗口 + cv2.destroyAllWindows() + + +# 封装函数:图片上显示中文 +def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=50): + if (isinstance(img, np.ndarray)): # 判断是否OpenCV图片类型 + img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) + # 创建一个可以在给定图像上绘图的对象 + draw = ImageDraw.Draw(img) + # 字体的格式 + fontStyle = ImageFont.truetype( + "simsun.ttc", textSize, encoding="utf-8") + # 绘制文本 + draw.text(position, text, textColor, font=fontStyle) + # 转换回OpenCV格式 + return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR) + + +def insert_rows(path, lines ,header): + """ + 将n行数据写入csv文件 + :param path: + :param lines: + :return: + """ + no_header = False + if not os.path.exists(path): + no_header = True + start_num = 1 + else: + start_num = len(open(path).readlines()) + + csv_head = header + with open(path, 'a', newline='') as f: + csv_write = csv.writer(f) + if no_header: + csv_write.writerow(csv_head) # 写入表头 + + for each_list in lines: + # 添加序号 + each_list = [start_num] + each_list + csv_write.writerow(each_list) + # 序号 + 1 + start_num += 1 + +class Colors: + # 用于绘制不同颜色 + def __init__(self): + """Initialize colors as hex = matplotlib.colors.TABLEAU_COLORS.values().""" + hexs = ('FF3838', 'FF9D97', 'FF701F', 'FFB21D', 'CFD231', '48F90A', '92CC17', '3DDB86', '1A9334', '00D4BB', + '2C99A8', '00C2FF', '344593', '6473FF', '0018EC', '8438FF', '520085', 'CB38FF', 'FF95C8', 'FF37C7') + self.palette = [self.hex2rgb(f'#{c}') for c in hexs] + self.n = len(self.palette) + self.pose_palette = np.array([[255, 128, 0], [255, 153, 51], [255, 178, 102], [230, 230, 0], [255, 153, 255], + [153, 204, 255], [255, 102, 255], [255, 51, 255], [102, 178, 255], [51, 153, 255], + [255, 153, 153], [255, 102, 102], [255, 51, 51], [153, 255, 153], [102, 255, 102], + [51, 255, 51], [0, 255, 0], [0, 0, 255], [255, 0, 0], [255, 255, 255]], + dtype=np.uint8) + + def __call__(self, i, bgr=False): + """Converts hex color codes to rgb values.""" + c = self.palette[int(i) % self.n] + return (c[2], c[1], c[0]) if bgr else c + + @staticmethod + def hex2rgb(h): # rgb order (PIL) + return tuple(int(h[1 + i:1 + i + 2], 16) for i in (0, 2, 4)) + + +def yolo_to_location(w,h,yolo_data): + # yolo文件转两点坐标,注意画图坐标要转换成int格式 + x_, y_, w_, h_ = yolo_data + x1 = int(w * x_ - 0.5 * w * w_) + x2 = int(w * x_ + 0.5 * w * w_) + y1 = int(h * y_ - 0.5 * h * h_) + y2 = int(h * y_ + 0.5 * h * h_) + # cv2.rectangle(img, (int(x1), int(y1)), (int(x2), int(y2)), (255, 0, 0)) + return [x1,y1,x2,y2] + +def location_to_yolo(w, h, locations): + # x1,y1左上角坐标,x2,y2右上角坐标 + x1, y1, x2, y2 = locations + x_ = (x1 + x2) / 2 / w + x_ = float('%.5f' % x_) + y_ = (y1 + y2) / 2 / h + y_ = float('%.5f' % y_) + w_ = (x2 - x1) / w + w_ = float('%.5f' % w_) + h_ = (y2 - y1) / h + h_ = float('%.5f' % h_) + return [x_,y_,w_,h_] + +def draw_yolo_data(img_path, yolo_file_path): + # 读取yolo标注数据并显示 + img = cv2.imread(img_path) + h, w, _ = img.shape + print(img.shape) + # yolo标注数据文件名为786_rgb_0616.txt + with open(yolo_file_path, 'r') as f: + data = f.readlines() + for each in data: + temp = each.split() + # ['1', '0.43906', '0.52083', '0.34687', '0.15'] + # YOLO转换为两点坐标x1, x2, y1, y2 + x_, y_, w_, h_ = eval(temp[1]), eval(temp[2]), eval(temp[3]), eval(temp[4]) + x1, y1, x2, y2 = yolo_to_location(w,h,[x_, y_, w_, h_]) + # 画图验证框是否正确 + cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255)) + + cv2.imshow('windows', img) + cv2.waitKey(0) + +if __name__ == '__main__': + img_path = 'TestFiles/1.jpg' + yolo_file_path = 'save_data/yolo_labels/1.txt' + draw_yolo_data(img_path, yolo_file_path) + diff --git a/src/test/imgTest.py b/src/test/imgTest.py new file mode 100644 index 0000000..ffea71d --- /dev/null +++ b/src/test/imgTest.py @@ -0,0 +1,21 @@ +#coding:utf-8 +from ultralytics import YOLO +import cv2 + +# 所需加载的模型目录 +path = 'models/best.pt' +# 需要检测的图片地址 +img_path = "TestFiles/test4.jpg" + +# 加载预训练模型 +# conf 0.25 object confidence threshold for detection +# iou 0.7 intersection over union (IoU) threshold for NMS +model = YOLO(path, task='detect') +# model = YOLO(path, task='detect',conf=0.5) + + +# 检测图片 +results = model(img_path) +res = results[0].plot() +cv2.imshow("YOLOv8 Detection", res) +cv2.waitKey(0) \ No newline at end of file diff --git a/src/test/train.py b/src/test/train.py new file mode 100644 index 0000000..e1acb00 --- /dev/null +++ b/src/test/train.py @@ -0,0 +1,23 @@ +#coding:utf-8 +from ultralytics import YOLO + +if __name__ == '__main__': + # 加载已训练的人脸模型 + model = YOLO("runs/detect/train/weights/best.pt") # 指向你的模型路径 + + # 训练迷彩服类别 + results = model.train( + data='datasets/micai/data.yaml', # 新的迷彩服数据集配置 + epochs=10, # 微调不需要太多轮次 + device=0, + batch=2, # 根据GPU内存调整 + imgsz=640, + cache='disk', + workers=4, + pretrained=True, # 使用预训练权重 + optimizer='Adam', # 对于小数据集,Adam比SGD更稳定 + lr0=0.001 # 较低的学习率,避免破坏预训练权重 + ) + + # 导出为ONNX格式 + success = model.export(format='onnx') \ No newline at end of file diff --git a/src/ui/MainProgram.py b/src/ui/MainProgram.py new file mode 100644 index 0000000..d7c9dbb --- /dev/null +++ b/src/ui/MainProgram.py @@ -0,0 +1,623 @@ +# -*- coding: utf-8 -*- +import time +from PyQt5.QtWidgets import QApplication , QMainWindow, QFileDialog, \ + QMessageBox,QWidget,QHeaderView,QTableWidgetItem, QAbstractItemView +import sys +import os +from PIL import ImageFont +from ultralytics import YOLO +sys.path.append('UIProgram') +from UIProgram.UiMain import Ui_MainWindow +import sys +from PyQt5.QtCore import QTimer, Qt, QThread, pyqtSignal,QCoreApplication +import detect_tools as tools +import cv2 +import Config +from UIProgram.QssLoader import QSSLoader +from UIProgram.precess_bar import ProgressBar +import numpy as np +# import torch + +class MainWindow(QMainWindow): + def __init__(self, parent=None): + # 调用父类 QMainWindow 的构造函数,初始化当前窗口实例 + super(QMainWindow, self).__init__(parent) + # 创建 Ui_MainWindow 类的实例,该类用于管理界面元素 + self.ui = Ui_MainWindow() + # 调用 setupUi 方法,将界面元素设置到当前窗口 + self.ui.setupUi(self) + # 调用 initMain 方法,进行窗口的初始化操作 + self.initMain() + # 调用 signalconnect 方法,连接界面元素的信号与相应的槽函数 + self.signalconnect() + + # 加载css渲染效果 + # 指定 CSS 样式文件的路径 + style_file = 'UIProgram/style.css' + # 调用 QSSLoader 类的 read_qss_file 方法,读取 CSS 样式文件内容 + qssStyleSheet = QSSLoader.read_qss_file(style_file) + # 将读取到的 CSS 样式应用到当前窗口 + self.setStyleSheet(qssStyleSheet) + + def signalconnect(self): + self.ui.PicBtn.clicked.connect(self.open_img) + self.ui.comboBox.activated.connect(self.combox_change) + self.ui.VideoBtn.clicked.connect(self.vedio_show) + self.ui.CapBtn.clicked.connect(self.camera_show) + self.ui.SaveBtn.clicked.connect(self.save_detect_video) + self.ui.ExitBtn.clicked.connect(QCoreApplication.quit) + self.ui.FilesBtn.clicked.connect(self.detact_batch_imgs) + + def initMain(self): + self.show_width = 770 + self.show_height = 480 + + self.org_path = None + + self.is_camera_open = False + self.cap = None + + # self.device = 0 if torch.cuda.is_available() else 'cpu' + + # 加载检测模型 + self.model = YOLO(Config.model_path, task='detect') + self.model(np.zeros((48, 48, 3))) #预先加载推理模型 + self.fontC = ImageFont.truetype("Font/platech.ttf", 25, 0) + + # 用于绘制不同颜色矩形框 + self.colors = tools.Colors() + + # 更新视频图像 + self.timer_camera = QTimer() + + # 更新检测信息表格 + # self.timer_info = QTimer() + # 保存视频 + self.timer_save_video = QTimer() + + # 表格 + self.ui.tableWidget.verticalHeader().setSectionResizeMode(QHeaderView.Fixed) + self.ui.tableWidget.verticalHeader().setDefaultSectionSize(40) + self.ui.tableWidget.setColumnWidth(0, 80) # 设置列宽 + self.ui.tableWidget.setColumnWidth(1, 200) + self.ui.tableWidget.setColumnWidth(2, 150) + self.ui.tableWidget.setColumnWidth(3, 90) + self.ui.tableWidget.setColumnWidth(4, 230) + self.ui.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows) # 设置表格整行选中 + self.ui.tableWidget.verticalHeader().setVisible(False) # 隐藏列标题 + self.ui.tableWidget.setAlternatingRowColors(True) # 表格背景交替 + + + def open_img(self): + if self.cap: + # 打开图片前关闭摄像头 + self.video_stop() + self.is_camera_open = False + self.ui.CaplineEdit.setText('摄像头未开启') + self.cap = None + + # 弹出的窗口名称:'打开图片' + # 默认打开的目录:'./' + # 只能打开.jpg与.gif结尾的图片文件 + # file_path, _ = QFileDialog.getOpenFileName(self.ui.centralwidget, '打开图片', './', "Image files (*.jpg *.gif)") + file_path, _ = QFileDialog.getOpenFileName(None, '打开图片', './', "Image files (*.jpg *.jepg *.png)") + if not file_path: + return + + self.ui.comboBox.setDisabled(False) + self.org_path = file_path + self.org_img = tools.img_cvread(self.org_path) + + # 目标检测 + t1 = time.time() + self.results = self.model(self.org_path)[0] + t2 = time.time() + take_time_str = '{:.3f} s'.format(t2 - t1) + self.ui.time_lb.setText(take_time_str) + + location_list = self.results.boxes.xyxy.tolist() + self.location_list = [list(map(int, e)) for e in location_list] + cls_list = self.results.boxes.cls.tolist() + self.cls_list = [int(i) for i in cls_list] + self.conf_list = self.results.boxes.conf.tolist() + self.conf_list = ['%.2f %%' % (each*100) for each in self.conf_list] + + # now_img = self.cv_img.copy() + # for loacation, type_id, conf in zip(self.location_list, self.cls_list, self.conf_list): + # type_id = int(type_id) + # color = self.colors(int(type_id), True) + # # cv2.rectangle(now_img, (int(x1), int(y1)), (int(x2), int(y2)), colors(int(type_id), True), 3) + # now_img = tools.drawRectBox(now_img, loacation, Config.CH_names[type_id], self.fontC, color) + now_img = self.results.plot() + self.draw_img = now_img + # 获取缩放后的图片尺寸 + self.img_width, self.img_height = self.get_resize_size(now_img) + resize_cvimg = cv2.resize(now_img,(self.img_width, self.img_height)) + pix_img = tools.cvimg_to_qpiximg(resize_cvimg) + self.ui.label_show.setPixmap(pix_img) + self.ui.label_show.setAlignment(Qt.AlignCenter) + # 设置路径显示 + self.ui.PiclineEdit.setText(self.org_path) + + # 目标数目 + target_nums = len(self.cls_list) + self.ui.label_nums.setText(str(target_nums)) + + # 设置目标选择下拉框 + choose_list = ['全部'] + target_names = [Config.names[id]+ '_'+ str(index) for index,id in enumerate(self.cls_list)] + # object_list = sorted(set(self.cls_list)) + # for each in object_list: + # choose_list.append(Config.CH_names[each]) + choose_list = choose_list + target_names + + self.ui.comboBox.clear() + self.ui.comboBox.addItems(choose_list) + + if target_nums >= 1: + self.ui.type_lb.setText(Config.CH_names[self.cls_list[0]]) + self.ui.label_conf.setText(str(self.conf_list[0])) + # 默认显示第一个目标框坐标 + # 设置坐标位置值 + self.ui.label_xmin.setText(str(self.location_list[0][0])) + self.ui.label_ymin.setText(str(self.location_list[0][1])) + self.ui.label_xmax.setText(str(self.location_list[0][2])) + self.ui.label_ymax.setText(str(self.location_list[0][3])) + else: + self.ui.type_lb.setText('') + self.ui.label_conf.setText('') + self.ui.label_xmin.setText('') + self.ui.label_ymin.setText('') + self.ui.label_xmax.setText('') + self.ui.label_ymax.setText('') + + # # 删除表格所有行 + self.ui.tableWidget.setRowCount(0) + self.ui.tableWidget.clearContents() + self.tabel_info_show(self.location_list, self.cls_list, self.conf_list,path=self.org_path) + + + def detact_batch_imgs(self): + if self.cap: + # 打开图片前关闭摄像头 + self.video_stop() + self.is_camera_open = False + self.ui.CaplineEdit.setText('摄像头未开启') + self.cap = None + directory = QFileDialog.getExistingDirectory(self, + "选取文件夹", + "./") # 起始路径 + if not directory: + return + self.org_path = directory + img_suffix = ['jpg','png','jpeg','bmp'] + for file_name in os.listdir(directory): + full_path = os.path.join(directory,file_name) + if os.path.isfile(full_path) and file_name.split('.')[-1].lower() in img_suffix: + # self.ui.comboBox.setDisabled(False) + img_path = full_path + self.org_img = tools.img_cvread(img_path) + # 目标检测 + t1 = time.time() + self.results = self.model(img_path)[0] + t2 = time.time() + take_time_str = '{:.3f} s'.format(t2 - t1) + self.ui.time_lb.setText(take_time_str) + + location_list = self.results.boxes.xyxy.tolist() + self.location_list = [list(map(int, e)) for e in location_list] + cls_list = self.results.boxes.cls.tolist() + self.cls_list = [int(i) for i in cls_list] + self.conf_list = self.results.boxes.conf.tolist() + self.conf_list = ['%.2f %%' % (each * 100) for each in self.conf_list] + + now_img = self.results.plot() + + self.draw_img = now_img + # 获取缩放后的图片尺寸 + self.img_width, self.img_height = self.get_resize_size(now_img) + resize_cvimg = cv2.resize(now_img, (self.img_width, self.img_height)) + pix_img = tools.cvimg_to_qpiximg(resize_cvimg) + self.ui.label_show.setPixmap(pix_img) + self.ui.label_show.setAlignment(Qt.AlignCenter) + # 设置路径显示 + self.ui.PiclineEdit.setText(img_path) + + # 目标数目 + target_nums = len(self.cls_list) + self.ui.label_nums.setText(str(target_nums)) + + # 设置目标选择下拉框 + choose_list = ['全部'] + target_names = [Config.names[id] + '_' + str(index) for index, id in enumerate(self.cls_list)] + choose_list = choose_list + target_names + + self.ui.comboBox.clear() + self.ui.comboBox.addItems(choose_list) + + if target_nums >= 1: + self.ui.type_lb.setText(Config.CH_names[self.cls_list[0]]) + self.ui.label_conf.setText(str(self.conf_list[0])) + # 默认显示第一个目标框坐标 + # 设置坐标位置值 + self.ui.label_xmin.setText(str(self.location_list[0][0])) + self.ui.label_ymin.setText(str(self.location_list[0][1])) + self.ui.label_xmax.setText(str(self.location_list[0][2])) + self.ui.label_ymax.setText(str(self.location_list[0][3])) + else: + self.ui.type_lb.setText('') + self.ui.label_conf.setText('') + self.ui.label_xmin.setText('') + self.ui.label_ymin.setText('') + self.ui.label_xmax.setText('') + self.ui.label_ymax.setText('') + + # # 删除表格所有行 + # self.ui.tableWidget.setRowCount(0) + # self.ui.tableWidget.clearContents() + self.tabel_info_show(self.location_list, self.cls_list, self.conf_list, path=img_path) + self.ui.tableWidget.scrollToBottom() + QApplication.processEvents() #刷新页面 + + def draw_rect_and_tabel(self, results, img): + now_img = img.copy() + location_list = results.boxes.xyxy.tolist() + self.location_list = [list(map(int, e)) for e in location_list] + cls_list = results.boxes.cls.tolist() + self.cls_list = [int(i) for i in cls_list] + self.conf_list = results.boxes.conf.tolist() + self.conf_list = ['%.2f %%' % (each * 100) for each in self.conf_list] + + for loacation, type_id, conf in zip(self.location_list, self.cls_list, self.conf_list): + type_id = int(type_id) + color = self.colors(int(type_id), True) + # cv2.rectangle(now_img, (int(x1), int(y1)), (int(x2), int(y2)), colors(int(type_id), True), 3) + now_img = tools.drawRectBox(now_img, loacation, Config.CH_names[type_id], self.fontC, color) + + # 获取缩放后的图片尺寸 + self.img_width, self.img_height = self.get_resize_size(now_img) + resize_cvimg = cv2.resize(now_img, (self.img_width, self.img_height)) + pix_img = tools.cvimg_to_qpiximg(resize_cvimg) + self.ui.label_show.setPixmap(pix_img) + self.ui.label_show.setAlignment(Qt.AlignCenter) + # 设置路径显示 + self.ui.PiclineEdit.setText(self.org_path) + + # 目标数目 + target_nums = len(self.cls_list) + self.ui.label_nums.setText(str(target_nums)) + if target_nums >= 1: + self.ui.type_lb.setText(Config.CH_names[self.cls_list[0]]) + self.ui.label_conf.setText(str(self.conf_list[0])) + self.ui.label_xmin.setText(str(self.location_list[0][0])) + self.ui.label_ymin.setText(str(self.location_list[0][1])) + self.ui.label_xmax.setText(str(self.location_list[0][2])) + self.ui.label_ymax.setText(str(self.location_list[0][3])) + else: + self.ui.type_lb.setText('') + self.ui.label_conf.setText('') + self.ui.label_xmin.setText('') + self.ui.label_ymin.setText('') + self.ui.label_xmax.setText('') + self.ui.label_ymax.setText('') + + # 删除表格所有行 + self.ui.tableWidget.setRowCount(0) + self.ui.tableWidget.clearContents() + self.tabel_info_show(self.location_list, self.cls_list, self.conf_list, path=self.org_path) + return now_img + + def combox_change(self): + com_text = self.ui.comboBox.currentText() + if com_text == '全部': + cur_box = self.location_list + cur_img = self.results.plot() + self.ui.type_lb.setText(Config.CH_names[self.cls_list[0]]) + self.ui.label_conf.setText(str(self.conf_list[0])) + else: + index = int(com_text.split('_')[-1]) + cur_box = [self.location_list[index]] + cur_img = self.results[index].plot() + self.ui.type_lb.setText(Config.CH_names[self.cls_list[index]]) + self.ui.label_conf.setText(str(self.conf_list[index])) + + # 设置坐标位置值 + self.ui.label_xmin.setText(str(cur_box[0][0])) + self.ui.label_ymin.setText(str(cur_box[0][1])) + self.ui.label_xmax.setText(str(cur_box[0][2])) + self.ui.label_ymax.setText(str(cur_box[0][3])) + + resize_cvimg = cv2.resize(cur_img, (self.img_width, self.img_height)) + pix_img = tools.cvimg_to_qpiximg(resize_cvimg) + self.ui.label_show.clear() + self.ui.label_show.setPixmap(pix_img) + self.ui.label_show.setAlignment(Qt.AlignCenter) + + + def get_video_path(self): + file_path, _ = QFileDialog.getOpenFileName(None, '打开视频', './', "Image files (*.avi *.mp4 *.jepg *.png)") + if not file_path: + return None + self.org_path = file_path + self.ui.VideolineEdit.setText(file_path) + return file_path + + def video_start(self): + # 删除表格所有行 + self.ui.tableWidget.setRowCount(0) + self.ui.tableWidget.clearContents() + + # 清空下拉框 + self.ui.comboBox.clear() + + # 定时器开启,每隔一段时间,读取一帧 + self.timer_camera.start(1) + self.timer_camera.timeout.connect(self.open_frame) + + def tabel_info_show(self, locations, clses, confs, path=None): + path = path + for location, cls, conf in zip(locations, clses, confs): + row_count = self.ui.tableWidget.rowCount() # 返回当前行数(尾部) + self.ui.tableWidget.insertRow(row_count) # 尾部插入一行 + item_id = QTableWidgetItem(str(row_count+1)) # 序号 + item_id.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter) # 设置文本居中 + item_path = QTableWidgetItem(str(path)) # 路径 + # item_path.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter) + + item_cls = QTableWidgetItem(str(Config.CH_names[cls])) + item_cls.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter) # 设置文本居中 + + item_conf = QTableWidgetItem(str(conf)) + item_conf.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter) # 设置文本居中 + + item_location = QTableWidgetItem(str(location)) # 目标框位置 + # item_location.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter) # 设置文本居中 + + self.ui.tableWidget.setItem(row_count, 0, item_id) + self.ui.tableWidget.setItem(row_count, 1, item_path) + self.ui.tableWidget.setItem(row_count, 2, item_cls) + self.ui.tableWidget.setItem(row_count, 3, item_conf) + self.ui.tableWidget.setItem(row_count, 4, item_location) + self.ui.tableWidget.scrollToBottom() + + def video_stop(self): + self.cap.release() + self.timer_camera.stop() + # self.timer_info.stop() + + def open_frame(self): + ret, now_img = self.cap.read() + if ret: + # 目标检测 + t1 = time.time() + results = self.model(now_img)[0] + t2 = time.time() + take_time_str = '{:.3f} s'.format(t2 - t1) + self.ui.time_lb.setText(take_time_str) + + location_list = results.boxes.xyxy.tolist() + self.location_list = [list(map(int, e)) for e in location_list] + cls_list = results.boxes.cls.tolist() + self.cls_list = [int(i) for i in cls_list] + self.conf_list = results.boxes.conf.tolist() + self.conf_list = ['%.2f %%' % (each * 100) for each in self.conf_list] + + now_img = results.plot() + + # 获取缩放后的图片尺寸 + self.img_width, self.img_height = self.get_resize_size(now_img) + resize_cvimg = cv2.resize(now_img, (self.img_width, self.img_height)) + pix_img = tools.cvimg_to_qpiximg(resize_cvimg) + self.ui.label_show.setPixmap(pix_img) + self.ui.label_show.setAlignment(Qt.AlignCenter) + + # 目标数目 + target_nums = len(self.cls_list) + self.ui.label_nums.setText(str(target_nums)) + + # 设置目标选择下拉框 + choose_list = ['全部'] + target_names = [Config.names[id] + '_' + str(index) for index, id in enumerate(self.cls_list)] + # object_list = sorted(set(self.cls_list)) + # for each in object_list: + # choose_list.append(Config.CH_names[each]) + choose_list = choose_list + target_names + + self.ui.comboBox.clear() + self.ui.comboBox.addItems(choose_list) + + if target_nums >= 1: + self.ui.type_lb.setText(Config.CH_names[self.cls_list[0]]) + self.ui.label_conf.setText(str(self.conf_list[0])) + # 默认显示第一个目标框坐标 + # 设置坐标位置值 + self.ui.label_xmin.setText(str(self.location_list[0][0])) + self.ui.label_ymin.setText(str(self.location_list[0][1])) + self.ui.label_xmax.setText(str(self.location_list[0][2])) + self.ui.label_ymax.setText(str(self.location_list[0][3])) + else: + self.ui.type_lb.setText('') + self.ui.label_conf.setText('') + self.ui.label_xmin.setText('') + self.ui.label_ymin.setText('') + self.ui.label_xmax.setText('') + self.ui.label_ymax.setText('') + + + # 删除表格所有行 + # self.ui.tableWidget.setRowCount(0) + # self.ui.tableWidget.clearContents() + self.tabel_info_show(self.location_list, self.cls_list, self.conf_list, path=self.org_path) + + else: + self.cap.release() + self.timer_camera.stop() + + def vedio_show(self): + if self.is_camera_open: + self.is_camera_open = False + self.ui.CaplineEdit.setText('摄像头未开启') + + video_path = self.get_video_path() + if not video_path: + return None + self.cap = cv2.VideoCapture(video_path) + self.video_start() + self.ui.comboBox.setDisabled(True) + + def camera_show(self): + self.is_camera_open = not self.is_camera_open + if self.is_camera_open: + self.ui.CaplineEdit.setText('摄像头开启') + self.cap = cv2.VideoCapture(0) + self.video_start() + self.ui.comboBox.setDisabled(True) + else: + self.ui.CaplineEdit.setText('摄像头未开启') + self.ui.label_show.setText('') + if self.cap: + self.cap.release() + cv2.destroyAllWindows() + self.ui.label_show.clear() + + def get_resize_size(self, img): + _img = img.copy() + img_height, img_width , depth= _img.shape + ratio = img_width / img_height + if ratio >= self.show_width / self.show_height: + self.img_width = self.show_width + self.img_height = int(self.img_width / ratio) + else: + self.img_height = self.show_height + self.img_width = int(self.img_height * ratio) + return self.img_width, self.img_height + + def save_detect_video(self): + if self.cap is None and not self.org_path: + QMessageBox.about(self, '提示', '当前没有可保存信息,请先打开图片或视频!') + return + + if self.is_camera_open: + QMessageBox.about(self, '提示', '摄像头视频无法保存!') + return + + if self.cap: + res = QMessageBox.information(self, '提示', '保存视频检测结果可能需要较长时间,请确认是否继续保存?',QMessageBox.Yes | QMessageBox.No , QMessageBox.Yes) + if res == QMessageBox.Yes: + self.video_stop() + com_text = self.ui.comboBox.currentText() + self.btn2Thread_object = btn2Thread(self.org_path, self.model, com_text) + self.btn2Thread_object.start() + self.btn2Thread_object.update_ui_signal.connect(self.update_process_bar) + else: + return + else: + if os.path.isfile(self.org_path): + fileName = os.path.basename(self.org_path) + name , end_name= fileName.rsplit(".",1) + save_name = name + '_detect_result.' + end_name + save_img_path = os.path.join(Config.save_path, save_name) + # 保存图片 + cv2.imwrite(save_img_path, self.draw_img) + QMessageBox.about(self, '提示', '图片保存成功!\n文件路径:{}'.format(save_img_path)) + else: + img_suffix = ['jpg', 'png', 'jpeg', 'bmp'] + for file_name in os.listdir(self.org_path): + full_path = os.path.join(self.org_path, file_name) + if os.path.isfile(full_path) and file_name.split('.')[-1].lower() in img_suffix: + name, end_name = file_name.rsplit(".",1) + save_name = name + '_detect_result.' + end_name + save_img_path = os.path.join(Config.save_path, save_name) + results = self.model(full_path)[0] + now_img = results.plot() + # 保存图片 + cv2.imwrite(save_img_path, now_img) + + QMessageBox.about(self, '提示', '图片保存成功!\n文件路径:{}'.format(Config.save_path)) + + + def update_process_bar(self,cur_num, total): + if cur_num == 1: + self.progress_bar = ProgressBar(self) + self.progress_bar.show() + if cur_num >= total: + self.progress_bar.close() + QMessageBox.about(self, '提示', '视频保存成功!\n文件在{}目录下'.format(Config.save_path)) + return + if self.progress_bar.isVisible() is False: + # 点击取消保存时,终止进程 + self.btn2Thread_object.stop() + return + value = int(cur_num / total *100) + self.progress_bar.setValue(cur_num, total, value) + QApplication.processEvents() + + +class btn2Thread(QThread): + """ + 进行检测后的视频保存 + """ + # 声明一个信号 + update_ui_signal = pyqtSignal(int,int) + + def __init__(self, path, model, com_text): + super(btn2Thread, self).__init__() + self.org_path = path + self.model = model + self.com_text = com_text + # 用于绘制不同颜色矩形框 + self.colors = tools.Colors() + self.is_running = True # 标志位,表示线程是否正在运行 + + def run(self): + # VideoCapture方法是cv2库提供的读取视频方法 + cap = cv2.VideoCapture(self.org_path) + # 设置需要保存视频的格式“xvid” + # 该参数是MPEG-4编码类型,文件名后缀为.avi + fourcc = cv2.VideoWriter_fourcc(*'XVID') + # 设置视频帧频 + fps = cap.get(cv2.CAP_PROP_FPS) + # 设置视频大小 + size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))) + # VideoWriter方法是cv2库提供的保存视频方法 + # 按照设置的格式来out输出 + fileName = os.path.basename(self.org_path) + name, end_name = fileName.split('.') + save_name = name + '_detect_result.avi' + save_video_path = os.path.join(Config.save_path, save_name) + out = cv2.VideoWriter(save_video_path, fourcc, fps, size) + + prop = cv2.CAP_PROP_FRAME_COUNT + total = int(cap.get(prop)) + print("[INFO] 视频总帧数:{}".format(total)) + cur_num = 0 + + # 确定视频打开并循环读取 + while (cap.isOpened() and self.is_running): + cur_num += 1 + print('当前第{}帧,总帧数{}'.format(cur_num, total)) + # 逐帧读取,ret返回布尔值 + # 参数ret为True 或者False,代表有没有读取到图片 + # frame表示截取到一帧的图片 + ret, frame = cap.read() + if ret == True: + # 检测 + results = self.model(frame)[0] + frame = results.plot() + out.write(frame) + self.update_ui_signal.emit(cur_num, total) + else: + break + # 释放资源 + cap.release() + out.release() + + def stop(self): + self.is_running = False + + +if __name__ == "__main__": + app = QApplication(sys.argv) + win = MainWindow() + win.show() + sys.exit(app.exec_()) diff --git a/src/ui/UIProgram/QssLoader.py b/src/ui/UIProgram/QssLoader.py new file mode 100644 index 0000000..6589cd4 --- /dev/null +++ b/src/ui/UIProgram/QssLoader.py @@ -0,0 +1,8 @@ +class QSSLoader: + def __init__(self): + pass + + @staticmethod + def read_qss_file(qss_file_name): + with open(qss_file_name, 'r', encoding='UTF-8') as file: + return file.read() \ No newline at end of file diff --git a/src/ui/UIProgram/UiMain.py b/src/ui/UIProgram/UiMain.py new file mode 100644 index 0000000..79b9aa9 --- /dev/null +++ b/src/ui/UIProgram/UiMain.py @@ -0,0 +1,519 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'UiMain.ui' +# +# Created by: PyQt5 UI code generator 5.15.9 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName("MainWindow") + MainWindow.resize(1250, 830) + MainWindow.setMinimumSize(QtCore.QSize(1250, 830)) + MainWindow.setMaximumSize(QtCore.QSize(1250, 830)) + icon = QtGui.QIcon() + icon.addPixmap(QtGui.QPixmap("C:/Users/pc/Desktop/YOLOv8face/UIProgram/ui_imgs/icons/目标检测.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.setWindowIcon(icon) + self.centralwidget = QtWidgets.QWidget(MainWindow) + self.centralwidget.setObjectName("centralwidget") + self.frame = QtWidgets.QFrame(self.centralwidget) + self.frame.setGeometry(QtCore.QRect(10, 100, 791, 711)) + self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame.setObjectName("frame") + self.frame_2 = QtWidgets.QFrame(self.frame) + self.frame_2.setGeometry(QtCore.QRect(10, 0, 771, 481)) + self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_2.setObjectName("frame_2") + self.label_show = QtWidgets.QLabel(self.frame_2) + self.label_show.setGeometry(QtCore.QRect(0, 0, 770, 480)) + self.label_show.setMinimumSize(QtCore.QSize(770, 480)) + self.label_show.setMaximumSize(QtCore.QSize(770, 480)) + self.label_show.setStyleSheet("border-image: url(C:/Users/pc/Desktop/YOLOv8face/UIProgram/ui_imgs/icons/face.png);") + self.label_show.setText("") + self.label_show.setObjectName("label_show") + self.frame_3 = QtWidgets.QFrame(self.frame) + self.frame_3.setGeometry(QtCore.QRect(10, 480, 771, 221)) + self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_3.setObjectName("frame_3") + self.groupBox_3 = QtWidgets.QGroupBox(self.frame_3) + self.groupBox_3.setGeometry(QtCore.QRect(0, 10, 771, 221)) + font = QtGui.QFont() + font.setFamily("华文楷体") + font.setPointSize(16) + self.groupBox_3.setFont(font) + self.groupBox_3.setObjectName("groupBox_3") + self.tableWidget = QtWidgets.QTableWidget(self.groupBox_3) + self.tableWidget.setGeometry(QtCore.QRect(10, 30, 751, 181)) + font = QtGui.QFont() + font.setFamily("华文楷体") + font.setPointSize(14) + self.tableWidget.setFont(font) + self.tableWidget.setObjectName("tableWidget") + self.tableWidget.setColumnCount(5) + self.tableWidget.setRowCount(0) + item = QtWidgets.QTableWidgetItem() + self.tableWidget.setHorizontalHeaderItem(0, item) + item = QtWidgets.QTableWidgetItem() + self.tableWidget.setHorizontalHeaderItem(1, item) + item = QtWidgets.QTableWidgetItem() + self.tableWidget.setHorizontalHeaderItem(2, item) + item = QtWidgets.QTableWidgetItem() + self.tableWidget.setHorizontalHeaderItem(3, item) + item = QtWidgets.QTableWidgetItem() + self.tableWidget.setHorizontalHeaderItem(4, item) + self.frame_4 = QtWidgets.QFrame(self.centralwidget) + self.frame_4.setGeometry(QtCore.QRect(810, 100, 431, 711)) + self.frame_4.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_4.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_4.setObjectName("frame_4") + self.groupBox = QtWidgets.QGroupBox(self.frame_4) + self.groupBox.setGeometry(QtCore.QRect(0, 0, 431, 171)) + font = QtGui.QFont() + font.setFamily("华文楷体") + font.setPointSize(16) + self.groupBox.setFont(font) + self.groupBox.setObjectName("groupBox") + self.PiclineEdit = QtWidgets.QLineEdit(self.groupBox) + self.PiclineEdit.setGeometry(QtCore.QRect(70, 40, 311, 31)) + self.PiclineEdit.setInputMask("") + self.PiclineEdit.setObjectName("PiclineEdit") + self.VideolineEdit = QtWidgets.QLineEdit(self.groupBox) + self.VideolineEdit.setGeometry(QtCore.QRect(70, 80, 311, 31)) + self.VideolineEdit.setObjectName("VideolineEdit") + self.CapBtn = QtWidgets.QPushButton(self.groupBox) + self.CapBtn.setGeometry(QtCore.QRect(30, 120, 30, 30)) + self.CapBtn.setStyleSheet("border-image: url(C:/Users/pc/Desktop/YOLOv8face/UIProgram/ui_imgs/icons/camera.png);") + self.CapBtn.setText("") + self.CapBtn.setObjectName("CapBtn") + self.PicBtn = QtWidgets.QPushButton(self.groupBox) + self.PicBtn.setGeometry(QtCore.QRect(30, 40, 30, 30)) + self.PicBtn.setStyleSheet("border-image: url(C:/Users/pc/Desktop/YOLOv8face/UIProgram/ui_imgs/icons/img.png);") + self.PicBtn.setText("") + self.PicBtn.setObjectName("PicBtn") + self.VideoBtn = QtWidgets.QPushButton(self.groupBox) + self.VideoBtn.setGeometry(QtCore.QRect(30, 80, 30, 30)) + self.VideoBtn.setStyleSheet("border-image: url(C:/Users/pc/Desktop/YOLOv8face/UIProgram/ui_imgs/icons/video.png);") + self.VideoBtn.setText("") + self.VideoBtn.setObjectName("VideoBtn") + self.CaplineEdit = QtWidgets.QLineEdit(self.groupBox) + self.CaplineEdit.setGeometry(QtCore.QRect(70, 120, 311, 31)) + self.CaplineEdit.setObjectName("CaplineEdit") + self.FilesBtn = QtWidgets.QPushButton(self.groupBox) + self.FilesBtn.setGeometry(QtCore.QRect(390, 40, 30, 30)) + self.FilesBtn.setStyleSheet("border-image: url(C:/Users/pc/Desktop/YOLOv8face/UIProgram/ui_imgs/icons/folder.png);") + self.FilesBtn.setText("") + self.FilesBtn.setObjectName("FilesBtn") + self.groupBox_2 = QtWidgets.QGroupBox(self.frame_4) + self.groupBox_2.setGeometry(QtCore.QRect(0, 180, 431, 371)) + font = QtGui.QFont() + font.setFamily("华文楷体") + font.setPointSize(16) + self.groupBox_2.setFont(font) + self.groupBox_2.setObjectName("groupBox_2") + self.frame_6 = QtWidgets.QFrame(self.groupBox_2) + self.frame_6.setGeometry(QtCore.QRect(0, 190, 431, 171)) + self.frame_6.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_6.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_6.setObjectName("frame_6") + self.label_4 = QtWidgets.QLabel(self.frame_6) + self.label_4.setGeometry(QtCore.QRect(10, 10, 131, 41)) + font = QtGui.QFont() + font.setFamily("华文楷体") + font.setPointSize(16) + self.label_4.setFont(font) + self.label_4.setStyleSheet("") + self.label_4.setObjectName("label_4") + self.layoutWidget = QtWidgets.QWidget(self.frame_6) + self.layoutWidget.setGeometry(QtCore.QRect(20, 60, 161, 37)) + self.layoutWidget.setObjectName("layoutWidget") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.layoutWidget) + self.horizontalLayout.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout.setObjectName("horizontalLayout") + self.label_6 = QtWidgets.QLabel(self.layoutWidget) + font = QtGui.QFont() + font.setFamily("华文楷体") + font.setPointSize(16) + font.setBold(False) + font.setWeight(50) + self.label_6.setFont(font) + self.label_6.setObjectName("label_6") + self.horizontalLayout.addWidget(self.label_6) + self.label_xmin = QtWidgets.QLabel(self.layoutWidget) + palette = QtGui.QPalette() + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) + self.label_xmin.setPalette(palette) + font = QtGui.QFont() + font.setFamily("Arial") + font.setPointSize(16) + font.setBold(True) + font.setWeight(75) + self.label_xmin.setFont(font) + self.label_xmin.setText("") + self.label_xmin.setObjectName("label_xmin") + self.horizontalLayout.addWidget(self.label_xmin) + self.layoutWidget1 = QtWidgets.QWidget(self.frame_6) + self.layoutWidget1.setGeometry(QtCore.QRect(210, 60, 161, 37)) + self.layoutWidget1.setObjectName("layoutWidget1") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.layoutWidget1) + self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.label_8 = QtWidgets.QLabel(self.layoutWidget1) + self.label_8.setObjectName("label_8") + self.horizontalLayout_2.addWidget(self.label_8) + self.label_ymin = QtWidgets.QLabel(self.layoutWidget1) + palette = QtGui.QPalette() + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) + self.label_ymin.setPalette(palette) + font = QtGui.QFont() + font.setFamily("Arial") + font.setPointSize(16) + font.setBold(True) + font.setWeight(75) + self.label_ymin.setFont(font) + self.label_ymin.setText("") + self.label_ymin.setObjectName("label_ymin") + self.horizontalLayout_2.addWidget(self.label_ymin) + self.layoutWidget2 = QtWidgets.QWidget(self.frame_6) + self.layoutWidget2.setGeometry(QtCore.QRect(20, 120, 161, 37)) + self.layoutWidget2.setObjectName("layoutWidget2") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.layoutWidget2) + self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.label_7 = QtWidgets.QLabel(self.layoutWidget2) + self.label_7.setObjectName("label_7") + self.horizontalLayout_3.addWidget(self.label_7) + self.label_xmax = QtWidgets.QLabel(self.layoutWidget2) + palette = QtGui.QPalette() + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) + self.label_xmax.setPalette(palette) + font = QtGui.QFont() + font.setFamily("Arial") + font.setPointSize(16) + font.setBold(True) + font.setWeight(75) + self.label_xmax.setFont(font) + self.label_xmax.setText("") + self.label_xmax.setObjectName("label_xmax") + self.horizontalLayout_3.addWidget(self.label_xmax) + self.layoutWidget3 = QtWidgets.QWidget(self.frame_6) + self.layoutWidget3.setGeometry(QtCore.QRect(210, 120, 161, 37)) + self.layoutWidget3.setObjectName("layoutWidget3") + self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.layoutWidget3) + self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.label_9 = QtWidgets.QLabel(self.layoutWidget3) + self.label_9.setObjectName("label_9") + self.horizontalLayout_4.addWidget(self.label_9) + self.label_ymax = QtWidgets.QLabel(self.layoutWidget3) + palette = QtGui.QPalette() + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) + self.label_ymax.setPalette(palette) + font = QtGui.QFont() + font.setFamily("Arial") + font.setPointSize(16) + font.setBold(True) + font.setWeight(75) + self.label_ymax.setFont(font) + self.label_ymax.setText("") + self.label_ymax.setObjectName("label_ymax") + self.horizontalLayout_4.addWidget(self.label_ymax) + self.layoutWidget4 = QtWidgets.QWidget(self.groupBox_2) + self.layoutWidget4.setGeometry(QtCore.QRect(208, 40, 211, 37)) + self.layoutWidget4.setObjectName("layoutWidget4") + self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.layoutWidget4) + self.horizontalLayout_5.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.label = QtWidgets.QLabel(self.layoutWidget4) + self.label.setObjectName("label") + self.horizontalLayout_5.addWidget(self.label) + self.label_nums = QtWidgets.QLabel(self.layoutWidget4) + palette = QtGui.QPalette() + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush) + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0, 128)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.PlaceholderText, brush) + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush) + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0, 128)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.PlaceholderText, brush) + brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush) + brush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 128)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.PlaceholderText, brush) + self.label_nums.setPalette(palette) + font = QtGui.QFont() + font.setFamily("Arial") + font.setPointSize(16) + font.setBold(True) + font.setWeight(75) + self.label_nums.setFont(font) + self.label_nums.setText("") + self.label_nums.setObjectName("label_nums") + self.horizontalLayout_5.addWidget(self.label_nums) + self.layoutWidget5 = QtWidgets.QWidget(self.groupBox_2) + self.layoutWidget5.setGeometry(QtCore.QRect(10, 90, 291, 38)) + self.layoutWidget5.setObjectName("layoutWidget5") + self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.layoutWidget5) + self.horizontalLayout_6.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_6.setObjectName("horizontalLayout_6") + self.label_5 = QtWidgets.QLabel(self.layoutWidget5) + self.label_5.setObjectName("label_5") + self.horizontalLayout_6.addWidget(self.label_5) + self.comboBox = QtWidgets.QComboBox(self.layoutWidget5) + self.comboBox.setObjectName("comboBox") + self.horizontalLayout_6.addWidget(self.comboBox) + self.layoutWidget_2 = QtWidgets.QWidget(self.groupBox_2) + self.layoutWidget_2.setGeometry(QtCore.QRect(10, 40, 171, 37)) + self.layoutWidget_2.setObjectName("layoutWidget_2") + self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.layoutWidget_2) + self.horizontalLayout_7.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_7.setObjectName("horizontalLayout_7") + self.label_10 = QtWidgets.QLabel(self.layoutWidget_2) + self.label_10.setObjectName("label_10") + self.horizontalLayout_7.addWidget(self.label_10) + self.time_lb = QtWidgets.QLabel(self.layoutWidget_2) + palette = QtGui.QPalette() + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush) + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0, 128)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.PlaceholderText, brush) + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush) + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0, 128)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.PlaceholderText, brush) + brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush) + brush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 128)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.PlaceholderText, brush) + self.time_lb.setPalette(palette) + font = QtGui.QFont() + font.setFamily("Arial") + font.setPointSize(16) + font.setBold(True) + font.setWeight(75) + self.time_lb.setFont(font) + self.time_lb.setText("") + self.time_lb.setObjectName("time_lb") + self.horizontalLayout_7.addWidget(self.time_lb) + self.layoutWidget6 = QtWidgets.QWidget(self.groupBox_2) + self.layoutWidget6.setGeometry(QtCore.QRect(210, 140, 191, 41)) + self.layoutWidget6.setObjectName("layoutWidget6") + self.horizontalLayout_8 = QtWidgets.QHBoxLayout(self.layoutWidget6) + self.horizontalLayout_8.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_8.setObjectName("horizontalLayout_8") + self.label_11 = QtWidgets.QLabel(self.layoutWidget6) + self.label_11.setObjectName("label_11") + self.horizontalLayout_8.addWidget(self.label_11) + self.label_conf = QtWidgets.QLabel(self.layoutWidget6) + palette = QtGui.QPalette() + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) + self.label_conf.setPalette(palette) + font = QtGui.QFont() + font.setFamily("Arial") + font.setPointSize(16) + font.setBold(True) + font.setWeight(75) + self.label_conf.setFont(font) + self.label_conf.setText("") + self.label_conf.setObjectName("label_conf") + self.horizontalLayout_8.addWidget(self.label_conf) + self.layoutWidget_3 = QtWidgets.QWidget(self.groupBox_2) + self.layoutWidget_3.setGeometry(QtCore.QRect(10, 140, 191, 41)) + self.layoutWidget_3.setObjectName("layoutWidget_3") + self.horizontalLayout_9 = QtWidgets.QHBoxLayout(self.layoutWidget_3) + self.horizontalLayout_9.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_9.setObjectName("horizontalLayout_9") + self.label_13 = QtWidgets.QLabel(self.layoutWidget_3) + self.label_13.setMaximumSize(QtCore.QSize(60, 16777215)) + self.label_13.setObjectName("label_13") + self.horizontalLayout_9.addWidget(self.label_13) + self.type_lb = QtWidgets.QLabel(self.layoutWidget_3) + palette = QtGui.QPalette() + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) + brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) + self.type_lb.setPalette(palette) + font = QtGui.QFont() + font.setFamily("Arial") + font.setPointSize(16) + font.setBold(True) + font.setWeight(75) + self.type_lb.setFont(font) + self.type_lb.setText("") + self.type_lb.setObjectName("type_lb") + self.horizontalLayout_9.addWidget(self.type_lb) + self.groupBox_4 = QtWidgets.QGroupBox(self.frame_4) + self.groupBox_4.setGeometry(QtCore.QRect(0, 560, 431, 141)) + font = QtGui.QFont() + font.setFamily("华文楷体") + font.setPointSize(16) + self.groupBox_4.setFont(font) + self.groupBox_4.setObjectName("groupBox_4") + self.SaveBtn = QtWidgets.QPushButton(self.groupBox_4) + self.SaveBtn.setGeometry(QtCore.QRect(30, 50, 151, 51)) + icon1 = QtGui.QIcon() + icon1.addPixmap(QtGui.QPixmap(":/icons/ui_imgs/icons/保存.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.SaveBtn.setIcon(icon1) + self.SaveBtn.setIconSize(QtCore.QSize(30, 30)) + self.SaveBtn.setObjectName("SaveBtn") + self.ExitBtn = QtWidgets.QPushButton(self.groupBox_4) + self.ExitBtn.setGeometry(QtCore.QRect(250, 50, 151, 51)) + icon2 = QtGui.QIcon() + icon2.addPixmap(QtGui.QPixmap(":/icons/ui_imgs/icons/退出.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.ExitBtn.setIcon(icon2) + self.ExitBtn.setIconSize(QtCore.QSize(30, 30)) + self.ExitBtn.setObjectName("ExitBtn") + self.frame_5 = QtWidgets.QFrame(self.centralwidget) + self.frame_5.setGeometry(QtCore.QRect(10, 10, 1231, 91)) + self.frame_5.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_5.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_5.setObjectName("frame_5") + self.label_3 = QtWidgets.QLabel(self.frame_5) + self.label_3.setGeometry(QtCore.QRect(240, 0, 811, 51)) + font = QtGui.QFont() + font.setFamily("华文楷体") + font.setPointSize(30) + self.label_3.setFont(font) + self.label_3.setObjectName("label_3") + self.label_2 = QtWidgets.QLabel(self.frame_5) + self.label_2.setGeometry(QtCore.QRect(20, 60, 311, 21)) + font = QtGui.QFont() + font.setFamily("华文楷体") + font.setPointSize(14) + font.setUnderline(True) + self.label_2.setFont(font) + self.label_2.setObjectName("label_2") + self.label_12 = QtWidgets.QLabel(self.frame_5) + self.label_12.setGeometry(QtCore.QRect(1070, 60, 131, 21)) + font = QtGui.QFont() + font.setFamily("华文楷体") + font.setPointSize(14) + font.setUnderline(True) + self.label_12.setFont(font) + self.label_12.setObjectName("label_12") + MainWindow.setCentralWidget(self.centralwidget) + self.statusbar = QtWidgets.QStatusBar(MainWindow) + self.statusbar.setObjectName("statusbar") + MainWindow.setStatusBar(self.statusbar) + + self.retranslateUi(MainWindow) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + _translate = QtCore.QCoreApplication.translate + MainWindow.setWindowTitle(_translate("MainWindow", "基于YOLOv8的人脸检测系统")) + self.groupBox_3.setTitle(_translate("MainWindow", "检测结果与位置信息")) + item = self.tableWidget.horizontalHeaderItem(0) + item.setText(_translate("MainWindow", "序号")) + item = self.tableWidget.horizontalHeaderItem(1) + item.setText(_translate("MainWindow", "文件路径")) + item = self.tableWidget.horizontalHeaderItem(2) + item.setText(_translate("MainWindow", "类别")) + item = self.tableWidget.horizontalHeaderItem(3) + item.setText(_translate("MainWindow", "置信度")) + item = self.tableWidget.horizontalHeaderItem(4) + item.setText(_translate("MainWindow", "坐标位置")) + self.groupBox.setTitle(_translate("MainWindow", "文件导入")) + self.PiclineEdit.setPlaceholderText(_translate("MainWindow", "请选择图片文件")) + self.VideolineEdit.setPlaceholderText(_translate("MainWindow", "请选择视频文件")) + self.CaplineEdit.setPlaceholderText(_translate("MainWindow", "摄像头未开启")) + self.groupBox_2.setTitle(_translate("MainWindow", "检测结果")) + self.label_4.setText(_translate("MainWindow", "
目标位置:
")) + self.label_6.setText(_translate("MainWindow", "xmin:
")) + self.label_8.setText(_translate("MainWindow", "ymin:
")) + self.label_7.setText(_translate("MainWindow", "xmax:
")) + self.label_9.setText(_translate("MainWindow", "ymax:
")) + self.label.setText(_translate("MainWindow", "目标数目:
")) + self.label_5.setText(_translate("MainWindow", "目标选择:
")) + self.label_10.setText(_translate("MainWindow", "用时:
")) + self.label_11.setText(_translate("MainWindow", "置信度:
")) + self.label_13.setText(_translate("MainWindow", "类型:
")) + self.groupBox_4.setTitle(_translate("MainWindow", "操作")) + self.SaveBtn.setText(_translate("MainWindow", "保存")) + self.ExitBtn.setText(_translate("MainWindow", "退出")) + self.label_3.setText(_translate("MainWindow", "基于YOLOv8的人脸检测系统")) diff --git a/src/ui/UIProgram/UiMain.ui b/src/ui/UIProgram/UiMain.ui new file mode 100644 index 0000000..e57ed70 --- /dev/null +++ b/src/ui/UIProgram/UiMain.ui @@ -0,0 +1,1226 @@ + +w3AwA$LIZd z;uCoPJF3f)U1z%`{TLGS>ud(U#ANccdP$#ZVs9$GB;h?$(@e+AtP|^OL#N-!I(uRj zL=FvQ5;?@9mUDg2Bz~xBegg!e$(N&hJdzm%Cuiaef`dw&L2yvqyyB73cuaAf!7nkH z;(BTsL^pW^@D!lBEK|xLvg2eB91TueeXNYJG6)7M!9xb&B6&c@TU3{2(isE?%kh4a zXeX6H#OJ+-_ypenf$Flfrt)`an$=VE_XH%TG4ONposNLwwDOYVkZL@BiOJ;2u`-nS zn(8G=6B&x3i4=CW6U-nc&8D`?F_EE=lR`O>p`bFNGL&CpTjb}F%us$ADI-m?` wQeBoQWhlAo zS@;#<7e>E-V~TL=B@L>XR=2T!`E9I!jf#^fai+>aaTYyCdW^_K4wF2x6n0>+5 kB(6>XpH|a&U2EC|1ZvSR5*LRLi&!FQ(~>z z7_0;j_Butj0bTx2s>?DZd%X(3pnM_0oU&fhpqgn;NquggMY4$z#z~ZTZs(vlJ6x2s zOyedsJDeshfE|8Kby=ol2mI~$#p)l79yg}=xL(qr+PK)k{Ff#(tX~msS*qq=*X3nS zY$;AtoTXkHM@yY08NgD%p}H(nvefHfsVD!9Sc;Q5v86aD&QfnkOSPq0|5fUhYM}Kv zGf+fC{67REOPImZhyp~v@bB^i*8eMeQH^~%_$I+agh{jhKk6$>9+wHqV*Rb`O*P3E z$dFB~ThpvmHI>jBI%jNZG)Y!!IclkTYfoVEZkxlk-{I=&Ipz4rOpC>_4#4`*Sj}r{ z+uU}|UEAAPyUFf;-qX`td*G>EPn~Q$V(YZmwry|GdX8$g?%F;_yQBN4yVlX!<8s&D z`@xUzUV8QJzdL{T&tI$QbsY^%>9o5%n$3C2(RI}B2~Gyo!7jKs3W1X2zd)WF$T|Xe z>>8%Ljtp%5Z(#R8j%aPKccf#}FQMtI+R>wR*|lm%x9zBXO=+LztW1$jlmXeRS{twg zCOd5%c4xc$SkI~8-vbjwdU; U8=Qu>Cm+>%`g%9^oNiwp zL{D@4Gq4`~bEs*U& aS-JTf-IIGDB9v!jA9L%BwZ2wQ)mw; zggv+g`&MG#RnRSnfATqy+v4bSI$ZY6T@FvM1zV= nh 2ZR463HzN zr`-)CgP)-Z-Dqj)IrYIW(0CyyUm5%kd<$Y)8ptucaYb+jHsO9u@Dse?Uz!f&Ic;Zp z`aFhj1*RSA(Hv)cTppWqmuTM-#N2{VtPEll31n^195(0P;7 W~s zE(=VLM%i9Z=o$(53;;*M)iZF*32qg^o$j`sj)Yszz^x#-)dY72;DR@S*`Pj(;}r~s zhCr6kVemY54@vCm>vjj9fd e1j8ShOdFg~Jg6| N} zPoKNPrd54AFvV^6Jk@dB-s#x`F)EO)+1-w__P|tV-tBNXy8F6S_^x5V4P>=q-MD8v z9lnQg818Kc `*^DdmCw8!uZ3N9ekV|KeIkON=$+E075$MNQ*)~%t*NfWBfYTW|y0W@d# zY_WAaoM!@gP;KdPxI9872rYW#weFR(mR5wgP?gO+&c1F}b59>2L6NLIr;IPt%>B1} z?A?JvxV qZTDf)cdRqXiT|D+~}w zZ}kN7RG56hh|p7WiF={m8#+CXllH)5!)ee&0cE?(X0$4s9B$NiS70(=3sKTG0AXz- zUYhZ;2``)Rf~kOpX_>YSFWd3511}iVwOx3@zb2t!MxfzeG|*JI1TqEH{1zvqJIBQ2 zBs^swcEDeL)Skv(lRz#bwrK~j5u>DrBUL+u7yM}HitF&tfZzZWkWUOd I~4=|Er3=?&RFt3#MR3wtaJh@##-34luJ6DaFib4X^!hr*fhp*9C* z*EPLogf9Aefv#@})A}uatU~(o4lYrAB<4 a z?u$1Uxb(sv--(m{6X(1q&cQNDOWTzGzl`EH7R#3Oo$1iHCA}3Ju@K+djBjn}&}GuT zbjj@upR({)$wGfg%}7a2|5?3c&4o;#G8<_6mDyfpwqL3ADwX~7e9G!u1#|rc3q}eS zT KZ1gT{)C*Q$$b5Y=@;CY7WWO@ktIYlA AI zndL8A<}F+1FMGmU_JmJa7rra>Q{^wO_m 5*`IXiF`OCfYm;2{G>7D6O1BCu?^y6f_;p~r?c47rD!^@{aAWka~bLa(y$%E_zeE}t7}9)4V3M2Zm5 zac?g0DhqBde8H!j3nQE7Rpwnv_bKzkE!gRj)2A#Si?ZemKFf&DaaLCK$n5I=u0iL3 zQ=h#ywz4)3XAG-)#Ri|Uar6*)`}e?GK}f$M##XscDG7@#lmM=~AlxFAFsH&lXW7V{ zWkVI$YCo;j=WIkDFA|7~yh@Q@sqiWlSN2^!botOw`B2C3{9(7gpxLKvN|pt`V&D-@ zibKkT8?AZiMW51OYFp%07WJq3l*Oht O+b`C8UMlM4mg940kJ3hm*sLWrqWTa?G|E9rR1H1Gh z3{X>$#*~Xw{E8_8p9sZ+~GsmmUc^@R27jD5$mnwbAl3Qb-HhsuCJY6qs@+nV5Ai7z8 z(x;pXH^rldzEC| 1PFtofVy2nuQ&!z7t@4*PjFdJEb@^9r^{(8imu^FRID`5X^bWrgnqW2zofs}N z(jL0A#H%d1xm3hTsV9HsYH#Igy%2*&-dGgzcAHO`gDQZu_HE5bHx1!qC _wwG&`>5^XLmwXMpWhGB zUoTmqPiwf4^`$aJWY;I(JM+#Ne_^$^uv#SWkj3Gg{!zilb3d5tpH<_XRr6WawW*&@ z_1A6p)@}bqgHLI_f3$VpS#_T+xK{INjlX`Uw|?g@Kr?DITK7=1Uec&fTb(qwELv2! z7>Xi`U4;R8)FR{UQ%2;D%CNvy-v+nEWkH0^VvOuK3F&An!ie`NjdBg*89X;|PA`FI z9k~uM&1=oW(}&d?<@%z{K4pu*7(K6*FY%YJ8Yy2joat}e;ceWZm+wS;I4K#^nqR5+ zD)mFlhHS%+4MQS=%MiL#?NzF8)`$>ic6KhU2`>mt;8k9ws=s1z>A+GPc5 rk3r zQm;>2o^*m}PG_6Fb xf`q!-~1fZX>@ESPznx7J&^RxiZe!o072 z4 EgEyEi4nslV!5#cHr}yZY-NgFpB$f3dEeVg0^R7XK+$6LDWy1lh(3w8 zU&4>JJ%b5j`Pa8JG6$@+-m10H4<`}_tch) eW)|_VOtz^!2Vk9SeDm)J-+g!^>%;KSaOp_l(*C`J z?E~$4A*OunL&M1Db?_u8_ubs@PBB(6@BrhZtdFOBIOXQTZF S?JjS-%ct~&ryVg7!Mawwa3d@f@zznfUe@4KR))KWXDRVEPEtH~ z!UH`wJk}KtI?=tpS)Ps8trEW3ftv0jt|P?1{}--g(7@+@aURch!b6?$eLO23#wJZa z(%nWsVPoH63O#SD2)#EEBLR|*Bom0i;(=nlXl2BD$Ml|y2i9Sa4|nM0__7U?m?guF ze1D*eed|TMO(;^9P5z3N-inp@+-p|3e^&L#tm^*b`Ye14XDa#wJnuDLwz_oCrz{h2 zB5TaNI`tEHNL~9&TuI`7^!u TS&=Fj>0N;j|aPMt|DU;Y@#;n$Di-#{)xAAMW>}LO3#5 z9C=X);Hwp1DUJH5nRLR;g{Nm9i@FV8LsYWvi%NEqRC4Z%O8A_70$C>A7nR9L%949u zRPvIfGKHlweY73pc+gZ9#|#EX;pn!If8?_`@W?>a#~K^QG#1C~C zXK|E95rnUCaLizFl#dBV0gIzzOgLt;IPhdf)F+NCg)9y{ z%Mta7gQJMWfu}&CK5=mHzoLTYN1{G)aLi`;z~d)TpEx+?usHDaO4KI~j$#%Ep7x9S z#2Nb~ERGdX2;gfRKIXDGR*nhBJQfF@;feah;e(k?;Y4%k9&w u(wd zGwyx(^6l%_fA#XPaWMJbfBgL3=O6dYfnK48&%b;3hacS@e)IOv-njR(AK(7@CwE^O z6bF*~FfF)q{jEE1UDGf+i6g;q9{Bd>Kl# 2PtRWWB>)xlI-?{Lo8pfYKJRxEr zx^w+cv=Rcm^G9#P>1cz93DcdypWgZXKkmZ=TfZ8-7Ce9P?rQ^ge(=S;i?14#BJcd_ z>MOy^?}YAP^uPPg%Xhx>)}1S#-TmlCcYb>Q&f9|qZgB|vo)E3?Iq27P%+u{$*K`a{ zX4S51>gee@v#zOkU6Z@l<|=jLQM4z@OYsa$^(k>8YR$^Jy0zu&j1%1k&;R_>51VSS z|GK7HfUGre)C#<3_ojv)kD{)LiM0>UDy4=PkEzCE_&!kMN!AC18V|e1MSZ`Py!-tj zFzEv&VR{5_s?|HM8FPUjNAHEhBIR>1&-+klu z&pr}S#W;N{s>Z3>suJT&>ohpEr`b33!fEzSo5z7iSi>ja#L>;rxkHD?X*bS-;4W z;w$EAff@3sx9PCv>u^gP)-+CN;t|T| ^=Fjuzukhxt7;4q?R~cvNU~&D 49iFPs+v-!cf&6rM0AJA_ z*fDhO=H^5C(r10jbK;)yau>eQI&gfr_~zE<^qP>~M#CM@mp OeXy$>%;J4i+ASgN00&r$m<)(WRB|(ki-GMHh7(yNGj%sDlsI zTyg@t4f~N$@za9P0iMukiNYHo9~|#51}u$x5z9PznlfY^e2bpC2txDBgp$A#;mX66 zdRgdg{z$bC9fOys%!d|nKN9T`^Ty4U2lSF>{#H4t{RND{swa&D+TvKY7|EDh8|Srg z)nN>A%-O}!ZgEK7IAJ^$+i;6Q99lOHi1*^xI=qzPMT8d2h>U1~=edoO(Oa;#11~Lj z*^d_t_{QmEaU59$9&vVA#2h?PY#dScU=72Kaco?~CK0(r&=TQGM6OQkqT&U2NsKes zcqrUBX}t++jd&5~wZ#GL?f6w3!4`+B593#Hj=BqLcwkwasW%Q&ABC@bs&WEKd%Ft` zBe%B)CbzeD_jL6+v7Xo7exlFj4Bg3ZZ$IMD+#Wm|?doZ7*KQy#5dsU^+wlhx9G&fO z_*`>z^m**=_VxjbFpd!_aXU)G3u@er8h^#|zti{SWUcv^-l?TohtiC`*keysb|9 Cs0kliDGW 6#@SL0T_e?XaE2J literal 0 HcmV?d00001 diff --git a/src/ui/UIProgram/__pycache__/UiMain.cpython-39.pyc b/src/ui/UIProgram/__pycache__/UiMain.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..09200b59fe1efb65ba79b1ccbfd3f909f0c23e79 GIT binary patch literal 13367 zcmeHOYjjlCb)L~YG t-H+d(E05Ep%GZqUW?I zi%pG?XzpJHDn5LB@J&2e=WwK)X;__cI;jRY=E{`udYR!$yT!9?^%PPJZ@N6=xK@@b zOZ!l-VD605@J^IZRPwSagWdzPI#ovUMoqdl1wAQ8Xhq5~u>x8>l3qv8yk#Y7E7SGR z^BnWCa^_ v=VQUSmBwSS8h=i4a$E#I>lcwGgXVHLJ 0_iJ5x1FN^{ z4)&bXnD4_zplr1IP=`J=SQ chrGeb|UTaF4+&&l3*s!zR==S$**45fR7Dh^Z^( zO25EXbE{nG7g^57o6=iSE@|r~Aj2cv-`^lSj=UAMt(L8gY#m!KY<&pw28p)ShP)NX zu# Y &N{PMjzuh0L(A_R|x7u{K0%@N_%I8QM zklG|t72A&-IgoL4uBCIN&6Xo=K<<#pl+UmibMao(_FBjX^V!Ggg){EnMftoJh@BFV z=EuDpu^qK`iRi^Feuy2;xH;F-wzk`BZHISqb7DKRbV)6>mX>{}?UP!%Sr0qHjtVWD z?qJ8H#D03_b{# I))a<7(@^J9$qm(+L4E{9%prBA2Cs%?+uDd~&cIzj$9Eop~Xuk=Hg z%|BhXjPHW4`XrC=RdKX?p}SW`yMIx%dm$endCdP5ZRkT@_o3ET6zx9no{_v1ZNb}* zT0dF_q!oQUV*N#YfoCvcfn`K2V2fD57O?<)HCW)Qod5IV^9+1?#u}ggg7J9<@ 3Oi(d*yqrPe<-oN+&L z dR KgprED{jROU| z 6mbFdnCEKV~A%8_mkhLne zb`-VIB5Oy%8 7I)Z450DYT HBTP3w7q17j~Cey`QlhArYYNdNK@up%D zwMlC%c-c+%cE&AHCKufUPcFJQn*`!J5|L&ij0Jda3biSTcnfpMyEgBYx|45|+NNxA znF8{AMaa`Yo|edTSGJA)QO3==N=JMHwITL1@)n1r^Rb_Xj`z8=IB5&(XQ5+O>i8~n z9QxWiW^FoVq2o5U!kPXykl}N_=S#^qNY_BS2A&Tj&v)pV*B$9MhzH!RiR ;A5jxmj9A=%zVB4uWc#QxqWXtU z_Uo}RU5WUUT1bnGCH&e*ESm5y{ODKn>09%Eaee;R@9&I9$IO}$HEQTec#6Np%T@w9 z%TQ=*ph^2jyoobCqrg#hCsAEQ{ZCZQa!w63Yh^_G50GXDhGRNY^&MJ78B_OfPU_)T zp3qF{1DV%!z;u|EVP#kihZ5tlsqDYQh@9${WHp}VZhtWUr?=*R_UZl4Kg!lobLE&G zOUAon)1j8^^JMhz(2MM^QOnj+dzGOKhgI>~GV38SbuCLT9kb|*BMV16v~AR_JGP$g z$^H^_)0acf9wT0Qi>mDfTXqw*R`qKmVJ)g2Wtx%gCrZs(jj1t JdAd?jwy zjmLCtHWoFM@F`9|mTe}kasknn{R&S(PnWJK;lb>y)Fg9#I-*6h|3ZWsJK}D$elcXI zIS1FC6P|%^p YbhbOCnvWrCpQDR>_5ZU?7tRSyr%?0tLfnm z$X+LQ+2d$3lE?-@(6-QEdZ`GhwFFXI&X!iwHxi2s$1v#4TD!;Ko?@5nHGLuiyLXx8 zh89sn;o RY;29EKCjMlhd73?^!#v-br z&p^i+*cl{~Im^Jf5?6y&1IA2PW&KK24RhOaZTN{w(0fMF5-QWH1oA0bqVyV4N+?`% zU|dxVvmB3u>a?M+AkK=wak)6@E9u!2IEMKlSV5YVh!&m+R-@V<)1n5sgiCXd>cC)r z)zT>p+@zjZI2nod#FA0Nq%NI_O^Js(JO4>TjRe=A`Ghqgolq6bh18(02bjK5Sa(XU zUHS|3Otzei#*@ZrC2>XHLZqrde=;%Noiq$MndUs5hN}KD6|@%WG)d~)sn|iqE-G44 zK=K5Jr w?~YwnkGsx~$b7a;*;G!GDuFVL@q zRl`sb*KQp);V--q(@h_wc>v6^fDx=7z~YM_f>VzMsZDZsjTqXb8mtsaLm>+KPDT|@ zHGN041o@kpm5`8{^n*~WcT#bPio;ZNQPE9B4;4qKI7$U=4|Lk9=_jb5>0LiX#c3+~ zP?&D6bwz&|+nsT~IPpw5Lkt5{45C2J^vJnQA0pyeD$Y^y8WrcMxJbn%Dqg1|M8#z) z6e@ #}~8NOd6fh>fF&Nw6|7 zzz2V~qU(B2$|9LHItH2&O@tLg9nz2sr&U7{(?hTx%A**61L2sF=$@hJqN&1kC)Dt$ z?j v zp*e>mD9^s^>Y~0sjPkfXc|2b|Op84hg6DDdK3Oa%zbUp~N4hZUXcSfRaY7kV_>>=0 zi)He;C8YAtBD<^0DxI^d3Vu1d6Y~;{ Vmc! ztF1y>S8Gu!(^cH26&9shQtB*9jiju!D76x&-lD9KeS6NL)JaN%MOi5+t1L>rq^!0m z&q>M}i_#z|Yc0wuNolkwt0iTfMOh;$>n+M!N!egg8f7mwT9kE?=Xr~=UQ#w$lns(n zCMf)-WpgiIXp*$)nfvM8`*%MOE5^bPZ{ELq_rcBIiVKs4f4H}B@25%HFG<3^kLG{! z@%`U^aR2k$3!ne${+F5gH}CL^k|Zr$b9X `}?AI|;dC-WcwV(zo+bKkoou=(ZC z0`FRqb`u@rMkL(XF^(Ohzq4aF#%4M@;+-9dxDwr*pe^#j7dO+|ykm;*)b_XS+I8T? zPI1#DZ2sM6KkV=me`kjul74~V=eV*5|M|y!RuQ)XyedxnO&j@H+pNQBLRY)uxMdqr3=JFW3TtO>(&=2DhcqLs ziZd#mnFjeIKXx|cub^y)$Qh{The&a9q@&&9W6c&~;b%mCJme?CcB1ja6s^wUxWvy# zbn+4B8-AeSCm8GSqVr=4olu(G`VHdb=Y-0T)f4?~qS7%y6z@{)Effn*Yyu9W;=n$n zj_-JBPha?@o&Tdgv+E0Y9t8)S-X@Rf3x%RM%7j8@WhfMhv1FL))uGVUq!Jb_`g^d0 zn`JYV8_n&dO$*&vC+Nn)=k&edpw9)J=)L$~GoJpLfYHjss=GiFmmc02zjfhUrC?28 Rhp?uT?k*D84>=lK{|lPVmd5}9 literal 0 HcmV?d00001 diff --git a/src/ui/UIProgram/__pycache__/__init__.cpython-313.pyc b/src/ui/UIProgram/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9c5cf3e06745d6e0f8659d1aa0d3135d154c1702 GIT binary patch literal 132 zcmey&%ge<81T6P%rGn_kAOZ#$p^VQgK*m&tbOudEzm*I{OhDdekkl>Z6swp>e;@xc zi?qb#)R<7ufTH~LqQu;o`1s7c%#!$cy@JYH95%W6DWy57c15f}Js>lSL5z>gjEsy$ H%s>_Z>dYL% literal 0 HcmV?d00001 diff --git a/src/ui/UIProgram/__pycache__/__init__.cpython-39.pyc b/src/ui/UIProgram/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..be6f8a96f10cde88d2c80ebf23ab841a6a45c8fe GIT binary patch literal 159 zcmYe~<>g`k0+xHXQbF`%5P=LBfgA@QE@lA|DGb33nv8xc8Hzx{2;!HEvsFxJacWU< zOhIytOKNd;Nq#|0q`!}UnMFowPHt+65ehFR)H9$cKfNe1HzqzlGcU6wK3=b&@)n0p RZhlH>PO2Tq^v^)d006E{Cl&wz literal 0 HcmV?d00001 diff --git a/src/ui/UIProgram/__pycache__/precess_bar.cpython-313.pyc b/src/ui/UIProgram/__pycache__/precess_bar.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0213987dea6e378a6a246498d05af019f578a903 GIT binary patch literal 3201 zcmai0T}&HC5Z?3e+St%E&;T*9p# <^#BB)uMJN2T=9!HyVCImBMB!u9D-faAL`=PAV(zsNORtq! zdu_z#L)EAOiKbd4nn#5Wb557o!xq1Folg8V-9FG0k)!djZW}lyk1J8#HE@Q+!$eWl zZkgz117{NI#qNZr#bYoz+a14lO1>UXXfXM(FbU=?=f?aoXrmM6W8mZ{B7%sBNfd}# zv<1*Xfx2`FUlNE#G}j_x6)iB@L@Tie&|!h#M&!5aWkr6hLmp7jRCEkY1U+fPXF=$Q zFo#A8n kDpc8(%Nsp(S7$+|Bn5Dq_PfNR-Y-gCWm3Lu;hDu$E_H)_`@; z&sPl^DAY9Ed})c|TP`h8sBu<3`wZ)x3l!>@NtEz?a6gwd=wPeCa}MgDjq?UIA`c_K zqdzhRb-5mb{X{hkFCN@n|L&{olW$jln1Au)o7JDc&px@o_Qj(FeF>|-&aTefUVZ$a zb#3YwAZv3!cD1#(CFr{@R_P)XGZHSUa_8%{pQdx0>+}WqYjmrcm{bU%Z%@aP6p2MN zNz!cqt&tmwUal(Ia3mIrUmc2QQAIatgaDL*=ul)b2gQyPimWk~P`J}8=)4FObtl;9 z1G^K6i5xFqV?2iSvvM?{5DE;sLk@+8BcZUO5sIU_D=5c;N;Hq^PS_PSqG-X3grX1= z&x5=J4CPsSFd7M7RzkWx7>~u2pr+$^>^L(7U~N&A=mp(2DHA28=?)eGYZJ~~42*Y; zvpy2dH4s~#IwUC=l~q-eRC>IReN%c AWBZmC?XQEO2>Zbdo4R=uXnO zOj;(d6Z&xV%A%~a@KjT4>X&dCucy#+?7nq*{$LXOmzvVJ{ZH(=Q#Mm}_xSwwG_G60 zt_ zlZ~L?*jXlhsCy6~7+?>SCOF|m&-MnT_ wJ&oVXdYYHY zA6rtM!_=Xg?2d-n&!=50xH5yiN$kA`9yPGpt|W#SGv2nOw+-@=-R7CCo3^ds@(iv{ z;_CU@G;TCzHEH~=G4rHx6NGT5e5U;Fl{DVP!l_B(nhdT_;`$8s({wjJI`HtoGu*iW zw}FDR!udyQleO@tz|7Is#CMA5Ape~xS_4V`A5^p|3M2H!*=Mx;127j&bS&B}z!zQT zK*1@4qe4Sv=GaiG{TD+ez>K+nOZ aeDc3YY+qG_1;qAWz9HAZ6 zZy^*60X{UDXu4U6g>*cb|0h#v0_h7O6u6oEo5jyx{$AKt`(T(t^p4y!?hLL=;=1|J zVt66E+|=__{k`M28_A}D<)PtZ({TFS`Q b&?2w-O5EZ~TW* z1Z0=k2n@SKihi3u-pPF^j2;U8enGbeqj6R7oARM5R{%CtYKuo!5B!^vakOcH9hLry z@sV1TJnN%9M14;-n|JRHqk z6Kw&k4^a43Y5#eB6TLF|tcU(SA(*UfudraPdWm3QfiTg2Kh`VGTp!RnS_Ys|Q1n&_ z%{1#0tRXNoXPC`!o~b=VITN%zbo_oU&?Dp+OsPX^EetQsf*`!IAwd>0=+l2}exd4a K^S=lP)BO+b&VFnF literal 0 HcmV?d00001 diff --git a/src/ui/UIProgram/__pycache__/precess_bar.cpython-39.pyc b/src/ui/UIProgram/__pycache__/precess_bar.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..67059800a2e73c9ee8c42c3d73f5177f5d14c6bc GIT binary patch literal 1730 zcmZ`(-D@316rb7eySe$Qv8kdE5QN)@B#4Rx5lM X`o$2|CA6PkaaPo6V-6K(_DWzL*4XXeZ~Gr!+N 5qJYSB48f&i?`Sx-lW!3}Z`f|3r z8tr9;1moRPBgSB(A0~)jJ`aMEfHD#o%)3W!Qk_gAFqy^dyCkrf!(8a?d&DAv1F1FC z*hmIzv7sZ?0uF=N&`fCg3?)PoNlUVCR7Ob$l#-HECWAc&hSn{xZDtO%PdeJN26P|R zgznI`hqfmh5D7hgNp}2dj5&2g(3=oZM+bep9+wmQ (`=dgpvK z3;hMO8Nm}=>wXAlbIjnBiVGkf-T(af=WiY!{B-#1504IhJpAjIhX;eB&weXr!Fl-4 zw})STb@=D~g`-dZhVJOQ-
I8$z%^?E#(%FB8yIuMY?%6W2AIsHiRo(vkg1SCb^*EMLp zxv5!`)O2y`{sC2uFpQHZ&%^Kmd3O>^z3 zpqrbUdrTKvj+lb*%7x3=;JZ>xqGjd)m}$_&IS?&NAaVh7G7?gmyvLN+A3j^+1)QeE zizf>%f|BcU=*wrSJps=X?+m^<*mSjcv`{A*kRiY5T8k<>PO_Z0jA17HHbCL**5_d* zzJR%Y!_I7ciYEx?B4v6}%7HR|7^WF364aYv_)!rhwMXBvu3unaH9iCqfIA7pk-eV> zuh6w48xiF>3Xe{_ G>+} P%{tw;^rMVH=FI;ArrODU literal 0 HcmV?d00001 diff --git a/src/ui/UIProgram/__pycache__/ui_sources_rc.cpython-39.pyc b/src/ui/UIProgram/__pycache__/ui_sources_rc.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..083077abf5a2a9bd89dbce7efd2d5a047d94ee0f GIT binary patch literal 535496 zcmeEuWl&sQvo0>dgS%U>KyY^nZowUb1$PggAcISA3-0b7oZt+ugS*Qhm*h>p^L 3dBLnKm=RG@Ky3ax`S%yh%Zc#I+v(HG zhbe?9 *Mm9qVgm|eN zT@`{JWACL!2ztl`IAv!sJ4Z7oA4&uW2zcqruSyD1D6a^9^&3S-T3iJJ0(Sdl1Y`(s zFC~FJ5n?Z2kWMO6q7dajiGEcAV=f{u0s&DKh4f$q`*MzGFRkSS0fE~4>kXN}fJ*pM zsOBu8>1=Q3 e?hIriww5+#oT9EOmOo$Wm-|(}nY**2k< -SpehNI{aUA_;vzFcU6(g&Im(k_>0<3WzUS0j;Fl_7 zvR&})ow?*x!S~}>tGop*#$#DXGGSv%gwJz8IjVX&h^8GK%5I z0=zMhv)Z#DCTCQV>nu-O2y&1?bh{c*(T?(NrP=^u>P^47@fn%=nMCwJ4BBF#n@% z*`WVPoyk+BtCAaV2|k%m2P9QZyuUr+*sMegcm!-drdzsx+?!pz={BmswYYdk%%`Uj zpSqCGI>tZAiZIWx_vAhfR`FT2%e65OEHnwOeRpCFn!ZW$e3m$33iP C z7{2cCfs??9Kl-Gory;mY0m0JS@ArHaO {sQyS4` z5ru%h05wCkI2BA)#U0P^-o5_UY(={ ~5hC@1m_ZlV4BGzy zk`(?+>6Mgc3BO(Hzk`K{^#wdYY|M`2PQKm$s0R7h4Y1H>{|2OJO4OH5-3NC4J8B0o zLjETK=YJH6|F<*0E!F>YWAne$^uN>eFYAgf`v0G|{J#J&053iHuj6kL{6h;s2$NW8 z=AC~jLOI$WMxh0TP&`Jc$zpsic-1b?_E$zg)Ia2b5fWxWMD?uzO08GR&dQhr&*|Eu zN+I9h- %BuwnZhW?l((hf5S0u3YfRFRQ3K>w>AEXbbsWF zE^u?39DxMW;y|d3xEiqsV_=w5V;T$kk}pN_4ZcX4HQNRmib+ELACU#=V*i0uQQ&|J zQx>t |n6nDka4HYtAtS-ZBpNAN}N;T4uf2gtJ+gmAj(fqDX{-*M^--ykU zfu7SpW^Y@Mk7RXwQ1wvF^r-C0QN}WHDR>t z2x49kx+H<$KIo+SlKY2sUyBU)+lsz9Rp$IX4wSVX=SS!|__6}Hiiu=b@nyb|hoJJX z{7s&)Dnm}C;{gTMcy)fYC$DGHm?tIEM*8X!dL4{;4|UL@ABoy1GKpv45_0Y9nSV_w z _MPT!G^bw7SV=*Bn%!@+k7L8)Qe!v3jKEiQk zW?F#RaSJx4rJayh6Ns1CFiLgNEcs{FK!%3@gbjI+FvS8!CajL}H$&3{4P3L5bi}8v z(aHss42sLNj!!5tx>pzxTms8v{Z3mNwpctDUk0vWXOyuEf1G;Vp^J@C3ObHL|Al|( z3$^_%1t&vD8%1~p0#qR6P%&CQ6qA08p4O@$%Q;9 Vd&_PG16y3;u5Ps`knW>zgiuSe!geObzRzLZopJRn zUv|1IJ?RSmW$ru{e{{fM-`@(&lmV0VP)p<}&yH^@qR`)B)0n3E>0Fh9MF7Lp-E Sd!>lVugQwl?&`U*- zOyFc3Qx;PO2GDFcu7vL?Ek&C@C$fo>zQ1i8sjF0LzMRm0S%moUQ+}d4{v=;#u)F z-Tmp`djBQSH0=?BIg=$qkeQNqN6g{EyR9D0Xctr2kZQorj5k>5YiaqH2)G&6BMgoS zo;d1AoX h5g22LL{bt|6cmx@F{WxOWpUi$5 @FFXT?j;Lnd7uh`jY z^Y%*3fwX8IaY- 4WzH(luO4la*2?e!-zZGxb>5u;ea@FJvJBeo= IyQP z$8{vOme|}@X@EXTahchZG$l=h@Z&7)0eqLlKKp{x1{O8M*|4p3#=|yqR2cf+kb`)$ zeEIupg0}SagKC9-yM%ede>^Ve{$s{~vVc{>^n`%TifU(bmFg(#E{J&k2-(ynK78pe ziK672b4xDzmxi4&i)z~{T^#bLqG?FFwd-5;y~`Fh&)Wi;YP8SgH7A2FL*nILa&YG& zKCVIax-6spoK}GROGl&I{?3uXM~TSEYxWILZ}THy-#?l_R7;iTqZHh--kyu+q{ksi zOoM*3F}qsR{&b5!JGuey{tq= NxmH|nnDi5$@^P`u~(R>D#AQ&G%Le87Rrn>Oi4L9w|)ko rb!b?qo*iq|;DoZ~MF_=}W4ChPVNm#3^D1&ft)u3?FmtlUz6a;c9biQ7(v*N&u z;LLX_nSe0A--;v!`;QHAeDp^cZ=C>n)=Gnky~(uUS#xC?hx%rkxB2drKAaUDdimuO zGJ(dW$cTStLGs-9Ed`z{n+`6tMl3O~V!O|JOP#BZ<<6KklCRFBo^m=RpgX!V+DCuy zXKeNWTK1pM7}7tTf_|}+XluN`O|mMA7gA@b?xje!T?cDlg*F#J7g~@tMO3#Br2ElS z--TeM>k?j4rtC>=v7uLZXrl&G_4KLshU2WUm^$Cp4%i!-fJZMSwF)n3f<~YLnIOEB z!JPZ|o~8{6I+g_1U1vMg9DGT3;B}?Q-@J jHNH*$~eGH8VS -} z&&mLF6gNBDCALkuH`$xv1>eVyQH{`kabyjz8-1^N6=*~t55DDZ7wZQ%`&yM8i}|GG zJES{5a2kwvl<#oH6l{rgjy5C7d+2>6iWLIqY>@pjV*?NWq&K78a7diPAW2M-`qgoc z-;z}3K9`#Ym+JFSp4WKg?UwD)ve}3!k+?2j*JklMGSGTpni0No$nVJ>n9Uzpi;Yl1 zvsM4Xb)}KaDMz^i8M5C;(AS!1p%bpQ@_|MQYgG}=cr^_u=^634o>*dWv~Joql^K-( zsZLm1!J%o#7SqFO^=STUmumb`%(S;Q+|`R?WV1VUxM3Ci-AUy?Sy^4b5yHx^o+Q?9 ziloB!N6b3P^CZIo5vFtu_ZX!&=|UJ<%L%9f=alT$EwGycQPoP7&znS9=nM(<$vQl- zLuZX?>BGF+ =@@^> h2XBD4 z)2mvCS3go33_K(9e6#_?s%P~$>0v}$&AxA(4Cl7K>Nl^#sZIP;rF+TvC5UxyALS*y zhyLB?x<4^XlP^M5j<9NHA$@e*u2!_n)U@H$Qdd@%ChPYEkp>0^S`u6yKN^@pB>p~0 z7bXG#QJB8egc)7Gw{CLe;uRZ-LEO<7-Gvy1ki- ev z_@o61w8+|X59VipmAQyaxpe(@@XmaCgKRcaQHwZ*K+en16^>>iAlDV{)?0(T%T7n# zdeV<~x}>;wSol9t=(gt!S7&r@Osz!%=30okCqmgYK9!0Q$Ny3z( wxO* zIrsT}vf2Is7!KQ?1s-xC+h5ApnSt5)*z%c=73@B&g&R_a9BBSt;8p$+J{Y;>Sz-F& z=0t>E9p$MerybCAk?Q%Zj=9-eB59+8@Mq$^E6>RjYi+F 7bhTB3znL#s-zAgS#N^Cu69GK>+fQs9Ehh=#cY1yDk(Qa3; zrHu9~q1)xi%-DDHozgR0dG5s@Jtoh2Pa{S(8^4g}D9&AbW9O*%U-3sCwqKmI5Vh2| z@W~sD0j1T0(0%l3QNPjf@(5na`I*|M+zu?B$JQ^f=Gj?ID0xj1_0e9-SjNY_uc{~4 zH7k)f$!p{}qzF(XK6t6Lp2$w#Es%!Lpp8f^nqdSF&Bf5%Q8WV~jPCChfyizh2955@ z3T@}bt@jHh)lE%IZ3);s_3g}BiQfPwe*WlBi+bmQUBc(yRF9>!ZcArIcL|D5VOTuZ zVeb8HGzU>Ya3#=69}L{Ju7A6kR2DYo6LaN=GovVCU{j+ 0}zKqN!dHa5WKpcGgmKaW?l28K4-Ho?e4^-`X&l7X $&Gykln*@g(Bd3 zHJmf;+o^*xoQqI?%(alpG;s~s*CdPRna}aK8`c99BeiwjmtR_5_P!xi2H+~c7ptj- zJ9 3YD-Y=jM#ueddEQz@$yTp*YwY zsj E!x LfOe(hKSH7PzblPSCln+rdEWKw z9ewzyA%yil+a%F}C&CPtnu$-oeFTd0dh+D0y@9dt(sK93+S$@=!&pW_rqFrer{m*+ z_kJ9^y+MMBgqt!=FnO`3K+LK%YZSNf8_)9}tG66YXMKca^x 9k3HuH zg>2UC78O%@1`SiwEY+7=KR#po8ULu(g |Y`ti%ZC>yib`GeA>ZV$v>VDmzUf(5*Xm`n;G%;clB!g8Q{ zYz3mSbMOooj<3Jp^e$_=%ZAAXUypc@YGJZbCNiK(5r{jfN|x6ex;oOkmRsPQ#M>d* zB=lszo!9+d)FxA($wS0`99~{0KLHhfyJAcw jLH~y(tv? ;B_pk5-QUDh oqUy$ 8Ly@h)3w0W~;# zyZ<7bLa0R%ChGGps0-h(uQl5&e5ntlSw&-Q7N+o}y+3$7-Yt)h$f7+^N;-9kJ!b*t z0y%SIvv$5^fy#H@5wz}cV%L6^|FB!$vNbaA6nh1JGtBrU!(}t-Le$_&^s^ucNAc#4 z(~ulo7!|te9!+{>I~x~D;wzrvbL}zJm1`rK8PucQgX0%zX#*Gor;GEhYB}9-q?tr! zL0x$yKH4iQu0{Byvd7N+R06g5l}juefE$@s+Lo}jT9iR$<`Qr_n?#S*lQzAeye*F| zrCkk! 77)@mi6KTM{dPIbPKTTTY#WY)3~H-bUXD##7$ zutxUW5NNTjh?xDH7j@-a-%p5M2#T?tWZ=&Cw@eLC-_`n;7h1eRp vblX9_v}|m{_N6a{hj{ueZa*%fm^dJ`z~3wz@@T7Z!=wEOJnLw zymBDZ(LqtsdL6R#+&Lz p_XM1mvJ(K p7xxDkxy8Kg0GI7kkAH4bf!UPtFE${J2(;M_M5!15O`Bz_@kh zq`0@^t+3YlP$^3ZKorfT@4+6&pUmZ2|1@Z&(^51bTOzM0=42`?A$h{D^6M8A1TUY8 ze01DRtWIuqC^e;q~_y@6c}> z# &-Y;<7wI($Ixgju}HZY6)S^VBt?OS-v5zE|+(8ml{l*qw04LLNl*5v}K zX}tY8n(59LzPYRKnUK*J@~*(}E6TW}H~TKI(0c)CF#i)FwHB`yrY*xdsV2U$9c$&v zaK^#%CZLg533|9Yj!t!;H<8DoLTUTby54INFnG2x!_!fn^Ey>% 0Ha+bKP3&5enGazTn zm!8PKZort^q!3NHCz!3pa!_Q@)atO!
DzTLhn6Q%>X&`}o!kMi{|RV!-zwVY18yvL zQ{k*zTTjt +vN|77hydB*m=FJmbLR!)8s=eZU!8CZrZwIa2 z)zOr!fo5n}P-Z~nOWx86zQx _>eSM=?S{qVI5ii4+fZ?vE|+Hp zNwGHWCG5LB0rcJHTOIg(of}OvJ%Nh#PW;26-Qx~K1F9lz{1yY#*c#`Xas5>C-%^PA zlU^j!O9^0Q7F&5;Dg(`?r1k!DKBu&QlvdJ8t;!Yi6qa+bmmA&+&1O%Mf|Tc@2?Ybg z_2pORUKLd&nF`l^RbhPMRNfZ-Vn0p8j8k&Bc8vJ`nnhBNLx(2&yIAK_A~*SKE-2;x zapNyBlv#l0;PJqbp+b-4_lc8!%r$Bs@5gv8i8ak5^pZ&-cgYT nOS^s(kWbf^d|oi3|4O2<0E<`fGoE%u_#i>WkkhSJrGF4bGX6w~0&kMfDA z-!_avO#e6;4U|7lhFxUsJ2`}j9OChG%OO2pO_Bny#k@QcB}^SBb8yT1G7&EO5!K-8 zod7vJm7LN^(6vc 6CpSLF{TU#r zj%y6T_HeXXE=dG82Qy&r7Wb(iFv~Tq+b )ecUb^2~amnb+0U z=O#~Ps_^v+;^K7Okn{|!n^l%-uMei|cm~w>KQ&(uN3VnY-$30yV#i3G5RWkx<6GWk z(V(RwE$|j*|2Cwkul~iw$m9st9E=GwbXClY{F9yE-Z(Xum_0U{{Vb}S_7|Np-OjT# zPJk8GQq>zfXoU1S(sS)`ZBUg~UV$W(wsyfR6J|}HTp~t;B4sRhDD5U*vH_4bx1E@y z$ i6Yb_7V(W~OGpYgS2@IPE+ zMx~}9igef3bB@C!LVJ1OOgT^1FR&BJTphT!0hVk=O=`+FUAOnVzUa2C$HffS?G6~S z$Jec6@3o#*4ypJ5gddl`Y_p;tV$#q%co%DY(CS>z6`*jJN?;N7Ban=>g>EIG^ z)VJ_c9x0^VbDk{C3 xlyd5G-tHavN8*VUfyh=#HnD9+nDCNHpk3q8?6w`X4wC% Kct&g&`XVc!V zRT&M!KS*#cG@u3M(pe}v?~m$N3@3^1CE;}YJ>~_Qvsjblw7*H4sxbwqTRk#(3Ks65 z?x&2vgWP?ad|@7L` E(KB zPrXs6Ws##Bz74?8qyGz_X0lZ0fI~sLq`xEngU>vQ+az4P+Tx+pO~j)g3_Rb1p6o0v z>8>r{owP-c2mK6{pOcQr=tII5n0LYhhIR24%k-1_9R*+cHxLRjo<}{6v57`Qjo!0_ z6y7L04_mN(t@lCOf)-!;$XlLxL6HPc>aEFaW4n7Ebs{Cw*^*XeTZ;9Rv^B@RB8i{K zhC^F)sjA{<6_g~-rA(`afv;|cX`(upe%_|9A=yHC2jB60Gjj9liWiw9f-7#fpF?Ev z0Wd&xUHuRmdV)T XTw5m9Dkh
{EAi4kzc$U%~$ar)msn5hrxGZ|{N&4P0`hJ_W zhlhu|chz>Dj|uHQ (0opz9UpETrbeZjoKKVAF)cC+ zkO0s{uaOn0O-WuXHxPU28zMP~fL0)85!;cDQ~9~liw-#X&bu&{4u=@uS>irv73=Og zvv} MNszn1+<5NlMt8Izh|wTG4yRvFXKq$j NExW%$u;lN zg3 nAF z8%?Laz?YbsgmrcKyM#eNPe1Pa3(=?tZz`QO(b_y6x(!(jDvW7;bFCeMJEgCkhUOw9 zVfgd|S8*VmrLE8`W~NRZX*#rJZPNp %3oC xX zqC>+qsv>-uDXKG}XctZdngKdN$9{O2M(&G`Yz}~$MO+2H+7US`Kwq(%aE11~N-? 3H= JoX zSF>60^2s6v-ZaB2Y _*jsB^2HfO{)wzu=(df{yApe1X|7{=I)oXZ5MQ^}6q1c8tW%#H8;A zX7N`tAoR}zLp=P~_9EfTvt>A%4yuiFD}nRWN-mA6rYe`>9|XaC+FGH)-&6RLt)^)# z3rBK02ec`>zXEQms^RByMsOL%%)S(;d!IWsYbCVTM~#1M_6;Q~CU2~w?USUDS)_rJ z=5sem>5pHKZlMx>HztMC%j5Qx18Xw5#f}0-lOGksv9iRs=t`=L=P6R5&h!VD7tt++ z3)kT=QmiYC8|e@9&ALXnOu->reh8~oDxww6P^mCLx?S@2Ej)1{v9%W2*V{iPLQzp{ zCE_O@5^laz0`;$A?3Eonu~$z?ayQMI1I2kwsE-2s&GbBUOgD843*2g0M&f6tp`8jh z0g}ZgoBa;sKSD2$RY$nNXO7I NbLz4lAjG)&6mvgkI{2q&3jO)sr(IPCnIcZn-i7!c3lBc`e^9HwNrj{1y7BAnR z4##lY-y( ^9$nxz@IbozKBDU$e zs733XPg8ZZ$5Zi?9M};FVWmWmZ`b%3OGbQKKUlN0UB0*IhNECH1kiaoj#xw*?l1g! z6#Bw*I02W~SY+LNDHSUk^<=Bq?B=IIB~;S?CF9+x_pKJYd@29uXzOZW3&mk8H;p3- z3+-wkZpkd#jIJr=6s3t56@K4%b~jRhr2K%l#mTV;bWu`hcYM`qQyvR)Y};passn7O zz3T{fpY%-6eS98|^Z54dZ^u@8dmooiV{=Q=gU*hFi6jog2aI}BN&x}ss&xpWI#TzK z8Kvdr!`DBB+wYD}24!jW>(>N+wg|%f%Jty=S$pj1VF^hs93BoollIv1j?~9;Lw`7y zsmj?hcxGyOr~binW-!mG9>NQ&u{E~fh%Pi|-RCieCu2x37;Ev{K$5R)*owp8D;O_~ z42Wa&ODM3xNmW_3<{0MNj3}+qwjbXi;Bqj&sCwb}KnAzEpKobO8PdS)mIXedd30J; zVO5D1CRB6gi1yUd6yb|yt|6(E&6|>_bxXO{x^96OXiM?QvP_k|*o{=%k7M3;Cf6b> zRSW~(xELhux-GIXO#} q)VNdGaS**ynEDFGFIu!IQ7=T7QFsj1tSJ%^!Z=qr)kV)0400^Vv zmeyCac5t6zOJ57su2r$!A{B=EJ$-3)xR1E}a6h@XF-+=%_D(&GGP{Vry<+|ei0Iam z$}eNdbl8%@E_K@m9L`I ^m0w#e8&OQQiBja|~w3{3` z79`098Rejqz@G1}hPdDZe%I8euu}%NzBwHjCKVkpxprMs$Obo>N&IH<^V8vKcfea# zE>d-_d~InnIZG}q)`qe&8!v!8f<+0Dg9k$|KbFnGIcuTeh*D}OtQrci0y#AY#RBQb zDAkM@KLTC+XsAd-zshXT1z=?Go>vX(J1aciG^TKBQU$EaYFDhcV$xtz&GArOcV!I& z{!eN@u*=|C@H#qJ(V}FWy~+6;z!C({ErN@d1a!W~uZlwvj=QpEOWQay3#HPSzA`eW zV`zEfb>%>x(WnYSk>6pqfc_b?Ft#LpUz_~iKg@+sTD#B66l0k(q(U!6SeqnHq4qk5 z%qiwraqfHfrZw;R91BU(l=({7STfLO7`dc+dmPEFv%fi*i*1xcf{z?+i>}fX@=;U5 zD35lg6j-(PJTw&6>U%HW^z0v+m%F2%9O{+-{v``aMD{1owU1d|)RR#0x+1P${Lb;T z3kM&o*|KBJyP;&Ol@{Mv-2mJ_NmxDv;a0cPRNUM7?vyC&llmtmfJ>4Vz?ecxZV05j z?NLxU=WU*a>V0*BMDnI1r+w=T19L9LQzlx&%!@1;(eOc&XeSu7?Pt`5LB-FR70bJh z-+2lPiU0BthR~ceyiyicdLJ4@`}w~0EIb8LJ034!N7=L~Nh}}s06VNcT~waD`E6YD z^4Z+2fi;sE@t%uUH6PI+G@8&GmP}8r=4O+vd#I=mi?3~)3yBBDHZg|#hTL>~QdpTJ z=l8Gm-_7}c-n6jjPj~= S&o_Btxig6v EI~S@Wt;wUX}6Nek{zcetR#d8f&PO&=_` zA*l@+?*}&nlf{JBmt=3(8-F04pt&m|4Eo-PN#HR|v91dGDIYiO2p)v7M7(HJbYOn2 zUEY HmveTls=ezDE;rnP^JQ2B>11*Zb zhetLbHaI*Wq6fskDT)r8W`PkvudG@#1a*H8cRXJ5;PG1z_@q0J;GaGrUCkJ$W7{ra z+q_59bTyk=hTN^@Vw+5IY^?Sc{?@AL&6)z3boD}YUR{SqodaoQ?pdk9H{q&oTX+{e zj6AiMU@Zd2>V27yinok^I}QR|f@rGAcXYOrZ8o9}7Bb0eIZ#<7)7`$tOAPF_>Lrh6 z9ctL7RpTQfyL+f0;T3}R4OuT+-j`T8)3}+6UcNe4HZ4Z6uh^4u*9howMjzAiByNf= z;voQkCkSPhYN(U(SujH*mLy(!_jCW|Clv9ggXi!8FF_(yOuij%Oi2?|4?UJyqrAC< z?8`j2oo9;k1qR-zc4-6J`YNXLE(6@VBR`r+Rs42@U`0+jpHk^KJTar>Xm$Q?NGIIk z%^7IyimPVI7gf4wrPg`As5ag0pJA^(o%2d8KXu7|zxs@$>~%Dwv9)KOS>xzNK^Ily zF(Voc-)h5%zv(mC6tNs(K)34`@s 5KuN~=W}&3hrX#FgwB?p?}Se7@^8Tj znSd5}#wqU{vVPXJ(cJ l@48_j3@(tlZ^!o=hAOJb71?$Z!7+N18yS5i1No|IC2&w)Bnu(Xy~R{-d1DS%^_ zXxSA>H3e!9s-)V7Dr(qbTaP@f49~?r^uYp; c4Smu)_ygiW-vGuqHCOR0--JY`nh+1Lz8vEz;yF88s@1oU5 zHlv>HC=N FNx=`2x>CV+?8B^0qJACPA27P8)O-~bRt3iR|I8`bYfbe}Y zVuF$+M~0702M#_e{C&n$+|7z>xcB;nff6|QQ6g#YC3k@JF+CCi@?{I*!K>qu7iQGk z^_AE6y}VFqex_vN4Y}(favu;)qB`A$iV)isb356C-^vqSR47S`(0%2hkmWJ7gJ~W~ z@k^-{7##({YA?$YR|%ijvJ!Smjahf3tUUcZM!JEe`bjXx?_o@$I(3>qgE`V`+lU>G zgXYU42bzImqYsdzL2(G`%h$ZNPd0UxbxrhWPY)PP-ezL6fHFi99_SRou#ip %`WBd>v3t=41Sl>!MAz7>pZN`|afL`MGsPAzHE}?MfMvm&v5(cUWws z5ipP)#XW0sh}_yl(n)5D00yJ4+G;>;muD8{(f)=X%7l-vB|wPc*8CZS_I b)&Ed#;+4JgD}qAOptauT7xM0etUXxPy_l z!lWxxnT fBKKM0eV@3gg^(y+&Us?|!{SHM z2fN9R+e83I>?vj0_yi0#*d1pW+e^E?cvwksp)7gWwt<#mUY?@kdCc^*9PPcq(SrQl zEQ#n(1m5JkSTd9~z+G>-vJENpw+2g+C&H)Q6rjGB9*M_>!`_Vs21RYl8;s;4@EYU= zn_@k=hR+B!=^Uk=rxn;K^I6^F#HJy^=lFimr#ifaD;w>b8~g`iq)8fRs8+bDIcb7q z__8p6{84Io(!oH4&H3lguiB6oafDU6Eb_pWKfTPo#C%UqeC2K1?>-JXXZCsb*Y8|y z-}lZkU`5_r$yxK=Pqza1g`?uykD<@ogs^!Y`4wyzuon8 KiNtMhkq&=*l$hi8HfQJr;(CLY&QDW3QIu=i|=<-i;Ld?VBx z02bKO+q9_1=7Ez3C*q2Nqc?$Ld&&8vVUk!4%EgK8id_k*my@ii$!6fJZ)~KvQKxuG zrL?~?ioezgcw7(R_zHx3ey(0`?YkTA?zAY4SJ_x7)pZ>ME-yL2AX;Co6+iHi*=Ldy z3~s4!@}q8QC$u*Lh1XY)V*L&M>r}4kRdg|04!U+yHX+a1A*`ZCj2A3XdKg_EdU31I zU_W4c@>@UoKy=ZRZ#$pFUpArtg^9z1c%))+Rhq9w@b0NlFO9#v?vEXcMZK6$=Bl77 z@OQ7peroWXl)60O5Ym&SeiP8PPGK^HOt~SN9O|q`ly~*XfU3p*11Lo9w5OEZ@fd?K zdcm16B~@mWTy%cXv93(;rkU&OL;ABQ2%tDj2Nz>BgV?n W77i$ bmHiK;CL}#XN2ov(WRCx3Q7R-1WgnM^isUTGY~* zCGC&`b)5{_ZzW%LSL9mpeGC`;@YMxN75`9zXCEgyN`3V#I%yDwm7cpF+mq;N^H~eD ze1hiKV7V#LCh7g4*_RaQq4D7uoH!thR)jFNJ843=%E^1Zl@Dd$d*X-g@f_MCGv;f` z2SB{4H^NlS$2<_6sTQ!brm7RNX^l^;N(w~X72GE Q&!PND?hcBQlPDo^pZFB@u?&6=(rf!tyX{#mNYvsAVHuaK_J$!nRSa29~A5y zo+{CPj%I4#Utrd-`#%3d7}xpIPd%p$@s2;wM^u;)(anys^Zd|hY*>|r-%iAX-w{gW z&K)!7b=|P1%5*>yt2)C0e{^V`Ns$lC6UNUMkR$-dTIq4QIL+Q7kCin*U{o%t8tN9W z2i6;Pb*IGgU~R3K^2QCy(j$CO50I{3l@Or^ir$ja?ciWW6p#4cssnH5&ImynnM>wT zX>;@Qh$cBvV0E_*f&$$nn4|=rS4GAu*Bf;;j3^l?(&hn!yF4G0x2m7|5M$s^ULI Cym(#jf%J0ly;J?DTO!%N|Nua(nE((oMe$zoP%A#OJGPt$TU) z$Trga`5GQr+NvKXzFGI@MXHWtJ~zX{2b!8`*6#!w)Y`=(z^d+wi1aog18SvN&u0>r zv~e?6CXUAsuuVHFnFA~&ekuwFO Mxy%#(mrbC5w(Du& z3t{vhEMeh_z?wb77;hz$;@Q>)yt>?2fXY@Hx0+xwb()UZtl*~(JbC_h8D&O6dYd%> zeA1~huia#x2s5{we@R LVvMIrP*NZ8&b51e?*gYtFEG)>o0k DKr;>+#Kc@5fim*A9m5KaOJ6)UJ#TY4XtD;YDik@n# zh#FG&fAY=h7mZ>_q>0rq#w97NO>m6Oq1A7I*2j`VV_`>3qRy$Mr6o46HR*6)OZc(S zb(;)&ew!gD-8=Y7sv|Mq3{xjF@~JW%OPvd+HA7|JJs*~VcIQI`;j1bXirP>ZBf+Hv zp@%>rVU{v3l$Sj*{Cv@Ol?NOzPzj2LHUcPSmB;E&litDu`>f5dd&578mFRfJ__T7f zoCE!^0?u#EdM|V++TOiB?v{(3M#;$__|y#+*E uPExh@03?v8;byAWj=a}q*c$(+Ff!j zFb`IGQZRT;tFy7@95fhrzE4=8rL=Oa|MHBFT;N&4M6K}|fcsTgHpwt6tns)w_S=j) zOMujZT4hteaV)SFil+DDdnJ;H^f|(n4%>d{Z0Wru)|j*EV8gk_FqLts!H=cYrHcvV z0XmQB9&6d~YFL5iwgb&_0H-q5a-@7594d@A(FT4~oQLicwNv;*_ex_%tM`hY1ml~E zW3=@!oOa6*Zuv4pS>D}2&G;$3S8uMb`0LuT_1Hxq^$4#|SS<;?C*&SahRO$OqAZDb zEMWURn^;Oz9s(wRM%}`KbgxLBb;@=d-MM{=NNr}n=0}9M9;ED#7%Tfk%!7bNMkaf3 z*7?utR<{fV0RHE0r1KFcmR;~f*m4zM6&jJ)-gN>Nu&hJ}J!AIfoyig?mURoa&}t^& zGzGW$guFiqdWCk^GE9qluP@9@uj?sw_Mnqdk! zAX$7H&S9bjhg?bYa1!(2uO;gSToMBlu9_5uoQlTpo!o1zD4N3WrJ}Mu7=Sj7sL7TB z?X#AduWFVTg>dj9w|KX1wF__A$_?)e*RT4~HYrvYRuT#_J$Mxqx$=Wvu~*o lIQW{WP4TnJcF0>N7pyEQ3;TR6^^GiQLu` zx-E_P04BD#t^EUg;u;TB&l&wE!g+=F-`U~4%n))SxYC_!k+1kAmXPsx7@WLK>2w=> zg|{(Y_!jh=M3yvjGyH#Q)aR%xbOW!iT|sVsqT3yJw3Cknud-odzTYmk8l;5;afp>l zk#EU@&jk$Qzj~$wV8UbM<3@m%q5-=X^KnYW@1n~)8}EvW%gHPnDY7#Xhf03QmaxB< ztTt0HE_cvu$4Mh7s8a$CB84Liaw-tzo@i>%b=?8q&+9<_yl9*%TJDPHOq{(`C6T9L zRWk)w>x2({r}z)q7?WvhDLc%hX>rKhutupRq$GQ#U907{K@{PwFRe!|n(!Spq@(Ps zv~@T#bDglOSWvhnX*#YeV41EJa#m)BoYc~rAGw4tm*~BMDxq~z+k~>`9ZHTA1?tOu zLh0^~ccloAjJvm@6m8VyeVUTo-jhTEbb$`>!TjMn@B24%*>J}0%Y3-fyXW<^du~^3 zAzbg9Wo?hmgR{F-JAyT{cgL7>i=*_Qk6kpMO1)%7;9}7dI22vRmw~yyjW|M Sl<64emDQotWqdCUj6{dhyf;KY7A6Yw=RTg zHV}UvEP(-}Nr~yhQTt#i3S2l)_93O+Z@#vM2FSA e|)tS2DFTUW>Eu$L`xU zC5;!1*Bac8hes;z*Vz6=B+d@8?L?)pr^D0VPcI#~_u!XkD#J%9HqTqgOkcBNF^S;# z0wPS2Xcsli AU5^P@FFFjQd%FFz2u%-d#{lcy3_?XFORkFuw=EI*?f2{=i zNsmvvBT$&8ZA4Z=1Pb=1k}^?fk$=|H|B|mU;iXCw5TIzi$mw6#y9+N^2I$9~w`%Ru zSrA`c)p{ycct1vWB?X`J6|>+isSU?lsM@4wDcHFi3kX@=CH>^}$b32Zu1W5BH=#Un zi^FKt*u4TTf@7*=WUM_O=^yp1`l~Qj%T5ow_HzlMIFM%$*v6Z@#7KszkVIpg%?KH6 zB>%-Y>nyPQ(1z#n^qck*e?aEjI$a>~Cip)O< A}(>D^lA
Sadf%#+-cF|?n0MALz{0*5})PvKC=|u zVe3dXb=rco2KW!o{f6N{rJG(gs^K_7c^_GiL?X06Md%$%K{=E6@O9v0aQ}A_|KtKA zGS0}nXsJp52UXBaMuthPjb?>Kc$~AU-Ry43d%xppro1$=B;zI8{KwhS(7fP!7lE7< zUYsw@jx&ACsw5aO0fb0CtRg IPl7bta7oSf|w*0d?+A^sQUYp_GE7xV0|HO?yEMex ~!#iTliVoZY_L-ezWh>23*&-6QsP_}n&p(v^DMOnL@`dOw- zf{#yfY%1nQA(GD?la#4O?%$0WOA^0{w8@J!yOfl=omn>-_E{qmYZMzzR6e?SrL^94 zh3f?Pe~>>#9tG@%Y!XEj1aGMjzDdC{o8M7C{j+ffZyl5PeVSaGAmB|pQC@lyhGk_) z;T&szG5Cpg7YY#I2Jd^Q`*hy}6OX@we?6@F?cjkfQzh>%rh7ho08)R`ASdM&At8Aa zJ#s0Ye@B(?sd<}Qe5sgwmudwyR<|)LCrSR%46=N -0Fao%dP( zlQ`#O2xONW3ZHuHa$(^jwm@sy`q8z=>^0^No!WL0Euiwz1K}OtWX%uBlVQ=lJEK zFI$WCst<7j2gZimWUN%2Xf&ZpdDQUy+x*b~vzFRSmX4kS4@D#3`ax}a1EcKq(2sM0 zT7kcR{Dt`HUKbbU@wM8BFrtuZ<8YNk@I_$lSMx VfXE(txUIfh;t8tYGn(t8y*PA zIK5hAZi}?}0%~3UGfbLli=o!X4DY@$TQ!v(lJtIOiIGcUK6p^5``19N^>_RJf5(f1 zytzLLBL4Val1ip3bobf{(s}B?G@|E}(zV!*G=%>u+k*qqzG#@3&TI MTlX!RNZOGnXl~hh7;@}T z4b)5xR0h{S2Ijl)+&N76;jVuOGirwc6nY3S!CkUyQ !?#M<&AlA*dP8@|82XT}6Xqveq4n p3%#nm1B7^OOS+Tt;^hok&8@1v#a5r%CT0(i{OTL5i+ zJy-6((6Bb?|170!=^P(f7`|dIIX>$cbc^mj$D%BKs5u%{0KRK!S?YtNkDV({QmhgA zORTtiH5h1VPN4I(IAQ}Khs}?@$CQR9SbA e@ zK(tA5NIrJkS}wsB58~z@{;$V*Go^eh#3x#*g`+g4q_m!ghbCkL2EH2G=C}P0wh9`L zUmywk9$7{>kM|zKdwOH4A4@SZCuzXOo)ehfp4Xp|`{X0g^zmGs7Gl&v5Z}B@?QcXh zBni1qY()Dw;h!<@Oe+$xG9iZ20^V*h7KTFYXbtL%q;O21IGRW_EXO$)w{4R*k`ME$ z3vRenC}fuemG4xLE`=O7^T?^{Dw`GArlCBk*a}P<0ayJ3Fk{g)yOx_jdY2IA^yeNZ z4-hXQN$E>>Rqnl`#cx$vzyE)J8rMna@I$X}`Z@45+4Geq9Zm|Vieb-$?zyL?bYU^2 zL0nNV2Uxz5(!FcAiCIxkNz#cpD3fMH7TdboP6za|%%D*Q8wzw)2WAZu>8rxO7u)Xg zL4p3rVbeTLCP~c>eE01!A}989yfK-(@5e@@_I8#NQ>DMo;~L~~H~gqJ0<^P~$f>Dk zN3R QI5y+2x(z^_~0$VM6(@bOo_769}A_8C@OI3Q4@u7TYkug)DJL81| zpm=Fjh+Q@gItT8LjM!TBQF{Z$zGWyerLg60&aVw=Npr(#y`dQD8QX4x{${bJ^TGOv z3@ (G+*|nAr6uK=6D{z7#o%1ul8Vl7rXrGH@raD- zrqq&xF|v;#E>pJ7tEJF19Ixw9JL=h)$oVZ(;I#4|L2U7yVZ@`tF`ML?QSLFT+;_%P zOS6hxxbnRFF9Nwy*2RRt+Egpp);&+eW$?LnU+&35O^{I_Juq%Cb@6tnj1??Mrq8!b z7W&9+=zS2FxTW*s*ykAyP+0vpFmF;}52|XH>e;g36N5g@VR1NK>+}UhUKSl)*ME_B zUQT(i6_ebYebVP~vlpc#*U9yEZ*(9J#R~y&SQ!eB8HUI!kStF_`+ygVL%t zO19~3eG)xUG0?4e#$&Mw9KRxCM#zc*ue`AzGG|JA#t_yYq&qTDD|PpT$0G{drBrWc zq{Xytq4Bf@*~Lc-k~uPjV)Vg-dCR5>^N1iif%EC9#m{9*$kidZ!{Wy6Ckb=TW$G|g z1ja(u{AN`hrS7~evG*FsG-$w_A0-rn>c%v338d-NyPU*mrna`6gQ>Xx3>XLhef_-_ z%{M)DWrpF_1_r|g&Ax5AV;B)VEU;>d%ue~5{f9LjF-I3eR6hOFtS#1!Ttv utt(_1aSP;P{(-*78HSlKK+KsRF@AOcyu~ zn3nHd4*W=eOkfxvvs7=Hj?MWhp!_tx)pSYVPfC7|;-U~!vD0Ydh2>wKEBe;j(B-9l z3PM$Z_zLAT88!)OqTPN5!dKHkc-i*RuQn9`Ywh>1ap?^9{i7D2+UAKz&1KozzSAsT zRHrFMv;N$w5N*p)K27_fAY=FxT3>MDp!!Mhf|{-=YFFcE-_k>~0S*K?!P7QWZ@S_1 zYEIcy{P+;~O!Sf+R$XYP#3oRFDtK)S`gKB7sX0nbeETJNQVr&~JQ8KxggV_>m&kqP zvcRJUw*IR|eM7_1!sBf3ENW1wMmB+G#N|hT^~k<&Ai&P38ul=Qik*>3@`^%x#*ViN z(MoZ6EAF63yNr7BaPY9~+dolH s=uhoUp=x zU(laqYObCjkq)MCZ+B7D0NBd;IcSiaeZ{p10!MtoN5ATw2QZBamqElUE)TaxPg`De zwnuQ-4$FtW_^<9v_M~X<*2tT3?xuRhy>$)3f|GPnf7slmmxs1qOFCT_qxtfusZfeN zaZcgf9zZ!U4~nVU6}nop;1WJy=DknZYZnRIb0jNmX{YHOMF8z(PP3}nwD$=9g@~NU zIM#grX6LS}Z{Bf7m{EB1O%Wnd0xc9S;LS#9S0 T&5P$75=G9JQ14T zzZHxKK7 b65^2fL z%Sag2wcFYZ0T zYV?L$Pevj%OMK+X7}k~}%_*p@(NHgxK??YhM;QiX!^$C>9FdV5b5BWoKT4~tHyxPu zFNSsf51s5r_+1kE3E3#OxHp*9prq5&q_(!uJ+(lfrs&XUy&1#g$f&I2UZylRBw7%n zh_4XgiaixFHh=r`aYNCf=}HQvS6XsKuNj<)eSbqSuxlkXTWe?Jp^K!+%t!wgilUNB zlgj}V%UOC5N8Vt|@_oaCuF&U&%zav$4!kU5up}X$QauXgcg>W>5Q2pzTJ-riM&LO9 z_^zRF%S_)3e*6T^k4gWD?(0i(4rQ}VthgT00z>~E&=TLa{*di%x`3N9+Fv~C@^nzv zu-P3omV26p&xl4lB>q0&B1Fkkx*_*NvEqT>mk3jn{Kl%db|lyB=hN4p36N+f>VFR$ z?zI2yf=oFj1C~?GAx+B5ps|2@Srie3cA5*&lY0uAKywB$eZENz4@}Fsq4Qw#TCLXY ziO0}yKiIpmOz)KVhJV9o)!f3HslPv;vjh(>thog|qjM)%=+y{duvbN3)`D#p{Z~ko zsw%5rNE$reH+j{YW8BK{G7qZzZN_EcUDv7hBahMeowZOwxve=Lq8Uk~3*F?yp33^E zg)} #|`A}r(l4S%it-vf<3 z=nx0}{i~zX264<9xog_QkCViT!08oN7i1t?ej&uYg>l&YavSySox&@QHl`i$LZb2X zbEYIIj-2sOE*=FEE!8rs{jtx1Z6-dC&tU2q()$hR%C2Os`iktvuf=W8u)20*L&Y}! z`@l{9sPvhcItPQOM-}L@eDSYYbQHFkTZCWf+P(`-of8S;f?61-i&w(ADnAU58hwo* z8-0Dj-e+PI96WCtUA5-_HdpD!hpX*Ch8ZiXAE~Y7$A7;;;;JN9e!aQrusx0{K92eP zsK~o^&(=?=<;Gy*trvd< %M$m~hZ`@fCbC!g5&ms0G|e?mY}ugF z%AB?wGk+C;eQBn=1*m>8F0B9Fdl_I}KSL9_Z)j63FVTG>Z8yJy>#-Ft4M0KDQaehz zo6t A!8cO`+DLx) zxd=j|DmYmNNO;;SAw Ci$vS&@-;+{u8{CnV1Pq}YJ4W{Vo?{&}WgH)%C(v$fyH6XiD!N`q~(FBfr+)&n3 z+*1XGj5*Vk65oqh1#7-ywi3_W{2DArV`+`0$|-+pQdUf-113et&xF+0OExAF9Dmby zr-iMdn#b4W=r%1UzTQ=QWuTBl4ov8g={fN7-6=eaOCw<326_@;9o))q($=*9yY<-# zxo1ntVB$MUYV?#a^bHy7vxY}>c>j0P%8sD9$~~*`+qPvB!W{+NM6S0cTdU;ST{Kk- zA3n04hzWV*O={Dr@Q@{5JQyl2HjMG>{S+q!V@~nZ@^S=~4X QXD1%D2`U)(8ERR`jL~j5+TN+u zR2n;bIm@*_B> N<5UjA<*y-@4|3oTVpO`$AW_Pi7jANR_we2(RXc`G9w zvs+y^YF!MyrG*ZJ&2jw&zV$wHVit)k*v>~|TOqiWDE9KTs=m*5hyP^rxi2ly%BSMp zIQ)y~aZqCW%fl(;>X$ |S$?J=6_ zEpHd42n#dK0@x2^%t8Qou`D^q;KCIPA&E>qaR4AQuxc?E6{BLe?IR4c*rRPhNBcay z9gnnBP#s8mzbo(qNj_G-fj#v^71e{KnPFqjPf|DwgDYV9SUCS3wO1GDcUFnz4;|M0 z&3sjgR)dgeMV;V`IpfTVc64io(%5Jg$H3xi!-YbtdF$&9^oZ%X0NBw2bfvFgSOHqx z1gRzQ+5!KI8&h*y#BIDHD=a_DpIzr9b}?H}NNpZ)?%$_=^FJJLKi}^wUKj9Otc(zV zN{Tna`siT4C|}4EOJE*v;7atZEhGPCuc%dko_*>2F^FQ(qKa-|rwHL)RDdj{X}vH; zqi+EZ% j6vdN-fC~@e141-Ylhoh` za7PWj(~ap0<@3fiub)tqf&l#FCyG!TyWh+Az;bjZWSfz#5pwCrk?M)OQl7AL0C^Z_ z6v;4k`Bk4@k)OKzq@*lystZ~odmxgKD3V{k>OOu)N>z6_pOU;49>ky2IeM?9*`# gKMZtbDiI72thgpyQeX*kFn;YZ5j76D z>yLSu+bvXRGxj^U+IaI%CsJmSJ+)2HL+kimODs>*;n>x>4Yp!p?)AEjvcZ*+BuLSo z(l?7~guEKa!e!TGOCW|MaKHW2132w#_vr-bL)DwRYTNUF*wyWH$!B70ppwE}9sR{N z?~ElT8JlBISclGl^Mb*F^qWz&&R0>QB*dIeY|SN(lxA@^ybmTrBJ!s}95ydCnfkgj zbQ{0G%2Ka8dd-L^^(FN6yX4v!F|E(H<>=zi{$Iye^?OUGXCkIi7i;p5tLVOmZBnwX zwPWo~6refMCK*+IxfrIVf~fuc>xJr&=D*Wi)ve`Rd(C;=PIGbNAwI1p2Yv9fpMS?H z $R%C(6#pnk9+I}#AUB_4jPLVh_bY?SttCG%AEV^}H( zl?yyC=U+OmkL;JT2UVBmSg_7Vn?>4j!jTz5@vo?7wi8<;xq22wwEz9*tEnOOdPqQ3 zT4OMl;cA$?rT%8F^m5RkkIemeh)_`r=}n8M^HP&2+)vb$geiUvex{x-vKuKjQnOw5 z68I&NvK)c^9-WflFrtC-*S9*6hI_?5H{$5z-;5L!zyHYutvK4BiZCmzqS48*=)u`y z*)iE=r*^;JN~-=t)`WGBsj!tGqA cVu?>VizE)Mx1TOi8Y}|P z#^B zgA=`pJc$)rO#?nkCyl*`B$_Fo$##~of!%=ZJW~YbHy^Zi__T&fpYf2S{=t>=g73Z^ z{TUy;=LsZ<6UR)QjO_}Q#Ca`z4$)Di|196CBXeNn&0 B&6ral85x3-{by`vNDOG?BYlIP<0Z6BV~ zZOf@WIiR^Jxf`EjBkYHAu1VdlgC3Y?5qJ0l$@vkK7h7IgBBiJTkrpiUN3zv)%8-DJ z&f0^kK1J`Qu6?#rvpUW3jxA~2v1kZ~Z1RDTN9QP@-I)-MI-oFkLhpN-%hTbX<+$`R zS}4I-n2miAW^|c~LyL1U)}v9T^eu{huJ22#3m0<^wrT3_s@t;fU~Ria4NRGazZI!7 zEkmC31{0{`-i=M~_>kj@QxtA@Yh}uasqxP)C5lBp*R=d_5)ZcYkfJvDD|TsdG%xrq z!YZXpWuK1KbQvvi_8IhCkAxl1ao_sKvrW`S&d2JK7D2)DW$>Z2y7@8{Hy3S%^DIco zqC_5x4Vjj>g3^ZG#@Ivi)#os-BhNm)`%Q0sfbA y-e7#HIs}9 z2{YSg_aGimn7CDf-?;q7Z1`}IB#$(9fMNWvjDP(92Pn2 p8?I;f;#EGnt1`DAI5M{!N}J+1VEK4bd0a!WQv z@RAX^^06u3YPwR2!oluKFxj;Tbzlu@AA@_6Q%EEQ$$Mn0bmA0^6g!qtofyWdz0@o- zPg~hPcupwl7OEKZ%Q_|5)HKVjG;rmHW0iHzGJ0L#Sj}TX+@iK#7HI3<`w?xGU;7qW zmoPfg`0q^$Ic6gKozOewOe>f}t>%(rj`mO?D|s!|-IHj4k)ncl#saUu_KLh2bCl~? z+pIkD*|Lc(Fn^#@n3JpMpYoLo&CZ96@>W*^Wwy7+B*^bc9=pa-*A+b;RV3(F#6_m2 zvs&4Pkf0g!Y%9rPdL|FAVJ=D;J*QKMSZXd%Gtky?r~l1FL{pFplTlnarS*t?^A3$b zyhBo}%%+PndQ(D9`@lIx!pBgc%}pgCQk(0ED$a?s0unnr$gXTVK^Ymh31K57;Mday ztswKM$F1#RYU!g_@|%?(bMikbfAQvA-awsY5FO+*eb`V7hpj`uINSk&{y@hifl3)P zgoHmAmfH~4dGwKTj$^|io-efVXx;99 ?@{IIGKOaq zd)d &{(ys&V}YzkVT6zRUX> *`kV1I z1&cp@4pg3JKWF8fhY3r$#ThX}qM*MfKX|$W=EWD+nhWsZ6mGoBcF+5`Ty!Jy-ddIG zz2+`!vt(=0Zd1aq@bZfzqF9D%z`C)aXjyYw(ygtwn%M@>q}K4n90bS*#BP${0zoYc zY8V7s?fh;|^ZEg@86k6Y$#bF$O!zSgd%20rrHEfxJIw^hcpWiKzABmM^cYeLT(W~| z?0*Z0ueED^V*&V;ud|)CVsTJ?#u2GH$|Q7DUx#W|7*p!|3=s+f8@A8SCGDz?Vn1={ zFfKxxH5~kGBdaol9G*1WFFp& deIDWs$48;WSd3VGiqR1 zA;^q98eH0lI-|lUF?~m45}agRfO-`~I`R8OczZJuA(jUGx9w8ATjjkGUKWqt#i^Z~ zMp-Do2e{wuRf~5CFffa=hU2jbSrp`G7$Vvm ztRYoLffE>?tFReF>kXn)-Ec2d46Uw~LHR1PE@do5LNz8}tFjc3*37*bc0%p+X`M$J zO|r@Ki>4t`udqh556J!r>3Sz;v^bi!R4eVE(XzofCCS?3!$aP)FzL&>1!03?i9Z|c zrOtkYt2h_HQahcEY(&nFGsVV$m?rTCJn!_#YLrgdMMKelRz8={-B{Lwz4${FM@FoB zUy9%^626dCV&vRS4RWn_mZ57OCrHk!Hp-NeLZ({;aSr8-9HafLV2EmfC(6>6w~Jp= zVB{3vx1%+_Ld}eMn5$>kc;4uJGnEONu*id0xH+A??L+;7|IxUO9oh~E_WA`r=gsI$ zZ73VSK~Q#_#-mV8KMFj(+iqKn-wY -xIoCG@?h9ixvdg)Q zmF^1?+EtaRuhBo)gHAr*yNQ#}*0wWM*U>|{S3Wu2b3XTk=&CDlRtkU5&e4XtLd#F9 z_fAqbB-1XV+2b@+k-kdi* av@Nds;w}&~WJ>KPh3XPn4C_sSl$`7RP$D5{i48pa_qc j1Tl3lvN}Iqt=>Ho&|QQ3N+M{roLfXKrfk)!%Vs-g#m7MX zRpbl|KKF <<2xz)-52h2kiZ^)(%1@*Y{=zF;rM*bs{7Lixr$GOSy(; zmu+nHyFG*Y K@4iE)N_tI$R9QhW**XsPW0Kbz`maRV&jR=e+93Zo#63QwM`@ z02_qNBX^64T9M#yWk~Qc8Ejq!c9!yOV`a^7O*#x$jdM28ZB?CFSVZYtp>4|r2Ifmq zkW7Qyx9yAk@wF%~vhHB}OQUbte4$d-#0MSvJ+~Q6O50VL7DRqPY)Fu`Ym}3@u|e@6 zq6ZP_)pAvza_eH=P-ykc4EOB{wETsuUyhI6f=wIL>*%P`Q*-ht03z@;Y7x=A4LHZF z>%=CxY;=5U1HbuAMLgg$`5puxen il*GqpJ{%g*MdRW<(V zp$a>A_h@ohsaTx1*R6xpsIu=R zuF|hJvneP{gZXe)N}XkNNJv3(Wig=LHciD)ezy+a9HL@=fI38^6ft#C1#2)@?}9tC za|;^h=o0{+y*HG_rTAyhu8QQOw(T^H3M>S0vQf_~v}RTDflqVb_A)Pe@Hx%_;z258 z={QIJnp%?7wt B$5LbLAzsi#oJIO(sY&lh+ z0^M3W*B7#6b*zISPBu(}hUA`R4Fg|I^8Gh=Xtord;VSfxgHo5Qp-Z3U1iz5)zqmdf zr8#+5mQ$@X9AnXEH}NXt##gI}IR63EzpeGVsNRPF!ec?#I1JmDS$ZV2cp9l#bI;@q zPnm76S8YUV{e$Zd2kY*27T=GOTpQRH2W7=hrlC?lKe?wdiVyF>IP?DWNcr6pRSqn3 zyZV%RD?ZxxF}-}GN>96IiW-IHTc-5#+!>I}e}dvUKYGwgs7BbQ0!*YhW?QOU{232d zK*8K*p-3GgBGrDzhxL1iKI2}as)4#>H)#2$B5h~L@IDN6Ys>lw9ECpe?XA{3HTh3J z%sNQLnXCF{zy*LV)(U3nt6FOVV!}6++2FTcZ=h5Qj<(&$MR5cx!9XdY(n!k^-L7;; zvIB$FafYj*PMh$9FLvuJ(xjDq*yj<4M(!8AV<)&C=kGx?ocbu vt zc$T^oa>YyB75-bNu-oGs&x@Bg$ERWVnX$Ww;EB;M_fk*v$qR#&-RCF9BShX>pjFJ6 zd54Vk>817I0X41%WkcKTiblQg)U?q!%7@jZA)q#21t(&xwomEBB;p6xoymj=_6}uE z(#yL|%VvyUMO&SmZ)TgdxQ!Im$ je*}<7Lg% zp?f5@_?7GPZRrs{luIpE7vCA2^!9RK?(*JWeu=Z2>`)X=eIJkiCv#y&5NG9M0EEE-zA|B?PY$Mk{JX+=mnl4GcG~xzK9KPE` z#*=C-yASmHoi&N5|LHk&dJWs-F8lkOiAXLH2N%<@NY0HdJ Q8tqnT+v8<@}7)4o>#0e0f)=_@S zvAoKdW2-vjBp6>dzV&)9CGJ_26d4z9XPM0? zdcf~w2Qu#dt0!RoCs{fPOu4L}q!jYH!Vri1VjZ%9xmn9?JJf94j_!w{<{1PYC#>Z+ z9KCd52<2I%v}Vp_3X>+R3YbAR5 wc$d2$yw}mMVo}?rk^+jY8VBC`3%o(h_IEh1ZYvJqR}Xg^ ze?J1swF*ea@C@rx#Bm<;?GUe< ?Qxl?Z=yL)Uf*>2&KdZN;`NRi-SWZ zeT_AVAC8ej0hM{|DUigb$Vl2=rS#OW8gS@#fO6DL&g>i8+|9(oMZ?_e;>=)t#;+}* z;%QXVZ^;)G-_Ho= tR_K;?} jLAoQz*u5#h;?D&k$=JuveSuV~NA}kAC>y*t7m?^a@&m5xLeVCa~1f1M?4OyUFnV zyfT7*k9H=8^j{I}&wEr*2271->klOfwygHu4}F14dzjHl+!Cw4oK0~0ss}2Edz8jv z2kRbo(cO*b%WrUxL*g<^F)kI40$!b9gL^HCnbY#$-uqFGenTS2JzotJO&$B#JJT;R zpNDCW9Fen7C)Gl?4hkkYvK#!qSKG}(*+bHF9nrs2FY+KehyQ2^p!It3W9BAr5qV=O zwMiQJ2}h~X)@wQlj7^;I+Ci3tAMV0Eml*q+&APdoBAf(}o?!hba~^e~)}P!1!+b(P zvfpwv4{}{St@e)S2aq(U&1~e Di R!x zRt@a?gZq#*>;YFS0#x7lIM)?5S7fd4B9L*L+_a&Gn}Yt^S3MI1L;0gXF1SwFvIP7M z+S%P;;7rSaj`4iYSz1t s|yc E7LHL7{(%e$wxEPXt1G)o`7Q9w2U)MqypA@}S0NoQmB0Og9Gw9`Y)td3T7XC5IHo znzVW(+U59}i0=9$>~58`uO*!lePnXW*R+vy+zbrs+t@tUh{FK8gQ*pGM`+|LNYXOw zTx^?Deb#SohiC 1E>mzgw+jl`VRM9I;xd{~pTBR9CLjvoY8Pu0=&~#R9h3xoZTliN8 z>W32&DuU6p{=VNMjyS)cF%TlO`-N$}NI~7FKKgkbxz#J{Thaub_OVF)SXq#jj^{KN zbcW_Uo#={y>C4&(S8(ADS6BKRuXy4Bz~?Ecc1+q@P`1&Sn3$Odbs5qOuJPs$N|8kh zjH&@|j91l%9@od>`}mwKzj}X-ue;`KI-b=%UKns+5$(6i&_wjSo_I 2vhSKL%>>TRJK7>-!z+NfFb9p7*IG=f4KtfN?`UBQIEmml>LHY)D*Ahr*8 zE`$ubTzo1KZ&kEi`=jrtY7Y&QK;ieZ!q4L0C!QsfCh-!$%Q+`E@=P3ePpR}RUo43@ zu2IdZn6{}YJUe`3e*Q&*{VKwHGB@3k@UX5b4LRqCLpY)!bR0eq1Juf@TiqB9_}iq~ z+uIJB3qD)MJyM4}0hdVjHE;3Q8VLNIjnV8cZ?pryYYUgJdyMN4^Iy`@WPKLj!M~<> zFpid89`4n2d0kPP`trA`F6KDYZK`g>l#YQ~z}$OJXvm_x5F$adQdZh6A@tO`Bj_>X zKy*