基于PyQt5&YOLOv4-tiny的目标检测系统

目录

一、项目整体效果图

二、项目流程简介

三、项目功能模块介绍

 Github地址: linluocheng/Detect_YOLOV4-tiny (github.com)


PS:此项目来自我朋友,这里只是作个介绍,源码在github上,我朋友的b站号名字为CiLang,有兴趣可以去关注。

一、项目整体效果图

二、项目流程简介

  • 根据数据集打标签,进行模型训练
  • 利用模型权重weights以及Yolov4-tiny.cfg结合,通过opencv写预测代码Detect.py
  • 使用QTDesigner设置UI界面,并通过PyUIC转为PyQt5代码,方便后期加功能。
  • 为UI界面的各个控件添加对应的槽方法。
  • 最后编写主函数,并在主函数中实现UI界面的控件槽方法,运行整个项目。

三、项目功能模块介绍

文件夹文件一览:

以文件夹中的文件的顺序介绍模块:

(一)DetectModel

PS:模型训练需要大量的时间,准确率也不能保证,于是该模块训练的模型即权重是直接从油管上获取的;

        1.classes.txt

 

该文件中包含了本模型中所有可以识别的种类,共有80个。

        2.yolov4-tiny.cfg

分为Net层、卷积层、下采样、shortcut和route层、上采样和池化层YOLO层网络模型参数,用于目标的预测推理。

        3.yolov4-tiny.weights

由大量的数据集进行深度学习YOLOv4-tiny算法根据类别训练出的模型。

(二)IMG

在各大图标库中找到的图标:

      PS:该图片标签在本项目中用于表示项目的是否开始检测状态。                 

未开始检测的状态:     开始检测的状态:

(三)Lib

        1.QRC_rc.py

由于在QTDesigner中使用了额外的图片,在进行保存PyUIC工具转.py文件时,会出现QRC_rc.py这个文件,用于图像的格式转换。

        2.UI_From.py

UI界面控件展示图

通过PyUIC工具将QTDesigner的UI文件转为UI_From.py的PyQt5代码格式

(四)Detect.py

        1.通过opencv的dnn.readNet()函数构造Darknet53网络传入模型结构cfg文件以及模型权重weights文件,使用cv2.dnn_DetectionModel()传入网络模型。

net = cv2.dnn.readNet("DetectModel/yolov4-tiny.weights", "DetectModel/yolov4-tiny.cfg")
model = cv2.dnn_DetectionModel(net)
model.setInputParams(size=(320, 320), scale=1 / 255)

        2.将类别文件中所有的类别录入classes列表

classes = []
with open("DetectModel/classes.txt", "r") as file_object:
     for class_name in file_object.readlines():
             class_name = class_name.strip()
                classes.append(class_name)

        3.通过模型进行图像物体的预测

frame = img
(class_ids, scores, bboxes) = model.detect(frame, confThreshold=0.3, nmsThreshold=.4)

        4.将识别出的物体使用bboxes进行框选,并将检测的类别class_ids,置信评分scores,画到每帧的视频流上。

框选物体前

框选物体后

(五)Main.py

        1.先导入依赖的包以及Lib文件夹下UI文件UI_From.py的主窗口函数Ui_MainWindow

        2.槽方法介绍

def TimeConnet(self):
    self.timer_video.timeout.connect(self.Show_Video_Frame)
def Show_Video_Frame(self):
    global Temp_Sign_Change
    if Temp_Sign_Change == 0:
        flag, img = self.cap.read()
        if img is not None:
            self.label_Information.setText('No Detection')
            show = cv2.resize(img, (640, 480))  

            self.result = cv2.cvtColor(show, cv2.COLOR_BGR2RGB)
            showImage = QtGui.QImage(self.result.data, self.result.shape[1], self.result.shape[0],
                                     QtGui.QImage.Format_RGB888)
            self.label_MP4.setPixmap(QtGui.QPixmap.fromImage(showImage))
            self.label_MP4.setScaledContents(True)  
    else:
        flag, img = self.cap.read()
        img, List = Detect.Detcetion(None, img)
        Len_List = len(List)
        print('检测到',List)
        if img is not None:
            self.label.setFont(QFont("Roman times", 50, QFont.Bold))  # 字体大小
            strT = '<span style=\" color: #ff4500;\">%s</span>' % ("检测到"+str(Len_List)+"个对象\n")
            self.label_Information.setText("%s" % (strT))
            show = cv2.resize(img, (640, 480))  

            self.result = cv2.cvtColor(show, cv2.COLOR_BGR2RGB)
            showImage = QtGui.QImage(self.result.data, self.result.shape[1], self.result.shape[0],
                                     QtGui.QImage.Format_RGB888)
            self.label_MP4.setPixmap(QtGui.QPixmap.fromImage(showImage))
            self.label_MP4.setScaledContents(True)

TimeConnect连接Show_Video_Frame,由定时器控制label_MP4的视频流的显示,Temp_Sign_Change是全局变量,当其为0,就是未检测状态,为1就是检测状态。将视频信息以640,480的尺寸格式自适应大小显示到label_MP4控件上。如果为未检测状态,在label_Information控件上显示No Detection,如果检测到了,使用Detect.py中的Detection文件,对此时的视频流的图片进行检测,然后检测到的结果信息以检测到多少对象显示在label_Information控件上。

def Exit(self):
    sys.exit(app.exec_())

