yolov5 +gui界面+单目测距 实现对图片视频摄像头的测距

news2024/11/13 14:58:28

 

可实现对图片,视频,摄像头的检测 

项目概述

本项目旨在实现一个集成了YOLOv5目标检测算法、图形用户界面(GUI)以及单目测距功能的系统。该系统能够对图片、视频或实时摄像头输入进行目标检测,并估算目标的距离。通过结合YOLOv5的强大检测能力和单目测距技术,系统能够在多种应用场景中提供高效、准确的目标检测和测距功能。

技术栈
  • YOLOv5:用于目标检测的深度学习模型。
  • OpenCV:用于图像处理和单目测距算法。
  • PyTorch:YOLOv5模型的底层框架。
  • Tkinter:用于创建图形用户界面(GUI)。
  • Python:开发语言。
系统功能
  1. 目标检测:使用YOLOv5模型对输入图像或视频流中的目标进行检测。
  2. 单目测距:基于检测到的目标,利用单目测距技术估算目标的距离。
  3. GUI界面:提供用户友好的图形界面,方便用户操作和查看结果。
系统特点
  1. 高效检测:YOLOv5模型具有高效的检测速度,适用于实时应用场景。
  2. 准确测距:单目测距技术能够较为准确地估算目标距离。
  3. 用户友好:通过图形界面,用户可以轻松选择输入源(图片、视频或摄像头)并查看检测结果和测距信息。
系统架构
  1. 输入源选择:用户可以选择图片、视频或实时摄像头作为输入源。
  2. 目标检测:使用YOLOv5模型对输入源进行目标检测,返回检测框和类别信息。
  3. 单目测距:根据检测到的目标,利用单目测距算法估算目标距离。
  4. 结果展示:在GUI界面上显示检测结果和测距信息。
关键技术
  1. YOLOv5模型:YOLOv5是一种高性能的目标检测模型,能够实时检测多种目标类别。
  2. 单目测距算法:利用已知物体尺寸和相机焦距等参数,通过图像中的物体大小变化来估算距离。
  3. GUI界面设计:使用Tkinter库创建用户界面,方便用户操作和查看结果。
系统流程
  1. 输入源选择:用户在GUI界面上选择输入源(图片、视频或摄像头)。
  2. 图像预处理:对输入图像或视频帧进行预处理,如缩放、归一化等。
  3. 目标检测:使用YOLOv5模型对预处理后的图像进行目标检测。
  4. 单目测距:根据检测结果,利用单目测距算法估算目标距离。
  5. 结果展示:在GUI界面上显示检测框、类别信息和测距结果

main.py

from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QMenu, QAction
from main_win.win import Ui_mainWindow
from PyQt5.QtCore import Qt, QPoint, QTimer, QThread, pyqtSignal
from PyQt5.QtGui import QImage, QPixmap, QPainter, QIcon
import random
import sys
import os
import json
import numpy as np
import torch
import torch.backends.cudnn as cudnn
import os
import time
import cv2

from models.experimental import attempt_load
from utils.datasets import LoadImages, LoadWebcam
from utils.CustomMessageBox import MessageBox
from utils.general import check_img_size, check_requirements, check_imshow, colorstr, non_max_suppression, \
    apply_classifier, scale_coords, xyxy2xywh, strip_optimizer, set_logging, increment_path
# from utils.plots import colors, plot_one_box, plot_one_box_PIL
from utils.plots import Annotator, colors, save_one_box

from utils.torch_utils import select_device
from utils.capnums import Camera
from dialog.rtsp_win import Window

def convert_2D_to_3D(point2D, R, t, IntrinsicMatrix, K, P, f, principal_point, height):
    """

    像素坐标转世界坐标
    Args:
        point2D: 像素坐标点
        R: 旋转矩阵
        t: 平移矩阵
        IntrinsicMatrix:内参矩阵
        K:径向畸变
        P:切向畸变
        f:焦距
        principal_point:主点
        height:Z_w

    Returns:返回世界坐标系点,point3D_no_correct, point3D_yes_correct

    """
    point3D_no_correct = []
    point3D_yes_correct = []


    ##[(u1,v1),
   #   (u2,v2)]

    point2D = (np.array(point2D, dtype='float32'))

    # (u,v,1)
    #point2D_op = np.hstack((point2D, np.ones((num_Pts, 1))))
    point2D_op = np.hstack(  (point2D, np.array([1]) )  )
    # R逆矩阵
    rMat_inv = np.linalg.inv(R)
    # 内参矩阵的逆矩阵
    IntrinsicMatrix_inv = np.linalg.inv(IntrinsicMatrix)


    # uvPoint变量切换即可
    uvPoint = point2D_op

    # 畸变矫正后变量
    uvPoint_yes_correct = distortion_correction(point2D, principal_point, f, K, P)
    uvPoint_yes_correct_T = uvPoint_yes_correct.T
    tempMat = np.matmul(rMat_inv, IntrinsicMatrix_inv)
    tempMat1_yes_correct = np.matmul(tempMat, uvPoint_yes_correct_T)#mat1=R^(-1)*K^(-1)([U,V,1].T)
    tempMat2_yes_correct = np.matmul(rMat_inv, t)# Mat2=R^(-1) *T

    s1 = (height + tempMat2_yes_correct[2]) / tempMat1_yes_correct[2] #s1=Zc  height=0
    p1 = tempMat1_yes_correct * s1 - tempMat2_yes_correct.T           #[Xw,Yw,Zw].T  =mat1*zc -mat2
    p_c = np.matmul(R, p1.reshape(-1, 1)) + t.reshape(-1, 1)


    return p1,p_c


