OpenCV for YOLOv3 深度学习的调用过程解析

编程入门 行业动态 更新时间:2024-10-26 18:18:15

OpenCV for YOLOv3 <a href=https://www.elefans.com/category/jswz/34/1769690.html style=深度学习的调用过程解析"/>

OpenCV for YOLOv3 深度学习的调用过程解析

本文将介绍在OpenCV环境中运行yolov3深度学习网络调用的全部过程,文章主要分为以下部分内容:

1.YOLOv3是什么,能做什么事情?

2.为什么要使用OpenCV for YOLOv3

3.YOLOv3调用整体过程的解析

4.总结

一.YOLOv3是什么,能做什么事情?

        这是yolo官网所给出的一副图片,我们可以不难看出,在相同mAP(可以理解为识别精度)上,yolov3具有相当高的识别速度,以至于官方“自嘲”将自己的识别速度停留在了时间轴的第二象限。接下来谈一谈什么是yolov3。

        YOLO(you only look once)是一款先进的实时目标检测系统,目前已经发展到yolov5,正是这种超快的实时检测速度,yolo的创始人看到了自己的成果被用在了自己不想应用的领域,放弃了v3之后的开发。yolo采用one-stage模式,完成从原始图像的输入到物体位置和类别的输出。

 

        YOLOv3的核心网络架构采用3个scale分别来检测大中小物体,并且三个scale之间也有相互关联,可以更加准确地识别信息,且每种scale分别输出维度为s×s×3×(4+1+80),s分别对应3个scale的值为13、26、52;3表示图像在识别过程中会对预测的物体输出3个先验框,最后挑选最优的来判定内容的信息;4+1+80,其中4代表先验框中心点的坐标(x,y,w,h),1代表开物体的置信程度,80代表yolov3所训练好的80种类型的分类。通过以上信息,有计算机进行对所检测内容与80种类型物体之间的相似程度,就可以判断出该物体的所属种类,实现物体识别。

二.为什么使用opencv for yolov3

        速度快!!

        OpenCV的DNN模块,其CPU运行是十分快的。比如,当用了OpenMP的Darknet在CPU上处理一张图片消耗2秒,OpenCV的实现只需要0.22秒。

三.YOLOv3调用整体过程的解析

       整体代码如下:

        1.首先调用摄像头模组

import cv2 as cv
import numpy as npcap=cv.VideoCapture(0)while True:ret,frame=cap.read()cv.imshow("frame",frame)c=cv.waitKey(1)if c==27:break
cap.release()
cv.destroyAllWindows()

        2.引入80种类别名称文件coco.name

        coco.name文件中存储着80种已经训练好的识别类型名称,这些类别名称正好与yolo所训练的80种类别一一对应,将他们以列表的形式装在classNames列表中,已便输出时进行调用。

        coco.names文件可以在csdn中查找,有其他作者提供的下载链接!!

import cv2 as cv
import numpy as npcap=cv.VideoCapture(0)classesFile="coco.names"
classNames=[]
with open (classesFile,"rt") as file:classNames=file.read().splitlines()while True:ret,frame=cap.read()cv.imshow("frame",frame)c=cv.waitKey(1)if c==27:break
cap.release()
cv.destroyAllWindows()

        

        3.加载模型并创建网络架构

import cv2 as cv
import numpy as npcap=cv.VideoCapture(0)classesFile="coco.names"
classNames=[]
with open (classesFile,"rt") as file:classNames=file.read().splitlines()modelConfiguration="yolov3-320.cfg"    ###配置文件
modelWeights="yolov3-320.weights"      ###配置权重文件net=cv.dnn.readNetFromDarknet(modelConfiguration,modelWeights)   ##将配置文件加入到dnn网络中
net.setPreferableBackend(cv.dnn.DNN_BACKEND_OPENCV)              ##将DNN后端设置成opencv
net.setPreferableTarget(cv.dnn.DNN_TARGET_CPU)                   ##将DNN前端设置成cpu驱动
while True:ret,frame=cap.read()blob=cv.dnn.blobFromImage(frame,1/255,(416,416),[0,0,0],True,False)  ##DNN网络的输入图像需要采用称为 blob 的特定格式net.setInput(blob)                                                   ##将输出的blob作为传入网络的输入layerNames=net.getLayerNames()                                       ##获取输入层的名称outputNames=[layerNames[i-1]for i in net.getUnconnectedOutLayers()]  ##获得输入层的最后一层,以此遍历整个网络outputs=net.forward(outputNames)                                     ##获取输出findobject(outputs,frame)                                            ##自定义函数功能,找到当前目标类型cv.imshow("frame",frame)c=cv.waitKey(1)if c==27:break
cap.release()
cv.destroyAllWindows()

           这里有如下说明:

           1.yolov3-320.weights.权重:预先训练的权重。

           2.yolov3-320.cfg:配置文件

           以上两个文件下载地址可在YOLO官网darknet模块进行下载。

           3.blob:神经网络的输入图像需要采用称为blob的特定格式。从摄像头读取每一帧开始,将通过blobFromImage()函数将其转换为神经网络所能够接受的blob格式。在此过程中,它使用比例因子1/255 将图像像素值缩放到 0 到 1 的目标范围。它还会将图像大小调整为给定的大小 (416,416),无需裁剪。bean值为 [0,0,0] ,并将 swapRB 参数保持为真。然后,输出 blob作为其输入传入网络,并运行正向传递以获取预测边界框的列表作为网络的输出。这些框经过后处理步骤,以过滤掉置信度分数较低的框。以上数据即便不明白来历,也可以在自己的opencv安装目录下进行查找,以下是查找方法:找到你的opencv安装目录,按路径opencv\sources\samples\dnn找到dnn文件夹中的models.yml 文件,里面存放有各种深度学习配置DNN网路的blob值,按顺序输入即可,下图为yolov3所需要配置参数的截图。

            4.OpenCV的Net类中的forwa()函数需要结束层,直到它应该在网络中运行。我们想要运行整个网络,因此我们需要识别网络的最后一层。通过使用函数 getUnconnectedOutLayer()l获取到未连接输出层的名称,这些输出层本质上是网络的最后一层,代码中我们使用循环进行遍历,直至遍历到未连接层减1层,即为网络的最后一层。最后,我们运行网络的正向传递,从输出层获取输出。

         3.自定义功能输出类别