Exit连接Btn_Video_Finish按钮,只要点击就会退出整个界面。

def Pause(self): #暂停
    self.timer_video.blockSignals(False)
    if self.timer_video.isActive() == True and self.num_stop % 2 == 1:
        self.Btn_Video_2.setText(u'暂停检测')  # 当前状态为暂停状态
        self.num_stop = self.num_stop + 1  # 调整标记信号为偶数
        self.timer_video.blockSignals(True)
    else:
        self.num_stop = self.num_stop + 1
        self.Btn_Video_2.setText(u'继续检测')

Pause连接Btn_Video_2,只要点击,首先允许进行QTimer定时器的信号接收,即默认显示视频页面,num_stop代表着此时的是否为暂停状态,奇数代表暂停,偶数为继续显示,初始状态为显示状态。

def Finish(self): #结束检测
    self.cap.release()  # 释放video_capture资源
    self.label_MP4.clear()
    if self.num_stop % 2 == 0:
        self.Btn_Video_2.setText(u'暂停检测')
        self.num_stop = self.num_stop + 1
        self.timer_video.blockSignals(False)

Finish连接Btn_Video_Finish按钮,一旦点击,首先释放摄像头资源,然后进行label_MP4的图像显示控件的资源清除,如果此时num_stop为偶数,就暂停定时器的信号接收,即退出视频流的显示。

def OpenCerama(self): #打开摄像头
    camera_num = 0
    self.cap = cv2.VideoCapture(camera_num)
    # 判断摄像头是否处于打开状态
    bool_open = self.cap.isOpened()
    if not bool_open:
        QtWidgets.QMessageBox.warning(self, u"Warning", u"打开摄像头失败", buttons=QtWidgets.QMessageBox.Ok,
                                      defaultButton=QtWidgets.QMessageBox.Ok)
    else:
        self.timer_video.start(30)

OpenCerama连接Btn_Video,一旦点击就会打开默认的摄像头,如果打开失败就QMessageBox显示打开失败,否则就设置时间间隔30ms。

def OpenMp4(self): #打开视频
    video_name, _ = QtWidgets.QFileDialog.getOpenFileName(self, "打开视频", "data/", "*.mp4;;*.avi;;All Files(*)")
    flag = self.cap.open(video_name)
    if not flag:
        QtWidgets.QMessageBox.warning(self, u"Warning", u"打开视频失败", buttons=QtWidgets.QMessageBox.Ok,
                                      defaultButton=QtWidgets.QMessageBox.Ok)
        return
    else:
        self.timer_video.start(30)

OpenMp4连接Btn_Cerama,一旦点击,就会在data目录下搜索所有.mp4,.avi文件,和其他所有文件。flag代表是否打开失败,如果为false,就会用messagebox显示打开失败,否则就定时器设置时间间隔30ms,然后显示视频流。

def SignChange(self): #Btn.png的移动
    global Temp_Sign_Change
    if Temp_Sign_Change == 0:
        Temp_Sign_Change = 1
        animation = QPropertyAnimation(self.label)
        animation.setTargetObject(self.label)  # 设置动画对象
        animation.setPropertyName(b"geometry")
        animation.setStartValue(QRect(self.label.geometry().x(), self.label.geometry().y(), 42, 38))  # 设置起始点;初始尺寸
        animation.setEndValue((QRect(self.label.geometry().x() + 90, self.label.geometry().y(), 42, 38)))  # 设置终点;终止尺寸
        animation.setDuration(100)  # 时长单位毫秒
        animation.start()
    else:
        Temp_Sign_Change = 0
        animation = QPropertyAnimation(self.label)
        animation.setTargetObject(self.label)  # 设置动画对象
        animation.setPropertyName(b"geometry")
        animation.setStartValue(QRect(self.label.geometry().x(), self.label.geometry().y(), 42, 38))  # 设置起始点;初始尺寸
        animation.setEndValue((QRect(self.label.geometry().x() - 90, self.label.geometry().y(), 42, 38)))  # 设置终点;终止尺寸
        animation.setDuration(100)  # 时长单位毫秒
        animation.start()

SignChange连接Btn_Detect按钮,点击就会控制按钮的移动,即添加的资源文件Btn.png图片,首先先引用全局变量Temp_Sign_Change,Temp_Sign_Change默认为0,即默认一开始为不检测状态,一旦点击,先查看此时是否是检测状态,不是检测状态就转为检测状态,按钮图片移动到终止位置,是检测状态就改为非检测状态,只要点击Btn_Detect按钮,就会进行按钮图片的移动效果,和全局的是否进行检测。

        3.进行界面的初始化工作,并由主函数去调用主窗口函数,显示窗口界面。

def __init__(self):
    super().__init__()
    self.setAttribute(Qt.WA_TranslucentBackground) #窗口部件透明化
    self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint | Qt.Tool)
    self.timer_video = QtCore.QTimer()  # 创建定时器
    self.cap = cv2.VideoCapture() # 打开摄像头
    self.TimeConnet()
    self.setupUi(self)
    self.num_stop = 1
if __name__ == '__main__':
    app = PyQt5.QtWidgets.QApplication(sys.argv)
    ui = Designer()
    ui.show()
    sys.exit(app.exec_())

  • 检测的结果展示(toothbrush,person)(准确率有待提升)

效果图1

效果图2

效果图3

 Github地址: linluocheng/Detect_YOLOV4-tiny (github.com)

  • 3
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

獜洛橙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值