YOLO-V3实时检测实现(opencv+python实现)

文章目录

    • 1.前置知识点(浅层了解)
      • (1)深度学习的网络模型
      • (2)yolo-v3网络结构
    • 2.YOLO-V3权重文件(.weights),类别文件(.names)和网络文件(.cfg)下载
      • (1)YOLOV3权重文件下载
      • (2)YOLOV3类别文件下载
      • (3)YOLO.cfg配置文件下载
    • 3.代码实战
      • (1)读取权重文件和网络配置文件
      • (2)获取最后三个输出层的名称
      • (3)读取包含80个类别coco.names的文件
      • (4)置信度阈值和非极大值抑制阈值的设定
      • (5)前向推断以及预测过程
        • (1)图像的预处理,设置网络输入和前向推断
        • (2)设置存储后续值的列表
        • (3)获取坐标,置信度,概率值以及预测类别
        • (4)求解非极大值抑制结果
        • (5)绘制矩形框
      • (6)预测单张图片
      • (7)实时检测
      • (8)整体代码
      • (9)单张图片预测结果
      • (10)实时检测结果

1.前置知识点(浅层了解)

(1)深度学习的网络模型

https://mydreamambitious.blog.csdn.net/article/details/125459959

(2)yolo-v3网络结构

对于了解目前这篇文章(YOLO-V3实时检测实现),读者只要了解下面给出的知识点,即可,不需要太关心论文中的细节。
YOLO-V3实时检测实现(opencv+python实现)_第1张图片
YOLO-V3实时检测实现(opencv+python实现)_第2张图片
在这里插入图片描述

YOLO-V3实时检测实现(opencv+python实现)_第3张图片

表的来源:https://blog.csdn.net/qq_37541097/article/details/81214953

图片来源:图片地址


2.YOLO-V3权重文件(.weights),类别文件(.names)和网络文件(.cfg)下载

(1)YOLOV3权重文件下载

https://pjreddie.com/darknet/yolo/

(2)YOLOV3类别文件下载

https://github.com/pjreddie/darknet/blob/master/data/coco.names

(3)YOLO.cfg配置文件下载

https://github.com/pjreddie/darknet
YOLO-V3实时检测实现(opencv+python实现)_第4张图片
下载之后如下:
在这里插入图片描述


3.代码实战

YOLO-V3输出的结果形式;知道了输出结果的形式,对于后面获取预测结果的预测框的坐标(x,y),高宽(w,h),置信度(confidence)以及预测类别的概率很有帮助(这些值是最后的输出结果,所以需要映射回原来的图像)。
在这里插入图片描述

(1)读取权重文件和网络配置文件

#读取网络配置文件和权重文件
net=cv2.dnn.readNet(model='dnn_model/yolov3.weights',
                    config='dnn_model/yolov3.cfg')

(2)获取最后三个输出层的名称

#由yolo-v3的结构可知,最终有三个尺度的输出
layerName=net.getLayerNames()
#存储输出的三个尺度名称,用于后面进行前向推断的
ThreeOutput_layers_name=[]
for i in net.getUnconnectedOutLayers():
    ThreeOutput_layers_name.append(layerName[i-1])

(3)读取包含80个类别coco.names的文件

#因为yolo-v3中检测包含80个类别,所以首先获取类别
with open('dnn_model/coco.names','r') as fp:
    classes=fp.read().splitlines()

(4)置信度阈值和非极大值抑制阈值的设定

#指定过滤的置信度阈值:confidence
Confidence_thresh=0.2
#指定非极大值抑制的值:对候选框进行筛选
Nms_thresh=0.35

(5)前向推断以及预测过程

(1)图像的预处理,设置网络输入和前向推断

 # 参数情况:图像 ,归一化,缩放的大小,是否对RGB减去一个常数,R和B交换(因为R和B是反着的,所以需要交换),是否裁剪
    blob = cv2.dnn.blobFromImage(frame, 1 / 255, (416, 416), (0, 0, 0), swapRB=True, crop=False)
    #获取图像的高宽
    height,width,channel=frame.shape
    #设置网络输入
    net.setInput(blob)
    #进行前向推断:采用的最后三个尺度输出层作为前向推断
    predict=net.forward(ThreeOutput_layers_name)

