当前位置:   article > 正文

【OpenCV-Python实战项目】08-YOLO-V3实时目标检测

【OpenCV-Python实战项目】08-YOLO-V3实时目标检测

0.介绍

(1)YOLO是一个开源的目标检测算法,兼顾准确率和运行速度,本笔记主要用YOLO-V3进行图像 or 摄像头视频或者下载视频的目标检测。
(2)检测流程:

  • 1)opencv读取视频流或图像;
  • 2)创建YOLO-V3网络模型并导入权重文件;
  • 3)用模型进行检测并输出检测数值,最后绘制显示在图像上;

(3)YOLO-V3的网络配置文件以及对应的模型权重文件下载:YOLO配置以及权重文件下载链接
注意:FPS表示视频显示帧率,即一秒中图像数量,越大表示视频显示越流畅,下载的模型为YOLOv3-320,下载cfg模型配置文件(加载网络结构)+weights(模型权重文件)两个。

在这里插入图片描述

此外由于该模型是在COCO上面下载的,一共有80类,需要导入其类别文件,方面后续绘制出类别名称,类别如下:

在这里插入图片描述

1.基础功能实现

(1)用法说明:
1)先加载类别文件,然后构建模型并导入训练好的权重,代码片段如下:

classNames= []
classFile='coco.names'
with open(classFile,'rt') as f:
    classNames=f.read().rstrip('\n').split('\n')

modelConfiguration='yolov3.cfg'
modekWeights='yolov3.weights'
net=cv2.dnn.readNetFromDarknet(modelConfiguration,modekWeights)
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)#to use opencv
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)#to use cpu
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2)对输入网络的数据进行预处理,比如裁剪到网络支持的尺寸等

#blobFromImage主要是用来对图片进行预处理:分别是影像,缩放系数、输入图片的尺寸,图片整体减去的平均值,crop
blob = cv2.dnn.blobFromImage(image, scalefactor=1.0, size, mean, swapRB=True,crop=False,ddepth = CV_32F )

3)将预处理好的数据喂入网络并从网络输出层得到结果,但是由于YOLO-V3是输出有三层,因此如下为得到输出三层的名称,然后提取出对应的结果步骤:

outputNames=[layerNames[i-1] for i in net.getUnconnectedOutLayers()]
outputs=net.forward(outputNames) #三层的输出结果,shape分别是:
outputs[0].shape=(300,85)outputs[1].shape=(1200,85),outputs[2].shape=(4800,85),

其中每一行85个数,前四个数表示x,y,w,h,检测置信度,最后80表示80个类别每个类别的得分,遍历提取即可。
在这里插入图片描述
4) 非极大值抑制用于过滤掉同一个物体出现了不同大小的检测框

(2)完整代码:

import cv2
import numpy as np


cap=cv2.VideoCapture('object.mp4')# 可以设置为0,默认打开摄像头

classNames= []
classFile='coco.names'
with open(classFile,'rt') as f:
    classNames=f.read().rstrip('\n').split('\n')

modelConfiguration='yolov3.cfg'
modekWeights='yolov3.weights'
net=cv2.dnn.readNetFromDarknet(modelConfiguration,modekWeights)
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)#to use opencv
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)#to use cpu


def findObjects(outputs,img):
    hT,wT,cT=img.shape
    bbox=[] 
    classIds=[]
    confs=[]

    for output in outputs:#3层结果
        for det in output:#每层检测结果
            scores=det[5:]  
            classId=np.argmax(scores)
            conf=scores[classId]
            if conf>0.5:
                w,h=int(det[2]*wT),int(det[3]*hT)
                x,y=int((det[0]*wT)-w/2),int((det[1]*hT)-h/2)#注意减去
                bbox.append([x,y,w,h])
                classIds.append(classId)
                confs.append(float(conf))

        indices=cv2.dnn.NMSBoxes(bbox,confs,0.5,0.4)

        for i in indices:
            # print(i)

            box=bbox[i]
            x,y,w,h=box
            label=classNames[classIds[i]]
            confidence=confs[i]
            cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,255),2)
            cv2.putText(img,f'{label} {confidence}',(x,y-10),cv2.FONT_HERSHEY_SIMPLEX,0.5,(255,0,255),2)
 


