OpenCV调用YOLOv4进行目标检测!是真的强!

目标检测就是对目标进行动态实时跟踪定位,常见的目标检测算法有 R-CNN、Fast R-CNN、Faster R-CNN、SSD、Yolo 等,其中 Yolo 的速度和精确度都比较高,且只需训练一次,使用起来比较方便。

这里我们就使用官方现成的模型来检测图片,看一看效果,先学会使用流程,以后再训练自己的模型。

注意:opencv-python 目前只有 4.4.0 版本适配了 YOLOv4


导入库

import numpy as np
import time
import cv2

设置标签和标注颜色

LABELS = open("coco.names").read().strip().split("\n")
np.random.seed(666)
COLORS = np.random.randint(0, 255, size=(len(LABELS), 3), dtype="uint8")

coco.names 内包含了很多目标标签,如 person、bicycle、car 等,且按一定顺序排列,里面基本包含了 Yolo 官方模型中可检测的对象。该文件可从以下链接中提取:https://gitee.com/public_sharing/ObjectDetection-YOLO/blob/master/coco.names

每个对象配备了不一样的颜色,以便在图片中标记时便于区分。


加载网络

# 导入 YOLO 配置和权重文件并加载网络:
net = cv2.dnn_DetectionModel('yolov4.cfg', 'yolov4.weights')
# 获取 YOLO 未连接的输出图层
layer = net.getUnconnectedOutLayersNames()

yolov4.cfg 和 yolov4.weights 文件就是官方提供的模型,下载链接:https://pan.baidu.com/s/1XrcPHdp2_4c-dKge2Guw4w 提取码:xsxb 。如果失效,可以直接百度搜索 Yolov4模型下载,有很多人都分享出来了。

cv2.dnn_DetectionModel 是 opencv 4.1.2 开始新增的方法,用于加载网络。以前是使用 cv2.dnn.readNetFromDarknet ,此处使用也可以达到同样的效果。

getUnconnectedOutLayersNames() 用于提取输出图层的名称,yolo 含有很多的图层,可以使用 getLayerNames() 将所有图层的名称提取出来。但在这里,我们只需要使用 yolo 的最后输出图层。


检测图片

# 导入图片
image = cv2.imread('timg.jpg')
# 获取图片尺寸
(H, W) = image.shape[:2]

# 从输入图像构造一个 blob,然后执行 YOLO 对象检测器的前向传递,给我们边界盒和相关概率
blob = cv2.dnn.blobFromImage(image, 1/255.0, (416, 416),
                             swapRB=True, crop=False)
net.setInput(blob)
start = time.time()
# 前向传递,获得信息
layerOutputs = net.forward(layer)
# 用于得出检测时间
end = time.time()
print("[INFO] YOLO took {:.6f} seconds".format(end - start))

blobFromImage 用于对图像进行预处理
cv2.dnn.blobFromImage(image[, scalefactor[, size[, mean[, swapRB[, crop[, ddepth]]]]]])

  • image:输入图像
  • scalefactor:图像各通道数值的缩放比例
  • size:输出图像的空间尺寸
  • mean:用于各通道减去的值,以降低光照的影响
  • swapRB:交换 RB 通道,默认为 False
  • crop:图像裁剪,默认为 False。当值为 True 时,先按比例缩放,然后从中心裁剪成 size 尺寸
  • ddepth:输出的图像深度,可选 CV_32F 或者 CV_8U

数据提取

boxes = []
confidences = []
classIDs = []

# 循环提取每个输出层
for output in layerOutputs:
    # 循环提取每个框
    for detection in output:
        # 提取当前目标的类 ID 和置信度
        scores = detection[5:]
        classID = np.argmax(scores)
        confidence = scores[classID]
        # 通过确保检测概率大于最小概率来过滤弱预测
        if confidence > 0.5:
            # 将边界框坐标相对于图像的大小进行缩放,YOLO 返回的是边界框的中心(x, y)坐标,
            # 后面是边界框的宽度和高度
            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))
            # 更新边界框坐标、置信度和类 id 的列表
            boxes.append([x, y, int(width), int(height)])
            confidences.append(float(confidence))
            classIDs.append(classID)