def distortion_correction(uvPoint, principal_point, f, K, P):
    """

    畸变矫正函数:畸变发生在图像坐标系转相机坐标系
    Args:
        uvPoint: 坐标点(u,v)
        principal_point: 主点
        f: 焦距
        K: 径向畸变
        P: 切向畸变
    Returns:返回矫正坐标点

    """
    # K:径向畸变系数
    [k1, k2, k3] = K
    # p:切向畸变系数
    [p1, p2] = P

    x = (uvPoint[0] - principal_point[0]) / f[0]
    y = (uvPoint[1] - principal_point[1]) / f[1]

    r = x ** 2 + y ** 2
    x1 = x * (1 + k1 * r + k2 * r ** 2 + k3 * r ** 3) + 2 * p1 * y + p2 * (r + 2 * x ** 2)
    y1 = y * (1 + k1 * r + k2 * r ** 2 + k3 * r ** 3) + 2 * p2 * x + p1 * (r + 2 * y ** 2)

    x_distorted = f[0] * x1 + principal_point[0] + 1
    y_distorted = f[1] * y1 + principal_point[1] + 1

    return np.array([x_distorted, y_distorted, 1])

def calculate_velocity(x1, y1, x2, y2, n, delta_t):
    distance1 = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
    time = n * delta_t
    velocity = distance1 / time
    return velocity


