frame实现整个框架的跳转_yolov4+opencv实现目标检测

frame实现整个框架的跳转_yolov4+opencv实现目标检测_第1张图片

在目标检测研究领域,基于深度学习模型的方法效果要比传统的特征检测方法好很多。传统的如基于harr特征、hog特征等速度很快,但精度总是不是很理想。基于深度网络的智能算法包括两步法和一步法。两步法模型包括R-CNN、Fast R-CNN等,一步法模型包括yolo系列和ssd等。下面基于opencv提供的DNN深度神经模块,结合开源的yolo系列的yolov4实现目标检测。

  1. 基于HOG特征行人检测

HOG特征是计算方向梯度直方图得到的高维向量,可用于描述图像的局部纹理特征。它的基本思想是:将一副图像划分为小的单元cell,尺寸为8*8的cell,统计这8*8个cell内的方向梯度直方图,然后将4个cell构成一个block块,将这个block块内所有的cell内的hog descriptor特征串联起来就可以得到这个block的HOG特征。最后将每个block的HOG特征串联起来形成整个图像的HOG特征。

如下为基于HOG特征来实现行人检测的代码:

# -*- coding: utf-8 -*-
import cv2
import numpy as np

#判断框与框重叠的情况
def is_inside(o, i):
    ox, oy, ow, oh = o
    ix, iy, iw, ih = i
    return ox > ix and oy > iy and ox + ow < ix + iw and oy + oh < iy + ih

#输入检测图像
img = cv2.imread("1.jpg")

#创建hog算子
hog = cv2.HOGDescriptor()
#设置svm分类器
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
#基于hog算子对整个图像开展检测
found, w = hog.detectMultiScale(img, winStride=(8, 8), scale=1.05)
#对检测到的图像box进行重合去除处理
found_filtered = []
for ri, r in enumerate(found):
    for qi, q in enumerate(found):
        if ri != qi and is_inside(r, q):
            break
    else:
        found_filtered.append(r)
        
#对box中的行人进行标注
for person in found_filtered:
    x, y, w, h = person
    cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 255), 2)
    
#显示检测图像
cv2.imshow("people detection", img)
cv2.waitKey(0)

运行后得到的结果如下:

frame实现整个框架的跳转_yolov4+opencv实现目标检测_第2张图片

这种结果还是不错的,但遇到目标较多时就会出现问题,下图看到中间两个行人就落在一个框内了。

frame实现整个框架的跳转_yolov4+opencv实现目标检测_第3张图片

2. 基于yolov4实现目标检测

yolo框架系列在图像目标检测里应用还是非常多的,框架系列从yolov1,v2,v3,v4以及到今年6月份发布的v5。yolov4属于网络调优集大成结果,通过多种方式改善原有框架的性能,包括在backbone特征提取部分、neck特征增强部分以及head部分进行了许多优化,最终在fps和ap方面比yolov3性能都要好。我们先来实践,后面再慢慢理解其原理。

整个过程分为几步:

第一步,下载yolov4框架的配置文件和权值模型,以及coco.names类别。

这三个文件名为:yolov4.cfg,yolov4.weights,coco.names。因为都是开源的,可以直接从github上下载。地址为:

Build software better, together​github.com

第二步,基于opencv的dnn模块加入yolov4配置文件实现网络模型创建

net = cv.dnn_DetectionModel('yolov4.cfg', 'yolov4.weights')
net.setInputSize(320, 320)
net.setInputScale(1.0 / 255)
net.setInputSwapRB(True)

第三步,读取coco.names文件的类别形成列表

with open('coco.names', 'rt') as f:
	names = f.read().rstrip('n').split('n')

第四步,读入新的图像基于模型net对象的detect方法开展检测处理

frame = cv.imread("1.jpg")
classes, confidences, boxes = net.detect(frame, confThreshold=0.1, nmsThreshold=0.4)

detect方法的参数解释如下:
frame: 图像; confThreshold: 用于根据置信度筛选框的阈值; nmsThreshold: 非最大抑制中使用的阈值。

处理之后返回:
[out] classes 结果检测中的类索引。
[out] confidences 一组相应的置信度。
[out] boxes 一组边界框。

第五步,设置置信度阈值筛选满足条件的目标,对目标进行标注。

or classId, confidence, box in zip(classes.flatten(), confidences.flatten(), boxes):
	if confidence>threshold:
		left, top, w, h = box		
		cv.rectangle(frame, box, color=(0, 255, 0), thickness=3)
		cv.rectangle(frame, (left, top), (left + w, top + h), (255, 	255, 255), cv.FILLED)
		cv.putText(frame, labels[classId], (left, top), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0))

第六步,查看最终输出结果

cv.imshow('out', frame)
cv.waitKey(0)

最终输出结果为:

frame实现整个框架的跳转_yolov4+opencv实现目标检测_第4张图片

可以看出,同一张图,采用hog特征以及svm分类器识别的内容和基于yolov4模型检测到的目标差别太多了。基于yolov4模型对手提袋都检测出来了。当然coco.names类别也有限,所以图中的某些目标也是没有标注出来的。

最后给出整个识别过程的源代码:

# -*- coding: utf-8 -*-
import cv2 as cv
import time

#创建模型net
net = cv.dnn_DetectionModel('yolov4.cfg', 'yolov4.weights')
net.setInputSize(320, 320)
net.setInputScale(1.0 / 255)
net.setInputSwapRB(True)

#创建类别names
with open('coco.names', 'rt') as f:
	names = f.read().rstrip('n').split('n')

#读入图像开展目标检测处理
frame = cv.imread('2.jpg')
classes, confidences, boxes = net.detect(frame, confThreshold=0.1, nmsThreshold=0.4)

#对识别目标进行标注
for classId, confidence, box in zip(classes.flatten(), confidences.flatten(), boxes):
	if confidence>0.5:
		left, top, w, h = box
		cv.rectangle(frame, (left, top), (left + w, top + h), (0,255,0),2 )
		cv.putText(frame, names[classId], (left, top), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255))

cv.imshow('out', frame)
cv.waitKey(0)

你可能感兴趣的:(frame实现整个框架的跳转)