(2)设置存储后续值的列表

 # 存放预测框的坐标
    boxes = []
    #存在预测物体的置信度
    confid_object=[]
    #存放预测的类别
    class_prob=[]
    #存放预测物体的id
    class_id=[]
    #存放预测类别的名称
    class_names=[]

(3)获取坐标,置信度,概率值以及预测类别

 #根据输出的是三个尺度,所以分别遍历三个尺度
    for scale in predict:
        for box in scale:
            #获取坐标值和高宽
            #首先获取矩形中心坐标值(这里需要映射回原图)
            center_x=int(box[0]*width)
            center_y=int(box[1]*height)
            #计算框的高宽
            w=int(box[2]*width)
            h=int(box[3]*height)
            #获取矩形框的左上角坐标
            left_x=int(center_x-w/2)
            left_y=int(center_y-h/2)
            boxes.append([left_x,left_y,w,h])

            #获取检测物体的置信度
            confid_object.append(float(box[4]))
            #获取概率最大值
            #首先获取最高值概率的下标
            index=np.argmax(box[5:])
            class_id.append(index)
            class_names.append(classes[index])
            class_prob.append(box[index])
    confidences=np.array(class_prob)*np.array(confid_object)

(4)求解非极大值抑制结果

 #计算非极大值抑制
    all_index=cv2.dnn.NMSBoxes(boxes,confidences,Confidence_thresh,Nms_thresh)

(5)绘制矩形框

#遍历,绘制矩形框
    for i in all_index.flatten():
        x,y,w,h=boxes[i]
        #四舍五入,保留2位小数
        confidence=str(round(confidences[i],2))
        #绘制矩形框
        cv2.rectangle(img=frame,pt1=(x,y),pt2=(x+w,y+h),
                      color=(0,255,0),thickness=2)
        text=class_names[i]+' '+confidence
        cv2.putText(img=frame,text=text,org=(x,y-10),
                    fontFace=cv2.FONT_HERSHEY_SIMPLEX,
                    fontScale=1.0,color=(0,0,255),thickness=2)

(6)预测单张图片

#单张图片的检测
def signa_Picture(image_path='images/smile.jpg'):
    img=cv2.imread(image_path)
    img=cv2.resize(src=img,dsize=(416,416))
    dst=Forward_Predict(img)
    cv2.imshow('detect',dst)
    key=cv2.waitKey(0)
    if key==27:
        exit()

(7)实时检测

#实时的检测
def detect_time():
    cap=cv2.VideoCapture(0)
    while cap.isOpened():
        OK,frame=cap.read()
        if not OK:
            break
        #将图片进行一下翻转,因为Opencv读取的图片和我们正常是反着的
        frame=cv2.flip(src=frame,flipCode=2)
        frame=cv2.resize(src=frame,dsize=(416,416))
        dst=Forward_Predict(frame)

        cv2.imshow('detect',dst)
        key=cv2.waitKey(1)
        if key==27:
            break
    cap.release()

(8)整体代码

import os
import cv2
import numpy as np
import matplotlib.pyplot as plt

#读取网络配置文件和权重文件
net=cv2.dnn.readNet(model='dnn_model/yolov3.weights',
                    config='dnn_model/yolov3.cfg')
#由yolo-v3的结构可知,最终有三个尺度的输出
layerName=net.getLayerNames()
#存储输出的三个尺度名称,用于后面进行前向推断的
ThreeOutput_layers_name=[]
for i in net.getUnconnectedOutLayers():
    ThreeOutput_layers_name.append(layerName[i-1])

#因为yolo-v3中检测包含80个类别,所以首先获取类别
with open('dnn_model/coco.names','r') as fp:
    classes=fp.read().splitlines()