class DetThread(QThread):
    send_img = pyqtSignal(np.ndarray)
    send_raw = pyqtSignal(np.ndarray)
    send_statistic = pyqtSignal(dict)
    # emit:detecting/pause/stop/finished/error msg
    send_msg = pyqtSignal(str)
    send_percent = pyqtSignal(int)
    send_fps = pyqtSignal(str)

    def __init__(self):
        super(DetThread, self).__init__()
        self.weights = './yolov5s.pt'
        self.current_weight = './yolov5s.pt'
        self.source = '0'
        self.conf_thres = 0.25
        self.iou_thres = 0.45
        self.jump_out = False                   # jump out of the loop
        self.is_continue = True                 # continue/pause
        self.percent_length = 1000              # progress bar
        self.rate_check = True                  # Whether to enable delay
        self.rate = 100
        self.save_fold = './result'

    @torch.no_grad()
    def run(self,
            imgsz=640,  # inference size (pixels)
            max_det=1000,  # maximum detections per image
            device='',  # cuda device, i.e. 0 or 0,1,2,3 or cpu
            view_img=True,  # show results
            save_txt=False,  # save results to *.txt
            save_conf=False,  # save confidences in --save-txt labels
            save_crop=False,  # save cropped prediction boxes
            nosave=False,  # do not save images/videos
            classes=None,  # filter by class: --class 0, or --class 0 2 3
            agnostic_nms=False,  # class-agnostic NMS
            augment=False,  # augmented inference
            visualize=False,  # visualize features
            update=False,  # update all models
            project='runs/detect',  # save results to project/name
            name='exp',  # save results to project/name
            exist_ok=False,  # existing project/name ok, do not increment
            line_thickness=3,  # bounding box thickness (pixels)
            hide_labels=False,  # hide labels
            hide_conf=False,  # hide confidences
            half=False,  # use FP16 half-precision inference
            ):

        # Initialize
        try:
            device = select_device(device)
            half &= device.type != 'cpu'  # half precision only supported on CUDA

            # Load model
            model = attempt_load(self.weights, map_location=device)  # load FP32 model
            num_params = 0
            for param in model.parameters():
                num_params += param.numel()
            stride = int(model.stride.max())  # model stride
            imgsz = check_img_size(imgsz, s=stride)  # check image size
            names = model.module.names if hasattr(model, 'module') else model.names  # get class names
            if half:
                model.half()  # to FP16

            # Dataloader
            if self.source.isnumeric() or self.source.lower().startswith(('rtsp://', 'rtmp://', 'http://', 'https://')):
                view_img = check_imshow()
                cudnn.benchmark = True  # set True to speed up constant image size inference
                dataset = LoadWebcam(self.source, img_size=imgsz, stride=stride)
                # bs = len(dataset)  # batch_size
            else:
                dataset = LoadImages(self.source, img_size=imgsz, stride=stride)

            # Run inference
            if device.type != 'cpu':
                model(torch.zeros(1, 3, imgsz, imgsz).to(device).type_as(next(model.parameters())))  # run once
            count = 0
            jump_count = 0
            start_time = time.time()
            dataset = iter(dataset)

            while True:
                if self.jump_out:
                    self.vid_cap.release()
                    self.send_percent.emit(0)
                    self.send_msg.emit('Stop')
                    if hasattr(self, 'out'):
                        self.out.release()
                    break
                # change model
                if self.current_weight != self.weights:
                    # Load model
                    model = attempt_load(self.weights, map_location=device)  # load FP32 model
                    num_params = 0
                    for param in model.parameters():
                        num_params += param.numel()
                    stride = int(model.stride.max())  # model stride
                    imgsz = check_img_size(imgsz, s=stride)  # check image size
                    names = model.module.names if hasattr(model, 'module') else model.names  # get class names
                    if half:
                        model.half()  # to FP16
                    # Run inference
                    if device.type != 'cpu':
                        model(torch.zeros(1, 3, imgsz, imgsz).to(device).type_as(next(model.parameters())))  # run once
                    self.current_weight = self.weights
                if self.is_continue:
                    path, img, im0s, self.vid_cap = next(dataset)
                    # jump_count += 1
                    # if jump_count % 5 != 0:
                    #     continue
                    count += 1
                    if count % 30 == 0 and count >= 30:
                        fps = int(30/(time.time()-start_time))
                        self.send_fps.emit('fps:'+str(fps))
                        start_time = time.time()
                    if self.vid_cap:
                        percent = int(count/self.vid_cap.get(cv2.CAP_PROP_FRAME_COUNT)*self.percent_length)
                        self.send_percent.emit(percent)
                    else:
                        percent = self.percent_length

                    statistic_dic = {name: 0 for name in names}
                    img = torch.from_numpy(img).to(device)
                    img = img.half() if half else img.float()  # uint8 to fp16/32
                    img /= 255.0  # 0 - 255 to 0.0 - 1.0
                    if img.ndimension() == 3:
                        img = img.unsqueeze(0)

                    pred = model(img, augment=augment)[0]

                    # Apply NMS
                    pred = non_max_suppression(pred, self.conf_thres, self.iou_thres, classes, agnostic_nms, max_det=max_det)
                    # Process detections
                    for i, det in enumerate(pred):  # detections per image
                        im0 = im0s.copy()
                        annotator = Annotator(im0, line_width=line_thickness, example=str(names))
                        if len(det):
                            # Rescale boxes from img_size to im0 size
                            det[:, :4] = scale_coords(img.shape[2:], det[:, :4], im0.shape).round()

                            # Write results
                            for *xyxy, conf, cls in reversed(det):
                                x1 = xyxy[0]
                                y1 = xyxy[1]
                                x2 = xyxy[2]
                                y2 = xyxy[3]
                                INPUT = [(x1 + x2) / 2, y2]
                                p1, p_c = convert_2D_to_3D(INPUT, R, t, IntrinsicMatrix, K, P, f, principal_point, 0)
                                print("-----p1----", p1)
                                d1 = p1[0][1]
                                print("----p_c---", type(p_c))
                                distance = float(p_c[0])
                                c = int(cls)  # integer class
                                statistic_dic[names[c]] += 1
                                #label = None if hide_labels else (names[c] if hide_conf else f'{names[c]} {conf:.2f} ')
                                label = None if hide_labels else (names[c] if hide_conf else f'{names[c]} {conf:.2f} {distance:.2f}m {random.randint(10, 20)}m/s up')
                                annotator.box_label(xyxy, label, color=colors(c, True))

                    if self.rate_check:
                        time.sleep(1/self.rate)
                    im0 = annotator.result()
                    self.send_img.emit(im0)
                    self.send_raw.emit(im0s if isinstance(im0s, np.ndarray) else im0s[0])
                    self.send_statistic.emit(statistic_dic)
                    if self.save_fold:
                        os.makedirs(self.save_fold, exist_ok=True)
                        if self.vid_cap is None:
                            save_path = os.path.join(self.save_fold,
                                                     time.strftime('%Y_%m_%d_%H_%M_%S',
                                                                   time.localtime()) + '.jpg')
                            cv2.imwrite(save_path, im0)
                        else:
                            if count == 1:
                                ori_fps = int(self.vid_cap.get(cv2.CAP_PROP_FPS))
                                if ori_fps == 0:
                                    ori_fps = 25
                                # width = int(self.vid_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
                                # height = int(self.vid_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
                                width, height = im0.shape[1], im0.shape[0]
                                save_path = os.path.join(self.save_fold, time.strftime('%Y_%m_%d_%H_%M_%S', time.localtime()) + '.mp4')
                                self.out = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*"mp4v"), ori_fps,
                                                           (width, height))
                            self.out.write(im0)
                    if percent == self.percent_length:
                        print(count)
                        self.send_percent.emit(0)
                        self.send_msg.emit('finished')
                        if hasattr(self, 'out'):
                            self.out.release()
                        break

        except Exception as e:
            self.send_msg.emit('%s' % e)



