敞开成长之旅!这是我参加「日新计划 12 月更文挑战」的第5天,点击检查活动详情
opencv调用yolov3模型进行深度学习方针检测,以实例进行代码详解
对于yolo v3现已练习好的模型,opencv供给了加载相关文件,进行图片检测的类dnn。 下面临怎么经过opencv调用yolov3模型进行方针检测办法进行详解,付源代码
1、树立相关目录
在练习成果backup文件夹下,找到模型权重文件,拷到win的工程文件夹下
在cfg文件夹下,找到模型装备文件,yolov3-voc.cfg拷到win的工程文件夹下
在data文件夹下,找到voc.names,类别标签文件,拷到win的工程文件夹下

2代码详解
weightsPath='E:\deep_learn\yolov3_modeFile\yolov3-voc_25000.weights'# 模型权重文件
configPath="E:\deep_learn\yolov3_modeFile\yolov3-voc.cfg"# 模型装备文件
labelsPath = "E:\\deep_learn\\yolov3_modeFile\\voc.names"# 模型类别标签文件
引进模型的相关文件,这儿需求运用yolo v3练习模型的三个文件 (1)模型权重文件 name.weights (2)练习模型时的装备文件 yolov3-voc.cfg(一定和练习时一致,后面会提原因) (3)模型类别的标签文件 voc.names
LABELS = open(labelsPath).read().strip().split("\n")
从voc.names中得到标签的数组LABELS
我的模型辨认的是车和人
voc,names文件内容


COLORS = np.random.randint(0, 255, size=(len(LABELS), 3),dtype="uint8")#色彩 随机生成色彩框
依据类别个数随机生成几个色彩 ,用来后期画矩形框 [[ 33 124 191] [211 63 59]]
boxes = []
confidences = []
classIDs = []
声明三个数组 (1)boxes 寄存矩形框信息 (2)confidences 寄存框的置信度 (3)classIDs 寄存框的类别标签 三个数组元素一一对应,即boxes[0]、confidences[0]、classIDs[0]对应一个辨认方针的信息,后期依据该信息在图片中画出辨认方针的矩形框
net = cv2.dnn.readNetFromDarknet(configPath,weightsPath)
加载 网络装备与练习的权重文件 构建网络 注意此处opencv2.7不行 ,没有dnn这个类,最好opencv版本在4.0以上,对应python用3.0以上版本
image = cv2.imread('E:\deep_learn\yolov3_detection_image\R1_WH_ZW_40_80_288.jpg')
(H,W) = image.shape[0:2]
读入待检测的图片,得到图画的高和宽
ln = net.getLayerNames()
得到 YOLO各层的称号,之后从各层称号中找到输出层




out = net.getUnconnectedOutLayers()#得到未衔接层得序号
x = []
for i in out: # i=[200]
x.append(ln[i[0]-1]) # i[0]-1 取out中的数字 [200][0]=200 ln(199)= 'yolo_82'
ln=x
yolo的输出层是未衔接层的前一个元素,经过net.getUnconnectedOutLayers()找到未衔接层的序号out= [[200] /n [267] /n [400] ],循环找到所有的输出层,赋值给ln 最终ln = [‘yolo_82’, ‘yolo_94’, ‘yolo_106’] 接下来便是将图画转化为输入的规范格式
blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416),swapRB=True, crop=False)
用需求检测的原始图画image结构一个blob图画,对原图画进行像素归一化1 / 255.0,缩放尺度 (416, 416),,对应练习模型时cfg的文件 交流了R与G通道

image_blob = np.squeeze(blob)
cv2.namedWindow('image_blob', cv2.WINDOW_NORMAL)
cv2.imshow('image_blob',np.transpose(image_blob,[1,2,0]))
cv2.waitKey(0)
net.setInput(blob) #将blob设为输入
layerOutputs = net.forward(ln) #ln此刻为输出层称号 ,向前传达 得到检测成果
将blob设为输入
ln此刻为输出层称号 ,向前传达 得到检测成果。
此刻layerOutputs即三个输出的检测成果,


接下来便是对检测成果进行处理与显现 在检测成果中会有许多每个类的置信度为0的矩形框,要把这些与置信度较低的框去掉
#接下来便是对检测成果进行处理
for output in layerOutputs: #对三个输出层 循环
for detection in output: #对每个输出层中的每个检测框循环
scores=detection[5:] #detection=[x,y,h,w,c,class1,class2]
classID = np.argmax(scores)#np.argmax反应最大值的索引
confidence = scores[classID]
if confidence >0.5:#过滤掉那些置信度较小的检测成果
box = detection[0:4] * np.array([W, H, W, H])
(centerX, centerY, width, height)= box.astype("int")
# 边框的左上角
x = int(centerX - (width / 2))
y = int(centerY - (height / 2))
# 更新检测出来的框
boxes.append([x, y, int(width), int(height)])
confidences.append(float(confidence))
classIDs.append(classID)
现在就将网络的检测成果提取了出来,框、置信度、类别。 可以先画一下看下作用
a=0
for box in boxes:#将每个框画出来
a=a+1
(x,y)=(box[0],box[1])#框左上角
(w,h)=(box[2],box[3])#框宽高
if classIDs[a-1]==0: #依据类别设定框的色彩
color = [0,0,255]
else:
color = [0, 255, 0]
cv2.rectangle(image, (x, y), (x + w, y + h), color, 2) #画框
text = "{}: {:.4f}".format(LABELS[classIDs[a-1]], confidences[a-1])
cv2.putText(image, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.3, color, 1)#写字
cv2.namedWindow('Image', cv2.WINDOW_NORMAL)
cv2.imshow("Image", image)
cv2.waitKey(0)
成果:

