基于YOLO和Darknet预训练模型的对象检测
YOLO(You Only Look Once)算法是约瑟夫·雷蒙(Redmon)等人在其论文中提出的对象检测算法。YOLO将图像分成若干个网格,对每个网格计算边框和可信度。
Darknet是一个基于C语言与CUDA实现的开源深度学习框架,其主要特点是容易安装、移植性好、支持CPU与GPU计算。
OpenCV的cv2.dnn.readNetFromDarknet()函数用于从文件中加载基于YOLO V3和Darknet的预训练模型。
下面的代码使用基于YOLO V3和Darknet的预训练模型进行对象检测。
使用基于YOLO和Darknet的预训练模型进行对象检测
import cv2
import numpy as np
from matplotlib import pyplot as plt
import matplotlib
from PIL import ImageFont, ImageDraw, Image
加载字体,以便显示汉字
fontpath = "STSONG.TTF"
font = ImageFont.truetype(fontpath,20) #载入字体,设置字号
font2 = {'family': 'STSONG', "size": 22}
matplotlib.rc('font', **font2) #设置plt字体
从文件中加载已知的对象名称
f=open("object_names.txt",encoding='utf-8')#文件保存了80个类别的对象名称,每行一个
object_names = [r.strip() for r in f.readlines()]
f.close()
从文件中加载预训练的Darknet模型
mode = cv2.dnn.readNetFromDarknet("yolov3.cfg", "yolov3.weights")
image = cv2.imread("objects.jpg") #打开图像文件
imgH,imgW = image.shape[:2]
out_layers = mode.getLayerNames() #获得输出层
out_layers = [out_layers[i[0] - 1] for i in mode.getUnconnectedOutLayers()]
blob = cv2.dnn.blobFromImage(image,1/255.0,(416,416),#创建图像blob数据
swapRB=True,crop=False)
mode.setInput(blob) #将图像blob数据设置为模型输入
layer_results = mode.forward(outlayers)#执行预测,返回每层的预测结果
ptime, = mode.getPerfProfile()
tilte_text='完成预测时间:%.2f ms' % (ptime*1000/cv2.getTickFrequency())
result_boxes = []
result_scores = []
result_name_id = []
for layer in layer_results: #遍历所有输出层
for box in layer:#遍历层的所有输出预测结果,每个结果为一个边框
#预测结果结构:x, y, w, h, confidence,80个类别的概率
probs = box[5:]
class_id = np.argmax(probs) #找到概率最大的类别id
prob = probs[class_id] #找到最大的概率
if prob > 0.5: #筛选出概率大于50%的
#计算每个box在原图像中的的绝对坐标
box = box[0:4] * np.array([imgW, imgH, imgW, imgH])
(centerX, centerY, width, height) = box.astype("int")
x = int(centerX - (width / 2))
y = int(centerY - (height / 2))
result_boxes.append([x, y, int(width), int(height)])
result_scores.append(float(prob))
result_name_id.append(class_id)
应用非最大值抑制消除重复边界框,获得要绘制的box
draw_boxes = cv2.dnn.NMSBoxes(result_boxes, result_scores, 0.6, 0.3)
if len(draw_boxes) > 0:
for i in draw_boxes.ravel():
#获得边框坐标
(x, y) = (result_boxes[i][0], result_boxes[i][1])
(w, h) = (result_boxes[i][2], result_boxes[i][3])
#绘制边框
cv2.rectangle(image,(x,y), (x+w,y+h),(0,255,0),1)
#输出类别名称和可信度
text=object_names[result_name_id[i]] +\
"\n{:.1%}".format(result_scores[i])
img_pil = Image.fromarray(image)
draw = ImageDraw.Draw(img_pil)
draw.text((x+5,y), text, font = font,fill=(0,0,255)) #绘制文字
image = np.array(img_pil)
img = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
plt.title(tilte_text)
plt.imshow(img)
plt.axis('off')
plt.show()