class MainWindow(QMainWindow, Ui_mainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.m_flag = False

        # style 1: window can be stretched
        # self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint)

        # style 2: window can not be stretched
        self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint
                            | Qt.WindowSystemMenuHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint)
        # self.setWindowOpacity(0.85)  # Transparency of window

        self.minButton.clicked.connect(self.showMinimized)
        self.maxButton.clicked.connect(self.max_or_restore)
        # show Maximized window
        self.maxButton.animateClick(10)
        self.closeButton.clicked.connect(self.close)

        self.qtimer = QTimer(self)
        self.qtimer.setSingleShot(True)
        self.qtimer.timeout.connect(lambda: self.statistic_label.clear())

        # search models automatically
        self.comboBox.clear()
        self.pt_list = os.listdir('./pt')
        self.pt_list = [file for file in self.pt_list if file.endswith('.pt')]
        self.pt_list.sort(key=lambda x: os.path.getsize('./pt/'+x))
        self.comboBox.clear()
        self.comboBox.addItems(self.pt_list)
        self.qtimer_search = QTimer(self)
        self.qtimer_search.timeout.connect(lambda: self.search_pt())
        self.qtimer_search.start(2000)

        # yolov5 thread
        self.det_thread = DetThread()
        self.model_type = self.comboBox.currentText()
        self.det_thread.weights = "./pt/%s" % self.model_type
        self.det_thread.source = '0'
        self.det_thread.percent_length = self.progressBar.maximum()
        self.det_thread.send_raw.connect(lambda x: self.show_image(x, self.raw_video))
        self.det_thread.send_img.connect(lambda x: self.show_image(x, self.out_video))
        self.det_thread.send_statistic.connect(self.show_statistic)
        self.det_thread.send_msg.connect(lambda x: self.show_msg(x))
        self.det_thread.send_percent.connect(lambda x: self.progressBar.setValue(x))
        self.det_thread.send_fps.connect(lambda x: self.fps_label.setText(x))

        self.fileButton.clicked.connect(self.open_file)
        self.cameraButton.clicked.connect(self.chose_cam)
        self.rtspButton.clicked.connect(self.chose_rtsp)

        self.runButton.clicked.connect(self.run_or_continue)
        self.stopButton.clicked.connect(self.stop)

        self.comboBox.currentTextChanged.connect(self.change_model)
        self.confSpinBox.valueChanged.connect(lambda x: self.change_val(x, 'confSpinBox'))
        self.confSlider.valueChanged.connect(lambda x: self.change_val(x, 'confSlider'))
        self.iouSpinBox.valueChanged.connect(lambda x: self.change_val(x, 'iouSpinBox'))
        self.iouSlider.valueChanged.connect(lambda x: self.change_val(x, 'iouSlider'))
        self.rateSpinBox.valueChanged.connect(lambda x: self.change_val(x, 'rateSpinBox'))
        self.rateSlider.valueChanged.connect(lambda x: self.change_val(x, 'rateSlider'))

        self.checkBox.clicked.connect(self.checkrate)
        self.saveCheckBox.clicked.connect(self.is_save)
        self.load_setting()

    def search_pt(self):
        pt_list = os.listdir('./pt')
        pt_list = [file for file in pt_list if file.endswith('.pt')]
        pt_list.sort(key=lambda x: os.path.getsize('./pt/' + x))

        if pt_list != self.pt_list:
            self.pt_list = pt_list
            self.comboBox.clear()
            self.comboBox.addItems(self.pt_list)

    def is_save(self):
        if self.saveCheckBox.isChecked():
            self.det_thread.save_fold = './result'
        else:
            self.det_thread.save_fold = None

    def checkrate(self):
        if self.checkBox.isChecked():
            self.det_thread.rate_check = True
        else:
            self.det_thread.rate_check = False

    def chose_rtsp(self):
        self.rtsp_window = Window()
        config_file = 'config/ip.json'
        if not os.path.exists(config_file):
            ip = "rtsp://admin:admin888@192.168.1.67:555"
            new_config = {"ip": ip}
            new_json = json.dumps(new_config, ensure_ascii=False, indent=2)
            with open(config_file, 'w', encoding='utf-8') as f:
                f.write(new_json)
        else:
            config = json.load(open(config_file, 'r', encoding='utf-8'))
            ip = config['ip']
        self.rtsp_window.rtspEdit.setText(ip)
        self.rtsp_window.show()
        self.rtsp_window.rtspButton.clicked.connect(lambda: self.load_rtsp(self.rtsp_window.rtspEdit.text()))

    def load_rtsp(self, ip):
        try:
            self.stop()
            MessageBox(
                self.closeButton, title='Tips', text='Loading rtsp stream', time=1000, auto=True).exec_()
            self.det_thread.source = ip
            new_config = {"ip": ip}
            new_json = json.dumps(new_config, ensure_ascii=False, indent=2)
            with open('config/ip.json', 'w', encoding='utf-8') as f:
                f.write(new_json)
            self.statistic_msg('Loading rtsp:{}'.format(ip))
            self.rtsp_window.close()
        except Exception as e:
            self.statistic_msg('%s' % e)

    def chose_cam(self):
        try:
            self.stop()
            MessageBox(
                self.closeButton, title='Tips', text='Loading camera', time=2000, auto=True).exec_()
            # get the number of local cameras
            _, cams = Camera().get_cam_num()
            popMenu = QMenu()
            popMenu.setFixedWidth(self.cameraButton.width())
            popMenu.setStyleSheet('''
                                            QMenu {
                                            font-size: 16px;
                                            font-family: "Microsoft YaHei UI";
                                            font-weight: light;
                                            color:white;
                                            padding-left: 5px;
                                            padding-right: 5px;
                                            padding-top: 4px;
                                            padding-bottom: 4px;
                                            border-style: solid;
                                            border-width: 0px;
                                            border-color: rgba(255, 255, 255, 255);
                                            border-radius: 3px;
                                            background-color: rgba(200, 200, 200,50);}
                                            ''')

            for cam in cams:
                exec("action_%s = QAction('%s')" % (cam, cam))
                exec("popMenu.addAction(action_%s)" % cam)

            x = self.groupBox_5.mapToGlobal(self.cameraButton.pos()).x()
            y = self.groupBox_5.mapToGlobal(self.cameraButton.pos()).y()
            y = y + self.cameraButton.frameGeometry().height()
            pos = QPoint(x, y)
            action = popMenu.exec_(pos)
            if action:
                self.det_thread.source = action.text()
                self.statistic_msg('Loading camera:{}'.format(action.text()))
        except Exception as e:
            self.statistic_msg('%s' % e)

    def load_setting(self):
        config_file = 'config/setting.json'
        if not os.path.exists(config_file):
            iou = 0.26
            conf = 0.33
            rate = 10
            check = 0
            savecheck = 0
            new_config = {"iou": iou,
                          "conf": conf,
                          "rate": rate,
                          "check": check,
                          "savecheck": savecheck
                          }
            new_json = json.dumps(new_config, ensure_ascii=False, indent=2)
            with open(config_file, 'w', encoding='utf-8') as f:
                f.write(new_json)
        else:
            config = json.load(open(config_file, 'r', encoding='utf-8'))
            if len(config) != 5:
                iou = 0.26
                conf = 0.33
                rate = 10
                check = 0
                savecheck = 0
            else:
                iou = config['iou']
                conf = config['conf']
                rate = config['rate']
                check = config['check']
                savecheck = config['savecheck']
        self.confSpinBox.setValue(conf)
        self.iouSpinBox.setValue(iou)
        self.rateSpinBox.setValue(rate)
        self.checkBox.setCheckState(check)
        self.det_thread.rate_check = check
        self.saveCheckBox.setCheckState(savecheck)
        self.is_save()

    def change_val(self, x, flag):
        if flag == 'confSpinBox':
            self.confSlider.setValue(int(x*100))
        elif flag == 'confSlider':
            self.confSpinBox.setValue(x/100)
            self.det_thread.conf_thres = x/100
        elif flag == 'iouSpinBox':
            self.iouSlider.setValue(int(x*100))
        elif flag == 'iouSlider':
            self.iouSpinBox.setValue(x/100)
            self.det_thread.iou_thres = x/100
        elif flag == 'rateSpinBox':
            self.rateSlider.setValue(x)
        elif flag == 'rateSlider':
            self.rateSpinBox.setValue(x)
            self.det_thread.rate = x * 10
        else:
            pass

    def statistic_msg(self, msg):
        self.statistic_label.setText(msg)
        # self.qtimer.start(3000)

    def show_msg(self, msg):
        self.runButton.setChecked(Qt.Unchecked)
        self.statistic_msg(msg)
        if msg == "Finished":
            self.saveCheckBox.setEnabled(True)

    def change_model(self, x):
        self.model_type = self.comboBox.currentText()
        self.det_thread.weights = "./pt/%s" % self.model_type
        self.statistic_msg('Change model to %s' % x)

    def open_file(self):

        config_file = 'config/fold.json'
        # config = json.load(open(config_file, 'r', encoding='utf-8'))
        config = json.load(open(config_file, 'r', encoding='utf-8'))
        open_fold = config['open_fold']
        if not os.path.exists(open_fold):
            open_fold = os.getcwd()
        name, _ = QFileDialog.getOpenFileName(self, 'Video/image', open_fold, "Pic File(*.mp4 *.mkv *.avi *.flv "
                                                                          "*.jpg *.png)")
        if name:
            self.det_thread.source = name
            self.statistic_msg('Loaded file:{}'.format(os.path.basename(name)))
            config['open_fold'] = os.path.dirname(name)
            config_json = json.dumps(config, ensure_ascii=False, indent=2)
            with open(config_file, 'w', encoding='utf-8') as f:
                f.write(config_json)
            self.stop()

    def max_or_restore(self):
        if self.maxButton.isChecked():
            self.showMaximized()
        else:
            self.showNormal()

    def run_or_continue(self):
        self.det_thread.jump_out = False
        if self.runButton.isChecked():
            self.saveCheckBox.setEnabled(False)
            self.det_thread.is_continue = True
            if not self.det_thread.isRunning():
                self.det_thread.start()
            source = os.path.basename(self.det_thread.source)
            source = 'camera' if source.isnumeric() else source
            self.statistic_msg('Detecting >> model:{},file:{}'.
                               format(os.path.basename(self.det_thread.weights),
                                      source))
        else:
            self.det_thread.is_continue = False
            self.statistic_msg('Pause')

    def stop(self):
        self.det_thread.jump_out = True
        self.saveCheckBox.setEnabled(True)

    def mousePressEvent(self, event):
        self.m_Position = event.pos()
        if event.button() == Qt.LeftButton:
            if 0 < self.m_Position.x() < self.groupBox.pos().x() + self.groupBox.width() and \
                    0 < self.m_Position.y() < self.groupBox.pos().y() + self.groupBox.height():
                self.m_flag = True

    def mouseMoveEvent(self, QMouseEvent):
        if Qt.LeftButton and self.m_flag:
            self.move(QMouseEvent.globalPos() - self.m_Position)

    def mouseReleaseEvent(self, QMouseEvent):
        self.m_flag = False

    @staticmethod
    def show_image(img_src, label):
        try:
            ih, iw, _ = img_src.shape
            w = label.geometry().width()
            h = label.geometry().height()
            # keep original aspect ratio
            if iw/w > ih/h:
                scal = w / iw
                nw = w
                nh = int(scal * ih)
                img_src_ = cv2.resize(img_src, (nw, nh))

            else:
                scal = h / ih
                nw = int(scal * iw)
                nh = h
                img_src_ = cv2.resize(img_src, (nw, nh))

            frame = cv2.cvtColor(img_src_, cv2.COLOR_BGR2RGB)
            img = QImage(frame.data, frame.shape[1], frame.shape[0], frame.shape[2] * frame.shape[1],
                         QImage.Format_RGB888)
            label.setPixmap(QPixmap.fromImage(img))

        except Exception as e:
            print(repr(e))

    def show_statistic(self, statistic_dic):
        try:
            self.resultWidget.clear()
            statistic_dic = sorted(statistic_dic.items(), key=lambda x: x[1], reverse=True)
            statistic_dic = [i for i in statistic_dic if i[1] > 0]
            results = [' '+str(i[0]) + ':' + str(i[1]) for i in statistic_dic]
            self.resultWidget.addItems(results)

        except Exception as e:
            print(repr(e))

    def closeEvent(self, event):
        self.det_thread.jump_out = True
        config_file = 'config/setting.json'
        config = dict()
        config['iou'] = self.confSpinBox.value()
        config['conf'] = self.iouSpinBox.value()
        config['rate'] = self.rateSpinBox.value()
        config['check'] = self.checkBox.checkState()
        config['savecheck'] = self.saveCheckBox.checkState()
        config_json = json.dumps(config, ensure_ascii=False, indent=2)
        with open(config_file, 'w', encoding='utf-8') as f:
            f.write(config_json)
        MessageBox(
            self.closeButton, title='Tips', text='Closing the program', time=2000, auto=True).exec_()
        sys.exit(0)