3 个列表内保存的内容:

  • boxes:对象的边界框
  • confidences :YOLO 分配给对象的置信度值,较低的置信度值表示该对象可能不是网络认为的对象。上面的代码中将过滤掉小于 0.5 阈值的对象
  • classIDs:检测到的对象的类标签

这样每个被提取出的对象,都确定了标签和区域坐标就、位置。接下来就是在图片中标记出来,便于我们观看。


标记显示

# 非最大值抑制,确定唯一边框
idxs = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.3)
# 确定每个对象至少有一个框存在
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(image, (x, y), (x + w, y + h), color, 1, lineType=cv2.LINE_AA)
        text = "{}: {:.4f}".format(LABELS[classIDs[i]], confidences[i])
        cv2.putText(image, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX,
            0.5, color, 1, lineType=cv2.LINE_AA)
cv2.imshow("Tag", image)
cv2.waitKey(0)

对于每个对象,Yolo 会框出 3 个左右的区域,我们只需要显示出最合适的区域。非最大值抑制,就是搜索出局部最大值,将置信度最大的框保存,其余剔除。

cv2.dnn.NMSBoxes(bboxes, scores, score_threshold, nms_threshold, eta=None, top_k=None)

  • bboxes:一组边框
  • scores:一组对应的置信度
  • score_threshold:置信度的阈值
  • nms_threshold:非最大抑制的阈值

之后将每个对象的方框和标签都画出来

结果展示:


完整代码

import numpy as np
import time
import cv2

LABELS = open("coco.names").read().strip().split("\n")
np.random.seed(666)
COLORS = np.random.randint(0, 255, size=(len(LABELS), 3), dtype="uint8")
# 导入 YOLO 配置和权重文件并加载网络:
net = cv2.dnn_DetectionModel('yolov4.cfg', 'yolov4.weights')
# 获取 YOLO 未连接的输出图层
layer = net.getUnconnectedOutLayersNames()
image = cv2.imread('timg.jpg')
# 获取图片尺寸
(H, W) = image.shape[:2]
# 从输入图像构造一个 blob,然后执行 YOLO 对象检测器的前向传递,给我们边界盒和相关概率
blob = cv2.dnn.blobFromImage(image, 1/255.0, (416, 416),
                             swapRB=True, crop=False)
net.setInput(blob)
start = time.time()
# 前向传递,获得信息
layerOutputs = net.forward(layer)
# 用于得出检测时间
end = time.time()
print("YOLO took {:.6f} seconds".format(end - start))

boxes = []
confidences = []
classIDs = []

# 循环提取每个输出层
for output in layerOutputs:
    # 循环提取每个框
    for detection in output:
        # 提取当前目标的类 ID 和置信度
        scores = detection[5:]
        classID = np.argmax(scores)
        confidence = scores[classID]
        # 通过确保检测概率大于最小概率来过滤弱预测
        if confidence > 0.5:
            # 将边界框坐标相对于图像的大小进行缩放,YOLO 返回的是边界框的中心(x, y)坐标,
            # 后面是边界框的宽度和高度
            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))
            # 更新边界框坐标、置信度和类 id 的列表
            boxes.append([x, y, int(width), int(height)])
            confidences.append(float(confidence))
            classIDs.append(classID)
# 非最大值抑制,确定唯一边框
idxs = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.3)
# 确定每个对象至少有一个框存在
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(image, (x, y), (x + w, y + h), color, 1, lineType=cv2.LINE_AA)
        text = "{}: {:.4f}".format(LABELS[classIDs[i]], confidences[i])
        cv2.putText(image, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX,
            0.5, color, 1, lineType=cv2.LINE_AA)
