130 OpenCV DNN 支持YOLO对象检测网络运行
代码
import cv2 as cv
import numpy as np
model_bin = "../models/yolov3/yolov3.weights"
config_text = "../models/yolov3/yolov3.cfg"
# Load names of classes
classes = None
with open("../models/object_detection_classes_yolov3.txt", 'rt') as f:
classes = f.read().rstrip('\n').split('\n')
# load tensorflow model
net = cv.dnn.readNetFromDarknet(config_text, model_bin)
image = cv.imread("../images/objects.jpg")
h = image.shape[0]
w = image.shape[1]
# 获得所有层名称与索引
layerNames = net.getLayerNames()
lastLayerId = net.getLayerId(layerNames[-1])
lastLayer = net.getLayer(lastLayerId)
print(lastLayer.type)
# 基于多个Region层输出getUnconnectedOutLayersNames
blobImage = cv.dnn.blobFromImage(image, 1.0/255.0, (416, 416), None, True, False);
outNames = net.getUnconnectedOutLayersNames()
net.setInput(blobImage)
outs = net.forward(outNames)
# Put efficiency information.
t, _ = net.getPerfProfile()
label = 'Inference time: %.2f ms' % (t * 1000.0 / cv.getTickFrequency())
cv.putText(image, label, (0, 15), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0))
print(outs)
# 绘制检测矩形
classIds = []
confidences = []
boxes = []
for out in outs:
for detection in out:
scores = detection[5:]
classId = np.argmax(scores)
confidence = scores[classId]
# numbers are [center_x, center_y, width, height]
if confidence > 0.5:
center_x = int(detection[0] * w)
center_y = int(detection[1] * h)
width = int(detection[2] * w)
height = int(detection[3] * h)
left = int(center_x - width / 2)
top = int(center_y - height / 2)
classIds.append(classId)
confidences.append(float(confidence))
boxes.append([left, top, width, height])
indices = cv.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
for i in indices:
i = i[0]
box = boxes[i]
left = box[0]
top = box[1]
width = box[2]
height = box[3]
cv.rectangle(image, (left, top), (left+width, top+height), (0, 0, 255), 2, 8, 0)
cv.putText(image, classes[classIds[i]], (left, top), cv.FONT_HERSHEY_SIMPLEX, 1.0, (255, 255, 0), 2)
cv.imshow('YOLOv3-Detection-Demo', image)
cv.waitKey(0)
cv.destroyAllWindows()
实验结果
解释
OpenCV DNN模块支持YOLO对象检测网络,最新的OpenCV4.0支持YOLOv3版本的对象检测网络,YOLOv3版本同时还发布了移动端支持的网络模型YOLOv3-tiny版本,速度可以在CPU端实时运行的对象检测网络,OpenCV中通过对DarkNet框架集成支持实现YOLO网络加载与检测。因为YOLOv3对象检测网络是多个层的合并输出,所以在OpenCV中调用时候必须显示声明那些是输出层,这个对于对象检测网络,OpenCV提供了一个API来获取所有的输出层名称,该API为:
retval = cv.dnn_Net.getUnconnectedOutLayersNames()
该函数返回所有非连接的输出层。
调用时候,必须显式通过输入参数完成推断,相关API如下:
outputBlobs = cv.dnn_Net.forward([, outputBlobs[, outputName]])
outputBlobs
是调用之后的输出outBlobNames
是所有输出层的名称
跟SSD/Faster-RCNN出来的结构不一样,YOLO的输出前四个为
[center_x, center_y, width, height]
后面的是所有类别的得分,这个时候只要根据score大小就可以得到score最大的对应对象类别,解析检测结果。相关模型下载到YOLO作者的官方网站:
YOLO: Real-Time Object Detection
所有内容均来源于贾志刚老师的知识星球——OpenCV研习社,本文为个人整理学习,已获得贾老师授权,有兴趣、有能力的可以加入贾老师的知识星球进行深入学习。