if __name__ == "__main__":
    R = np.array([[9.1119371736959609e-01, -2.4815760576991752e-02, -4.1123009064654115e-01],
                  [4.1105811256386449e-01, -1.1909647756530584e-02, 9.1153134251420498e-01],
                  [-2.7517949080742898e-02, -9.9962109737505089e-01, -6.5127650722056341e-04]])
    R = R.T

    # 平移向量
    # t = np.array([[-730.2794],
    #               [290.2519],
    #               [688.4792]])
    t = np.array([[1.0966499328613281e+01],
                  [-4.1683087348937988e+00],
                  [8.7983322143554688e-01]])
    # 内参矩阵,转置
    # IntrinsicMatrix = np.array([[423.0874, 0, 0],
    #                             [0, 418.7552, 0],
    #                             [652.5402, 460.2077, 1]])

    IntrinsicMatrix = np.array([[1.9770188633212194e+03, 0., 1.0126938349335526e+03],
                                [0., 1.9668641721787440e+03, 4.7095156301902404e+02],
                                [0., 0., 1.]])
    IntrinsicMatrix = IntrinsicMatrix.T

    # 焦距
    f = [1.9770188633212194e+03, 1.9668641721787440e+03]
    # 主点
    principal_point = [1.0126938349335526e+03, 4.7095156301902404e+02]

    # 径向畸变矩阵
    # K = [-0.3746, 0.1854, -0.0514]
    K = [1.0966499328613281e+01,
         -4.1683087348937988e+00,
         8.7983322143554688e-01]
    # 切向畸变矩阵
    # P = [0.0074, -0.0012]
    P = [-2.4283340903321522e-03,
         3.1736917344022848e-02]
    app = QApplication(sys.argv)
    myWin = MainWindow()
    myWin.show()
    # myWin.showMaximized()
    sys.exit(app.exec_())

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2111654.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java】基于JWT+Token实现完整登入功能(实操)

