上期文章,我们介绍了YOLOV4对象检测算法的模型以及基本知识,哪里还进行了图片的对象检测,如何使用YOLOV4进行视频检测与实时视频检测呢?毕竟我们绝大多数的需求必然是视频的实时对象检测
YOLOV4视频检测
import numpy as npimport timeimport cv2import oslabelsPath = "yolo-coco/coco.names"LABELS = Nonewith open(labelsPath, 'rt') as f: LABELS = f.read().rstrip('').split("")np.random.seed(42)COLORS = np.random.randint(0, 255, size=(len(LABELS), 3), dtype="uint8")weightsPath = "yolo-coco/yolov4.weights"configPath = "yolo-coco/yolov4.cfg"net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)ln = net.getLayerNames()ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]
首先加载模型在COCO数据集上的对象label,然后定义了随机的颜色,这里主要是为了后期检测到不同的对象时,采用不同的颜色边框进行标注
cv2.dnn.readNetFromDarknet(configPath, weightsPath)来加载YOLOV4的预训练模型,这里需要注意:opencv的版本需要时4.4版本
opencv4.4支持YOLOv4、EfficientDet检测模型,SIFT移至主库!
![8b422f3915458477cbbe35575257203d.png](https://i-blog.csdnimg.cn/blog_migrate/c3eadbbdd6d90d3de4af10909b7f26c4.jpeg)
SIFT
支持谷歌目标检测算法 EfficientDet
![01a2f9201d4d4721220dc5823e24107f.png](https://i-blog.csdnimg.cn/blog_migrate/b6fea706005aebaa4a4e3b8f7e7deea8.jpeg)
EfficientDet检测模型
新增光流算法 FlowNet2 demo:
![d7c503ddf3f932783f4f411fad3fdd4d.png](https://i-blog.csdnimg.cn/blog_migrate/0f0518dec3afd56618567163b1f6bd1e.jpeg)
FlowNet2 demo
增加对OpenVINO 2020.3 LTS / 2020.4 支持
![457532360fee779e10bedc77598335f8.png](https://i-blog.csdnimg.cn/blog_migrate/3220b009898537b6e023c6f8789be091.jpeg)
OpenVINO
由于opencv4.4支持了YOLOV4,因此我们可以使用opencv来实现YOLOV4的对象检测
![f7d8c749adb9b4e7a6c86e5dd2dd2ea2.png](https://i-blog.csdnimg.cn/blog_migrate/7cc4ac33d4f116c9f47188ec10fff56b.jpeg)
代码截图
截取视频帧进行神经网络检测
#vs = cv2.VideoCapture('videos/a1.mp4')vs = cv2.VideoCapture(0)time.sleep(2.0)writer = None(W, H) = (None, None)while True: (grabbed, frame) = vs.read() if not grabbed: break print('ok') if W is None or H is None: (H, W) = frame.shape[:2] blob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (416, 416),swapRB=True, crop=False) net.setInput(blob) start = time.time() layerOutputs = net.forward(ln) end = time.time()
cv2.VideoCapture(0)默认为打开摄像头,若想打开一段视频,直接在里面输入“路径地址”
(grabbed, frame) = vs.read() if not grabbed: break print('ok')
这里我们截取视频帧,若没有检测到视频,直接退出,若检测到视频,进行神经网络的检测
blob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (416, 416),swapRB=True, crop=False) net.setInput(blob) start = time.time() layerOutputs = net.forward(ln) end = time.time()
这里我们进行神经网络Blob 值的计算,然后进行神经网络的预测,并进行前向传递,这里跟其他神经网络不同的是,前向传递的是ln,神经网络的所有输出层
![0db3564b35505fdbd42a5944891f1398.png](https://i-blog.csdnimg.cn/blog_migrate/eba66a7f50cd26926c1fac22928fb468.jpeg)
代码截图
遍历输出层,得到检测结果
boxes = [] confidences = [] classIDs = [] for output in layerOutputs: for detection in output: scores = detection[5:] classID = np.argmax(scores) 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)
首先我们初始化了3个参数,分别是box(对象检测到的坐标), confidence(对象检测到的置信度)ID(对象的ID)
通过遍历所有的输出层,提取置信度大于0.5的对象,并记录每个对象的box、confidence、ID。
![409af44c0e7ad99c32a2658b2eeeef15.png](https://i-blog.csdnimg.cn/blog_migrate/332a46e51343fd42938a3f474d7b7079.jpeg)
代码截图
非最大值抑制
idxs = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4) if len(idxs) > 0: for i in idxs.flatten(): (x, y) = (boxes[i][0], boxes[i][1]) (w, h) = (boxes[i][2], boxes[i][3]) color = [int(c) for c in COLORS[classIDs[i]]] cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2) text = "{}: {:.4f}".format(LABELS[classIDs[i]], confidences[i]) cv2.putText(frame, text, (x, y - 5),cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2) cv2.imshow("Image", frame)key = cv2.waitKey(1) & 0xFFif key == ord("q"):break''' if writer is None: # initialize our video writer fourcc = cv2.VideoWriter_fourcc(*"MJPG") writer = cv2.VideoWriter("videos/123.avi", fourcc, 30, (frame.shape[1], frame.shape[0]), True) writer.write(frame)'''vs.release()cv2.destroyAllWindows()
为什么需要非最大抑制,因为YOLO系列对多个临近的对象检测会出3个以上的对象检测框,这些我们只需要提取边框最大,概率最大的那个对象
![10b16bf34eb74aed6c05afb4f75d126d.png](https://i-blog.csdnimg.cn/blog_migrate/ee3c6341abb2b311b5e36c65243f481f.jpeg)
无最大抑制检测图形
当没有非最大值抑制时,可以看出,神经网络在同一个对象上会有多个框,每个框都带有分类器的得分,这些并不是我们需要的。
使用非最大值抑制来提取最大的检测边框以及得分,并把边框与分类ID以及置信度实时显示到屏幕上,最后,若想退出程序,可以直接输入字母q
![8b5c586225ced3a0ba906cecd75bafb9.png](https://i-blog.csdnimg.cn/blog_migrate/9dccab716e685139de863c91ff4b567f.jpeg)
代码截图
视频对象检测保存视频
if writer is None: # initialize our video writer fourcc = cv2.VideoWriter_fourcc(*"MJPG") writer = cv2.VideoWriter("videos/123.avi", fourcc, 30, (frame.shape[1], frame.shape[0]), True) writer.write(frame)
当然,这部分代码需要跟前面vs = cv2.VideoCapture('videos/a1.mp4')打开视频配合
当我们进行一段视频检测完成后,我们希望保存检测完成的视频,这里直接使用CV2的VideoWriter写入功能
编码参数:cv2.VideoWriter_fourcc('I','4','2','0')---未压缩的YUV颜色编码,4:2:0色度子采样。兼容性好,但文件较大。文件扩展名.avi。
cv2.VideoWriter_fourcc('P','I','M','1')---MPEG-1编码类型,文件扩展名.avi。
cv2.VideoWriter_fourcc('X','V','I','D')---MPEG-4编码类型,视频大小为平均值,MPEG4所需要的空间是MPEG1或M-JPEG的1/10,它对运动物体可以保证有良好的清晰度,间/时间/画质具有可调性。文件扩展名.avi。
cv2.VideoWriter_fourcc('T','H','E','O')---OGGVorbis,音频压缩格式,有损压缩,类似于MP3等的音乐格式。,兼容性差,件扩展名.ogv。
cv2.VideoWriter_fourcc('F','L','V','1')---FLV是FLASH VIDEO的简称,FLV流媒体格式是一种新的视频格式。文件扩展名为.flv。
这里需要特别注意,选择的视频编码格式与要保存的视频后缀要保持一致,以上编码格式请参考,小编首次运行时,保存的视频是MP4格式,一直报错,通过搜索资料,才发现是由于保存的视频后缀有问题。参数中的30是视频的帧30FPS。