AI 队列长度检测:使用 YOLO 进行视频对象检测






4.82/5 (5投票s)
在这篇文章中,我们将尝试在视频流上实现 YOLO,用于检测队列长度。
到目前为止,在本系列文章中,我们一直在处理静态图像数据。 在本文中,我们将使用 YOLO 的基本实现来检测和计数视频序列中的人员。
让我们再次从导入所需的库开始。
import cv2
import numpy as np
import time
在这里,我们将使用与上一篇文章中讨论的相同的文件和代码模式。 如果您还没有阅读过该文章,我建议您阅读一下,因为它将阐明代码的基础知识。 作为参考,我们将在这里加载 YOLO 模型。
# Load Yolo
net=cv2.dnn.readNet("./yolov3.weights", "./yolov3.cfg")
# Classes
classes=[]
with open("coco.names","r") as f:
classes=[line.strip() for line in f.readlines()]
# Define Output Layers
layer_names=net.getLayerNames()
output_layers=[layer_names[i[0]-1] for i in net.getUnconnectedOutLayers()]
现在,我们将向模型输入一个视频文件,而不是图像。 OpenCV 提供了一个简单的接口来处理视频文件。 我们将创建一个 VideoCapture
对象的实例。 它的参数可以是附加设备的索引或一个视频文件。 我将使用一个视频。
cap = cv2.VideoCapture('./video.mp4')
我们也会将输出保存为视频序列。 为了保存我们的视频输出,我们将使用 Keras 中的 VideoWriter
对象实例。
out_video = cv2.VideoWriter( 'human.avi', cv2.VideoWriter_fourcc(*'MJPG'), 15., (640,480))
现在我们将从视频序列中捕获帧,使用 blob 处理它们并进行检测。(请查看上一篇文章以获取详细说明。)
frame = cv2.resize(frame, (640, 480))
height,width,channel=frame.shape
#detecting objects using blob. (320,320) can be used instead of (608,608)
blob=cv2.dnn.blobFromImage(frame,1/255,(320,320),(0,0,0),True,crop=False)
net.setInput(blob)
#Object Detection
outs=net.forward(outputlayers)
让我们获取每个检测到的对象的边界框坐标,并应用阈值以消除弱检测。 当然,不要忘记应用非极大值抑制 (Non-Maximum Suppression)。
# # Evaluate class ids, confidence score and bounding boxes for detected objects i.e. humans
class_ids=[]
confidences=[]
boxes=[]
for out in outs:
for detection in out:
scores=detection[5:]
class_id=np.argmax(scores)
confidence=scores[class_id]
if confidence>0.5:
# Object Detected
center_x=int(detection[0]*width)
center_y=int(detection[1]*height)
w=int(detection[2]*width)
h=int(detection[3]*height)
# Rectangle Co-ordinates
x=int(center_x-w/2)
y=int(center_y-h/2)
boxes.append([x,y,w,h])
confidences.append(float(confidence))
class_ids.append(class_id)
# Non-max Suppression
indexes=cv2.dnn.NMSBoxes(boxes,confidences,0.4,0.6)
在检测到的对象上绘制最终的边界框,并为每次检测增加计数器。
count = 0
# Draw bounding boxes
for i in range(len(boxes)):
if i in indexes:
x,y,w,h=boxes[i]
label=str(classes[class_ids[i]])
color=COLORS[i]
if int(class_ids[i] == 0):
count +=1
cv2.rectangle(frame,(x,y),(x+w,y+h),color,2)
cv2.putText(frame,label+" "+str(round(confidences[i],3)),(x,y-5),font,1, color, 1)
我们可以在屏幕上绘制帧号以及计数器,以便我们知道每帧中有多少人。
# draw counter
cv2.putText(frame, str(count), (100,200), cv2.FONT_HERSHEY_DUPLEX, 2, (0, 255, 255), 10)
cv2.imshow("Detected_Images",frame)
我们的模型现在将计算帧中存在的人数。 为了更好地估计队列长度,我们可以在处理之前定义我们的感兴趣区域。
# Region of interest
ROI = [(100,100),(1880,100),(100,980),(1880,980)]
然后将帧聚焦在该区域内,如下所示
# draw Region Of Interest
cv2.rectangle(frame, ROI[0], ROI[3], (255,255,0), 2)
这是最终视频处理的快照。
结束语
在本系列文章中,我们学习了如何为计算机视觉问题实现深度神经网络。 我们从头开始实现了神经网络,使用了迁移学习,并使用了预训练模型来检测感兴趣的对象。 一开始,使用自定义训练的模型似乎可能更好,尤其是在处理拥挤的场景,在这种场景中,感兴趣的对象并不清晰可见时。 在这种情况下,自定义训练的模型会更准确,但准确性是以时间和资源消耗为代价的。 像 YOLO 这样的某些最先进的算法比自定义训练的模型更有效,并且可以在保持合理的准确度水平的同时实时实现。
我们在此系列文章中探讨的解决方案并不完美,可以改进,但您现在应该能够清楚地了解使用深度学习模型进行对象检测的含义。 我鼓励您尝试我们所经历的解决方案。 也许您可以微调参数以获得更好的预测,或者实现 ROI 或 LOI 以更好地估计队列中的人数。 您也可以尝试对象跟踪,但请不要忘记与我们分享您的发现。 编码愉快!