idxs=cv2.dnn.NMSBoxes(boxes, confidences, 0.2,0.3)
box_seq = idxs.flatten()#[ 2 9 7 10 6 5 4]
if len(idxs)>0:
for seq in box_seq:
(x, y) = (boxes[seq][0], boxes[seq][1]) # 框左上角
(w, h) = (boxes[seq][2], boxes[seq][3]) # 框宽高
if classIDs[seq]==0: #依据类别设定框的色彩
color = [0,0,255]
else:
color = [0,255,0]
cv2.rectangle(image, (x, y), (x + w, y + h), color, 2) # 画框
text = "{}: {:.4f}".format(LABELS[classIDs[seq]], confidences[seq])
cv2.putText(image, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.3, color, 1) # 写字
cv2.namedWindow('Image', cv2.WINDOW_NORMAL)
cv2.imshow("Image", image)
cv2.waitKey(0)
最终的检测成果

3、附源代码
#coding:utf-8
import numpy as np
import cv2
import os
weightsPath='E:\deep_learn\yolov3_modeFile\yolov3-voc_25000.weights'# 模型权重文件
configPath="E:\deep_learn\yolov3_modeFile\yolov3-voc.cfg"# 模型装备文件
labelsPath = "E:\\deep_learn\\yolov3_modeFile\\voc.names"# 模型类别标签文件
#初始化一些参数
LABELS = open(labelsPath).read().strip().split("\n")
boxes = []
confidences = []
classIDs = []
#加载 网络装备与练习的权重文件 构建网络
net = cv2.dnn.readNetFromDarknet(configPath,weightsPath)
#读入待检测的图画
image = cv2.imread('E:\deep_learn\yolov3_detection_image\R1_WH_ZW_40_80_288.jpg')
#得到图画的高和宽
(H,W) = image.shape[0:2]
# 得到 YOLO需求的输出层
ln = net.getLayerNames()
out = net.getUnconnectedOutLayers()#得到未衔接层得序号 [[200] /n [267] /n [400] ]
x = []
for i in out: # 1=[200]
x.append(ln[i[0]-1]) # i[0]-1 取out中的数字 [200][0]=200 ln(199)= 'yolo_82'
ln=x
# ln = ['yolo_82', 'yolo_94', 'yolo_106'] 得到 YOLO需求的输出层
#从输入图画结构一个blob,然后经过加载的模型,给我们供给边界框和相关概率
#blobFromImage(image, scalefactor=None, size=None, mean=None, swapRB=None, crop=None, ddepth=None)
blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416),swapRB=True, crop=False)#结构了一个blob图画,对原图画进行了图画的归一化,缩放了尺度 ,对应练习模型
net.setInput(blob) #将blob设为输入??? 具体作用还不是很清楚
layerOutputs = net.forward(ln) #ln此刻为输出层称号 ,向前传达 得到检测成果
for output in layerOutputs: #对三个输出层 循环
for detection in output: #对每个输出层中的每个检测框循环
scores=detection[5:] #detection=[x,y,h,w,c,class1,class2] scores取第6位至最后
classID = np.argmax(scores)#np.argmax反应最大值的索引
confidence = scores[classID]
if confidence >0.5:#过滤掉那些置信度较小的检测成果
box = detection[0:4] * np.array([W, H, W, H])
#print(box)
(centerX, centerY, width, height)= box.astype("int")
# 边框的左上角
x = int(centerX - (width / 2))
y = int(centerY - (height / 2))
# 更新检测出来的框
boxes.append([x, y, int(width), int(height)])
confidences.append(float(confidence))
classIDs.append(classID)
idxs=cv2.dnn.NMSBoxes(boxes, confidences, 0.2,0.3)
box_seq = idxs.flatten()#[ 2 9 7 10 6 5 4]
if len(idxs)>0:
for seq in box_seq:
(x, y) = (boxes[seq][0], boxes[seq][1]) # 框左上角
(w, h) = (boxes[seq][2], boxes[seq][3]) # 框宽高
if classIDs[seq]==0: #依据类别设定框的色彩
color = [0,0,255]
else:
color = [0,255,0]
cv2.rectangle(image, (x, y), (x + w, y + h), color, 2) # 画框
text = "{}: {:.4f}".format(LABELS[classIDs[seq]], confidences[seq])
cv2.putText(image, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.3, color, 1) # 写字
cv2.namedWindow('Image', cv2.WINDOW_NORMAL)
cv2.imshow("Image", image)
cv2.waitKey(0)