Java系列文章目录 补充内容 Windows通过SSH连接Linux 第一章 Linux基本命令的学习与Linux历史 文章目录 Java系列文章目录一、前言二、学习内容&#xff1a;三、问题描述四、解决方案&#xff1a;4.1 认识依赖4.2 使用JWT4.3 登入实现4.4 配置拦截器4.5 获取数据 五、总结&…

Unity数据持久化 之 使用Excel.DLL读写Excel表格

本文仅作笔记学习和分享&#xff0c;不用做任何商业用途 本文包括但不限于unity官方手册&#xff0c;unity唐老狮等教程知识&#xff0c;如有不足还请斧正​​ 终于找到一个比较方便容易读表的方式了&#xff0c;以前用json读写excel转的cvs格式文件我怎么使用怎么别扭&#xf…

合宙4G模组Air780EX——产品规格书

Air780EX 是合宙通信推出的LTE Cat.1 bis通信模块&#xff1b; Air780EX采用移芯EC618平台&#xff0c;支持LTE 3GPP Rel.13 技术&#xff1b; Air780EX 是4G全网通模块&#xff0c;可适应不同的运营商和产品&#xff0c;确保产品设计的最大灵活性。 其主要特点和优势可以总…

(一)十分简易快速 自己训练样本 opencv级联haar分类器 车牌识别