cv2.imshow("Tag", image)
cv2.waitKey(0)


源码地址

  • 8
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 要使用OpenCV调用Yolov5目标识别,需要先安装OpenCV和Yolov5。然后,可以使用OpenCV的cv::dnn模块来加载Yolov5模型,并使用它来检测图像中的目标。具体步骤如下: 1. 安装OpenCV和Yolov5。 2. 下载Yolov5预训练模型权重文件和配置文件。 3. 使用OpenCV的cv::dnn模块加载Yolov5模型。可以使用以下代码: cv::dnn::Net net = cv::dnn::readNetFromDarknet("yolov5.cfg", "yolov5.weights"); 4. 加载图像并将其转换为OpenCV的Mat格式。 5. 将Mat格式的图像传递给Yolov5模型进行目标检测。可以使用以下代码: cv::Mat inputBlob = cv::dnn::blobFromImage(image, 1 / 255., cv::Size(416, 416), cv::Scalar(, , ), true, false); net.setInput(inputBlob); cv::Mat detectionMat = net.forward(); 6. 解析检测结果并在图像上绘制检测框。可以使用以下代码: float* data = (float*)detectionMat.data; for (int i = ; i < detectionMat.rows; i++, data += detectionMat.cols) { cv::Mat scores = detectionMat.row(i).colRange(5, detectionMat.cols); cv::Point classIdPoint; double confidence; cv::minMaxLoc(scores, , &confidence, , &classIdPoint); if (confidence > confidenceThreshold) { int centerX = (int)(data[] * image.cols); int centerY = (int)(data[1] * image.rows); int width = (int)(data[2] * image.cols); int height = (int)(data[3] * image.rows); int left = centerX - width / 2; int top = centerY - height / 2; cv::rectangle(image, cv::Rect(left, top, width, height), cv::Scalar(, 255, ), 2); } } 7. 显示图像并等待用户按下任意键退出。可以使用以下代码: cv::imshow("Yolov5 Object Detection", image); cv::waitKey(); 以上就是使用OpenCV调用Yolov5目标识别的基本步骤。需要注意的是,Yolov5模型的输入图像大小为416x416,因此需要将输入图像缩放到该大小。另外,需要设置置信度阈值来过滤低置信度的检测结果。 ### 回答2: Opencv是一个流行的计算机视觉库,它可以用来实现各种图像处理和计算机视觉应用,比如目标识别、物体跟踪、人脸识别等。而Yolov5则是一种基于深度学习目标检测算法,它可以用来识别图像中的各种物体,并将它们标注出来。下面我们来介绍一下如何使用Opencv调用Yolov5进行目标识别。 首先,我们需要安装Yolov5和Opencv的相关库文件。Yolov5可以直接通过Github的仓库获取,而Opencv可以通过pip命令进行安装,安装完成后我们需要在Python中导入这些库文件。 ``` python import cv2 from matplotlib import pyplot as plt from numpy import random import torch import torch.backends.cudnn as cudnn #导入Yolov5模型的‘detect'函数 from yolov5.models.experimental import attempt_load from yolov5.utils.general import non_max_suppression from yolov5.utils.datasets import letterbox from yolov5.utils.plots import plot_one_box ``` 接下来,我们需要加载训练好的Yolov5模型,以及设置一些模型参数。 ``` python # 指定设备 device = 'cpu' # 这里如果有GPU可用,建议使用GPU,否则多张图片进行推断速度会很慢 weights_path = "C:/Users/*****/yolov5/weights/yolov5m.pt" # 训练好的模型权重地址 img_size = 640 # 输入图片的大小 conf_thres = 0.5 # 目标置信度阈值 iou_thres = 0.4 # NMS的IOU阈值 augment = False # 图像增 view_img = False # 视觉化推断的结果 save_txt = False # 是否保存结果的txt文件 save_conf = False # 是否输出每个目标的置信度 ``` 然后,我们需要加载输入图片,并将其转换为Yolov5模型所需的格式。 ``` python # 使用Opencv加载图片 img_path = "C:/Users/*****/yolov5/data/images/test.jpg" img = cv2.imread(img_path) # 将图像转换为RGB格式 img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 对图像进行缩放和填充,使其符合Yolov5模型输入要求 img = letterbox(img, img_size, 32)[0] # 将图像转换为Tensor格式,并添加一个批次维度 img = torch.from_numpy(img).to(device) img = img.unsqueeze(0).float() ``` 接下来,我们可以使用Yolov5模型的“detect”函数进行目标识别了,这个函数会返回检测到的目标信息。 ``` python # 加载Yolov5模型 model = attempt_load(weights_path, map_location=device) # 模型加载 # 将模型设置为推断模式 model.eval() # 设置GPU加速 if device == 'cuda': cudnn.benchmark = True model.cuda() with torch.no_grad(): # 将图像传入模型 detections = model(img) # 对模型的输出进行NMS处理 detections = non_max_suppression(detections, conf_thres=conf_thres, iou_thres=iou_thres) ``` 最后,我们可以将检测到的目标信息绘制到输入图片上,以便可视化识别结果。 ``` python # 将检测结果可视化 if detections is not None: for detection in detections: if save_txt: # 将目标框的信息保存到txt文件中 with open(txt_path + 'det.txt', mode='a') as file: file.write( '%g %g %g %g %g %g\n' % ( detection[0], detection[1], detection[2], detection[3], detection[4], detection[5])) # 按类别绘制目标框和置信度 colors = [[random.randint(0, 255) for _ in range(3)] for _ in range(len(detection))] for i, det in enumerate(detection): # detections per image plot_one_box( det[:4], img, label='%.2f' % det[4], color=colors[i], line_thickness=3) if view_img: # 将结果显示在窗口中 plt.imshow(img) plt.show() ``` 综上所述,通过以上步骤,我们可以使用Opencv调用Yolov5进行目标识别,实现对图像中物体的检测和识别。同时,由于Yolov5模型具有较高的检测精度和速度,因此在实际应用中也有着广泛的应用前景。 ### 回答3: OpenCV是一种开源的计算机视觉库,支持图像和视频的处理、深度学习、目标识别、跟踪等功能,而yolov5则是一种高效的目标检测模型,由ultralytics公司研发,目前已成为业界广泛使用的目标识别工具之一。在使用OpenCV进行目标识别时,可以结合yolov5进行更准确、高效的检测。 接下来介绍如何使用OpenCV调用yolov5进行目标识别。 1. 安装OpenCV和yolov5 首先,需要安装OpenCV和yolov5。可以使用pip命令快速安装,也可以从源码进行编译安装。在安装OpenCV时需要注意,需要安装OpenCV深度学习模块,以便于后续调用yolov5。 2. 定义yolov5模型 在进行目标识别前,需要定义yolov5模型。可以使用官方提供的预训练模型,也可以根据自己的数据进行训练得到模型。在使用模型前,需要将模型加载到内存中,并定义好输入和输出层。 3. 调用OpenCV进行目标识别 接下来,可以调用OpenCV对图像进行目标识别。首先需要读取图像,然后将图像进行预处理,包括缩放、裁剪、归一化等操作,以便于输入到yolov5模型进行检测检测完成后,可以得到检测结果,包括目标类别、位置、置信度等信息,可以根据需求进行后续处理,比如绘制检测框、标注类别等。 以上就是使用OpenCV调用yolov5进行目标识别的基本流程。需要注意的是,yolov5是一种较为复杂的模型,运行时需要较大的计算资源,建议在较为高配置的机器上进行模型的训练和调用。同时,在使用yolov5时也需要注意模型参数的选择和调整,以便于得到更准确、高效的检测结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值