while True:
    success,img=cap.read()
    # blobFromImage主要是用来对图片进行预处理:分别是影像,缩放系数、输入图片的尺寸,图片整体减去的平均值,crop
    blob=cv2.dnn.blobFromImage(img,1/255,(320,320),[0,0,0],1,crop=False)

    net.setInput(blob)

    layerNames=net.getLayerNames()
    # print(type(layerNames))
    # print(layerNames[0])
    # print(type(net.getUnconnectedOutLayers()))#获取输出层的索引
 
    outputNames=[layerNames[i-1] for i in net.getUnconnectedOutLayers()]
    # print(outputNames)
    outputs=net.forward(outputNames)
    # print(outputs[0].shape)#第一个表示检测的盒子数,85表示一堆值,如x,y,w,h,confidence,80表示类别数
    # print(outputs[1].shape)
    # print(outputs[2].shape)
    # print(outputs[0][0])
    findObjects(outputs,img)

    cv2.imshow('Video',img)
    
    if cv2.waitKey(1) & 0xFF==ord('q'):
        break
    

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77

(3)效果预览:
在这里插入图片描述

2.工程应用

2.1 封装类

2.2 只检测指定类别的物体

(1)说明

(2)完整代码

import cv2
import numpy as np


cap=cv2.VideoCapture('object.mp4')# 可以设置为0,默认打开摄像头

classNames= []
classFile='coco.names'
with open(classFile,'rt') as f:
    classNames=f.read().rstrip('\n').split('\n')

modelConfiguration='yolov3.cfg'
modekWeights='yolov3.weights'
net=cv2.dnn.readNetFromDarknet(modelConfiguration,modekWeights)
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)#to use opencv
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)#to use cpu

# detectLabels为指定只检测的物体名称列表
def findObjects(outputs,img,detectLabels=classNames):
    hT,wT,cT=img.shape
    bbox=[] 
    classIds=[]
    confs=[]

    for output in outputs:#3层结果
        for det in output:#每层检测结果
            scores=det[5:]  
            classId=np.argmax(scores)
            conf=scores[classId]
            if conf>0.5:
                w,h=int(det[2]*wT),int(det[3]*hT)
                x,y=int((det[0]*wT)-w/2),int((det[1]*hT)-h/2)#注意减去
                bbox.append([x,y,w,h])
                classIds.append(classId)
                confs.append(float(conf))

        indices=cv2.dnn.NMSBoxes(bbox,confs,0.5,0.4)

        for i in indices:
            # print(i)

            box=bbox[i]
            x,y,w,h=box
            label=classNames[classIds[i]]
            confidence=confs[i]
            if label in detectLabels:
                cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,255),2)
                cv2.putText(img,f'{label} {confidence}',(x,y-10),cv2.FONT_HERSHEY_SIMPLEX,0.5,(255,0,255),2)
 


while True:
    success,img=cap.read()
    # blobFromImage主要是用来对图片进行预处理:分别是影像,缩放系数、输入图片的尺寸,图片整体减去的平均值,crop
    blob=cv2.dnn.blobFromImage(img,1/255,(320,320),[0,0,0],1,crop=False)

    net.setInput(blob)

    layerNames=net.getLayerNames()
 
    outputNames=[layerNames[i-1] for i in net.getUnconnectedOutLayers()]
    # print(outputNames)
    outputs=net.forward(outputNames)

    findObjects(outputs,img,['person'])

    cv2.imshow('Video',img)
    
    if cv2.waitKey(1) & 0xFF==ord('q'):
        break
    

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

(3)效果预览(只检测行人)
在这里插入图片描述
未完待续!!!

3.参考

(1)B站视频-08-YOLO-V3实时目标检测视频教程
(2)gitee代码仓库
(3)教程源地址cv zone(1)(2)均来自此正式教程。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/969716
推荐阅读
相关标签
  

闽ICP备14008679号