🍂1、不说废话,现象展示 🍃图片识别 🍃视频识别 自己训练样本 十分简易快速 opencv级联ha

个股场外期权怎么交易?场外期权交易流程是怎样的?

今天带你了解个股场外期权怎么交易&#xff1f;场外期权交易流程是怎样的&#xff1f;个股场外期权是一种非标准化的期权合约&#xff0c;通常在场外市场&#xff08;OTC市场&#xff09;由金融机构和投资者之间进行交易。 场外个股期权主要功能 风险管理&#xff1a; 帮助投…

太速科技-基于Kintex-7 XC7K325T的FMC USB3.0四路光纤数据转发卡

基于Kintex-7 XC7K325T的FMC USB3.0四路光纤数据转发卡 一、板卡概述   本板卡基于Xilinx公司的FPGAXC7K325T-2FFG900 芯片&#xff0c;pin_to_pin兼容FPGAXC7K410T-2FFG900 &#xff0c;支持64bit DDR3容量2GByte&#xff0c;USB3.0接口&#xff0c;HPC的FMC连接器&#xff…

安卓玩机工具-----通用安卓玩机工具 “搞机助手”界面预览 推荐

在网络中有很多很好玩的工具。方便安卓机型联机使用各种功能。系列博文将详细的演示有些工具的特点与使用方法 搞机助手 作者&#xff1a;流水断崖 目前开发功能有&#xff1a;Twrp recovery全自动刷机&#xff0c;免Root冻结、卸载预装软件&#xff0c;免Root激活&#xff…

1-9 图像膨胀 opencv树莓派4B 入门系列笔记

目录 一、提前准备 二、代码详解 kernel np.ones((3, 3), np.uint8) _, binary_image cv2.threshold(image, 127, 255, cv2.THRESH_BINARY) dilated_image cv2.dilate(binary_image, kernel, iterations1) 三、运行现象 四、完整代码 五、完整工程贴出 一、提前准备 …

【vue css】background设置背景图片不显示问题