import cv2 as cv
import numpy as npdef findobject(outputs,frame):H,W,C=frame.shape                                  ##获取原始帧图像的大小H,Wbbox=[]                                            ##建立一个用来存储先验框的坐标列表classIds=[]                                        ##建立用来存储每一帧检测到的类别信息名称confs=[]                                           ##建立每一帧读取的置信度值for output in outputs:                             ##由于每一帧图片的内容可能含有多个类别信息,例如图片中既含有人,也含有汽车、小狗等类别,我们需要对每个类别进行检测for det in output:                             ##开始检测frame帧中的每个类别                scores=det[5:]                             ##获取该类别与80项全类别分别的相似概率classId=np.argmax(scores)                  ##获得80项中最为相似的类别(相似概率值最大的类别)confidence=scores[classId]                 ##获取该最大相似概率的值赋值给confidenceif confidence>0.5:                         ##若果相似度大于0.5,我们认为检测结果可靠,当然你也可以提高该数值进而提高你的识别精度w=int(det[2]*W)                        ##获取先验框的四个坐标点h=int(det[3]*H)x=int(det[0]*W-w/2)y=int(det[1]*H-h/2)bbox.append((x,y,w,h))                 ##将坐标添加到bbox中进行存储,便于对frame帧中所有类别的先验框坐标进行存储,最后输出classIds.append(classId)               ##将frame中每一类别对应的编号(1-80),便于在输出文本时,与对应coconame文件中的类别名称进行输出confs.append(float(confidence))        ##将frame中每一类别对应的相似概率进行存储    indices=cv.dnn.NMSBoxes(bbox,confs,0.5,0.2)        ##对frame中识别出来的每一类信息进行最大抑制由参数nms阈值控制for i in indices:                                    box=bbox[i]                                    ##依次读取最大已知参数nms阈值的先验框坐标x,y,w,h=box[0],box[1],box[2],box[3]            cv.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),2,8)  ##对每个最终识别的目标进行矩形框选cv.putText(frame,f"{classNames[classIds[i]].upper()} {round(confs[i]*100,2)}%",(x,y),cv.FONT_HERSHEY_COMPLEX,0.6,(128,0,255),2,8)     ##对应coco.names相应的类别名称和相似概率进行文字输出cap=cv.VideoCapture(0)classesFile="coco.names"
classNames=[]
with open (classesFile,"rt") as file:classNames=file.read().splitlines()modelConfiguration="yolov3-320.cfg"
modelWeights="yolov3-320.weights"net=cv.dnn.readNetFromDarknet(modelConfiguration,modelWeights)
net.setPreferableBackend(cv.dnn.DNN_BACKEND_OPENCV)
net.setPreferableTarget(cv.dnn.DNN_TARGET_CPU)
while True:ret,frame=cap.read()blob=cv.dnn.blobFromImage(frame,1/255,(416,416),[0,0,0],True,False)net.setInput(blob)layerNames=net.getLayerNames()outputNames=[layerNames[i-1]for i in net.getUnconnectedOutLayers()]outputs=net.forward(outputNames)findobject(outputs,frame)cv.imshow("frame",frame)c=cv.waitKey(1)if c==27:break
cap.release()
cv.destroyAllWindows()

           这里有如下说明:

           1.我们需要对每一张图片frame中每个计算机认为的物体进行识别,为了提高检测速度,我们需要过滤掉置信程度小于0.5的信息,这只是初步筛选的内容。

           2.即便如此,计算机也极有可能对一张图片中的同一个物体进行二次甚至多次的识别,认为这是两个或多个不同的物体,因此我们需要对所识别出来的物体进行非最大抑制由参数nms阈值控制,此数值控制的越低,我们所误检测的相同物体会越少,以提高我们的识别精度。

            下图可以很好的帮助我们理解对图片进行非最大阈值控制的重要性:

 四.总结

          随笔书写最近学习内容,希望以上内容可以帮到大家,有不懂的地方可以评论留言。

          小编也是一个初学者,也有很多疑惑地的地方,如果有理解错误的地方也请大家批评指正,一起学习,一起进步!

更多推荐

OpenCV for YOLOv3 深度学习的调用过程解析

本文发布于:2024-02-26 08:39:37,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1701889.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:深度   过程   OpenCV

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!