#指定过滤的置信度阈值:confidence
Confidence_thresh=0.2
#指定非极大值抑制的值:对候选框进行筛选
Nms_thresh=0.35

#检测的过程已经图形的绘制
def Forward_Predict(frame):
    # 参数情况:图像 ,归一化,缩放的大小,是否对RGB减去一个常数,R和B交换(因为R和B是反着的,所以需要交换),是否裁剪
    blob = cv2.dnn.blobFromImage(frame, 1 / 255, (416, 416), (0, 0, 0), swapRB=True, crop=False)
    #获取图像的高宽
    height,width,channel=frame.shape
    #设置网络输入
    net.setInput(blob)
    #进行前向推断:采用的最后三个尺度输出层作为前向推断
    predict=net.forward(ThreeOutput_layers_name)
    # 存放预测框的坐标
    boxes = []
    #存在预测物体的置信度
    confid_object=[]
    #存放预测的类别
    class_prob=[]
    #存放预测物体的id
    class_id=[]
    #存放预测类别的名称
    class_names=[]
    #根据输出的是三个尺度,所以分别遍历三个尺度
    for scale in predict:
        for box in scale:
            #获取坐标值和高宽
            #首先获取矩形中心坐标值(这里需要映射回原图)
            center_x=int(box[0]*width)
            center_y=int(box[1]*height)
            #计算框的高宽
            w=int(box[2]*width)
            h=int(box[3]*height)
            #获取矩形框的左上角坐标
            left_x=int(center_x-w/2)
            left_y=int(center_y-h/2)
            boxes.append([left_x,left_y,w,h])

            #获取检测物体的置信度
            confid_object.append(float(box[4]))
            #获取概率最大值
            #首先获取最高值概率的下标
            index=np.argmax(box[5:])
            class_id.append(index)
            class_names.append(classes[index])
            class_prob.append(box[index])
    confidences=np.array(class_prob)*np.array(confid_object)
    #计算非极大值抑制
    all_index=cv2.dnn.NMSBoxes(boxes,confidences,Confidence_thresh,Nms_thresh)

    #遍历,绘制矩形框
    for i in all_index.flatten():
        x,y,w,h=boxes[i]
        #四舍五入,保留2位小数
        confidence=str(round(confidences[i],2))
        #绘制矩形框
        cv2.rectangle(img=frame,pt1=(x,y),pt2=(x+w,y+h),
                      color=(0,255,0),thickness=2)
        text=class_names[i]+' '+confidence
        cv2.putText(img=frame,text=text,org=(x,y-10),
                    fontFace=cv2.FONT_HERSHEY_SIMPLEX,
                    fontScale=1.0,color=(0,0,255),thickness=2)
    return frame

#实时的检测
def detect_time():
    cap=cv2.VideoCapture(0)
    while cap.isOpened():
        OK,frame=cap.read()
        if not OK:
            break
        #将图片进行一下翻转,因为Opencv读取的图片和我们正常是反着的
        frame=cv2.flip(src=frame,flipCode=2)
        frame=cv2.resize(src=frame,dsize=(416,416))
        dst=Forward_Predict(frame)

        cv2.imshow('detect',dst)
        key=cv2.waitKey(1)
        if key==27:
            break
    cap.release()


#单张图片的检测
def signa_Picture(image_path='images/smile.jpg'):
    img=cv2.imread(image_path)
    img=cv2.resize(src=img,dsize=(416,416))
    dst=Forward_Predict(img)
    cv2.imshow('detect',dst)
    key=cv2.waitKey(0)
    if key==27:
        exit()
cv2.destroyAllWindows()

if __name__ == '__main__':
    print('Pycharm')
    # signa_Picture()
    detect_time()

(9)单张图片预测结果

YOLO-V3实时检测实现(opencv+python实现)_第5张图片

(10)实时检测结果

yolov3视频演示

你可能感兴趣的:(Opencv,python,opencv,计算机视觉,目标检测)