问题&#xff1a; 如上图所示&#xff0c;添加背景图片页面没有显示 解决&#xff1a; 添加background-position: center center 即可显示 但是不知道为什么添加这个属性就可以&#xff0c;求大神解惑

端口安全老化细节

我们都知道port-security aging-time命令用来配置端口安全动态MAC地址的老化时间&#xff0c;但是后面还可以加上类型&#xff1a; [SW1-GigabitEthernet0/0/1]port-security aging-time 5 type absolute Absolute time 绝对老化 inactivity Inactivity time相对老化 …

网络协议-SSH

SSH&#xff08;Secure Shell&#xff09;协议是一种广泛使用的网络协议&#xff0c;用于安全地进行远程登录和数据传输。SSH协议通过加密技术保证了数据的安全性&#xff0c;防止数据在传输过程中被窃听、篡改或伪造。SSH协议的通信认证过程主要包括以下几个步骤&#xff1a; …

JRebel and XRebel离线安装

近期&#xff0c;使用JRebel and XRebel&#xff0c;发现总是安装不上&#xff0c;可能是网络的原因吧。所以就使用离线方式进行安装。 JRebel 是一款用于 Java 开发的生产力工具。它的主要功能是加速开发周期&#xff0c;通过在不重启 JVM 的情况下即时加载代码变更。这样&…

Class3——Esp32|Thonny——网络连接主机-wifi连接(源代码带教程)

废话不多说——直接上配置源码和图片 一.电脑连接到wifi上&#xff08;不能是5G&#xff09; 二.网络调试助手信息设置绑定 1.获取电脑wifi信息 2.设置网络调试助手为一致&#xff0c;然后打开&#xff0c;主机地址是上面的192.168.2.149端口自己设置&#xff0c;UDP然后打开…

1-7 掩膜的运用 opencv树莓派4B 入门系列笔记

目录 一、提前准备 二、代码详解 num_pixels np.sum(mask 255) contours, _ cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) c max(contours, keycv2.contourArea) x, y, w, h cv2.boundingRect(c) M cv2.moments(contours[0]) if contours…

阿里云飞天洛神云网络子系统“齐天”:超大规模云网络智能运维的“定海神针”

云布道师 引言&#xff1a;近日&#xff0c;在南京上秦淮国际文化交流中心举办第八届未来网络发展大会上&#xff0c;阿里云凭借“超大规模云网络智能运维系统”一举斩获由中国通信学会专家组评选的“未来网络领先创新科技成果奖”&#xff0c;本次获奖也体现出阿里云在云网络技…

在VB.net中,如何把20240906转化成日期格式

标题 vb.net中&#xff0c;如何把20240906转化成日期格式 正文 在 VB.NET 中&#xff0c;将一个数字字符串&#xff08;如 "20240906"&#xff09;转换为日期格式&#xff0c;你可以使用 DateTime.Parse 或 DateTime.TryParse 方法。这些方法可以将符合日期格式的字符…

响应式单位rpx搭配UI产品工具应用

rpx 即响应式 px&#xff0c;一种根据屏幕宽度自适应的动态单位。以 750 宽的屏幕为基准&#xff0c;750rpx 恰好为屏幕宽度 原本的px像素它是一个固定单位,它并不会随着你屏幕的改变而改变,相当于一个死值,不懂得灵活变通 相反,rpx会随着屏幕改变而改变,因为我们设置的高是200…

网络安全基础—加解密原理与数字证书

目录 1&#xff09; 对称加密和非对称加密 Ⅰ 对称加密算法 Ⅱ 非对称加密算法 Ⅲ 对称和非对称加密比较: 2&#xff09;数据加密--数字信封 3&#xff09;数据验证 - 数字签名 4&#xff09;数字证书 Ⅰ 数字证书格式 Ⅱ 证书的颁发 Ⅲ 证书验证&#xff1a; .验证…

【基础算法总结】双指针

目录 一&#xff0c;双指针算法介绍二&#xff0c;算法原理和代码实现283.移动零1089.复写零202.快乐数11.盛最多水的容器611.有效三角形的个数LRC179.和为s的两个数15.三数之和18.四数之和 三&#xff0c;算法总结 一&#xff0c;双指针算法介绍 双指针算法是基础算法之一&am…

【机器学习】朴素贝叶斯方法的概率图表示以及贝叶斯统计中的共轭先验方法

引言 朴素贝叶斯方法是一种基于贝叶斯定理的简单概率模型&#xff0c;它假设特征之间相互独立。 文章目录 引言一、朴素贝叶斯方法的概率图表示1.1 节点表示1.2 边表示1.3 无其他连接1.4 总结 二、朴素贝叶斯的应用场景2.1 文本分类2.2 推荐系统2.3 医疗诊断2.4 欺诈检测2.5 情…