手把手教你使用LabVIEW OpenCV dnn实现物体识别(Object Detection)含源码

简介: 今天和大家一起分享如何使用LabVIEW调用pb模型实现物体识别

前言

今天和大家一起分享如何使用LabVIEW调用pb模型实现物体识别,本博客中使用的智能工具包可到主页置顶博客LabVIEW AI视觉工具包(非NI Vision)下载与安装教程中下载

一、物体识别算法原理概述

1、物体识别的概念

物体识别也称目标检测,目标检测所要解决的问题是目标在哪里以及其状态的问题。但是,这个问题并不是很容易解决。形态不合理,对象出现的区域不确定,更不用说对象也可以是多个类别。
image.png

目标检测用的比较多的主要是RCNN,spp- net,fast- rcnn,faster- rcnn;YOLO系列,如YOLOV3和YOLOV4;除此之外还有SSD,ResNet等。

2、Yolo算法原理概述

Yolo的识别原理简单清晰。对于输入的图片,将整张图片分为7×7(7为参数,可调)个方格。当某个物体的中心点落在了某个方格中,该方格则负责预测该物体。每个方格会为被预测物体产生2(参数,可调)个候选框并生成每个框的置信度。最后选取置信度较高的方框作为预测结果。
image.png

二、opencv调用darknet物体识别模型(yolov3/yolov4)

相关源码及模型在darknt文件夹下
image.png

使用darknet训练yolo的模型,生成weights文件。使用opencv调用生成的模型

1、darknet模型的获取

文件含义:

  • cfg文件:模型描述文件
  • weights文件:模型权重文件

Yolov3获取链接:
https://github.com/pjreddie/darknet/blob/master/cfg/yolov3.cfg
https://pjreddie.com/media/files/yolov3.weights

Yolov4获取链接:
https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.cfg
https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.weights

2、python调用darknet模型实现物体识别

(1)dnn模块调用darknet模型

net = cv2.dnn.readNetFromDarknet("yolov3/yolov3.cfg", "yolov3/yolov3.weights")

(2)获取三个输出端的LayerName

使用getUnconnectedOutLayer获取三个只有输入,没有输出的层的名字,Yolov3的三个输出端层名为:['yolo_82', 'yolo_94', 'yolo_106']

def getOutputsNames(net):
    # Get the names of all the layers in the network
    layersNames = net.getLayerNames()
    # Get the names of the output layers, i.e. the layers with unconnected outputs
    return [layersNames[i - 1] for i in net.getUnconnectedOutLayers()]

(3)图像预处理

使用blobFromImage将图像转为image
Size=(416,416)或(608,608)
Scale=1/255
Means=[0,0,0]

blob = cv2.dnn.blobFromImage(frame, 1/255, (416, 416), [0,0,0], 1, crop=False)

(4)推理

使用net.forward(multiNames)获取多个层的结果,其中getOutputsNames(net)=['yolo_82', 'yolo_94', 'yolo_106']

net.setInput(blob)
outs = net.forward(getOutputsNames(net))

(5)后处理(postrocess)

获取的结果(outs)里面有三个矩阵(out),每个矩阵的大小为85*n,n表示检测到了n个物体,85的排列顺序是这样的:
第0列代表物体中心x在图中的位置(0~1)
第1列表示物体中心y在图中的位置(0~1)
第2列表示物体的宽度
第3列表示物体的高度
第4列是置信概率,值域为[0-1],用来与阈值作比较决定是否标记目标
第5~84列为基于COCO数据集的80分类的标记权重,最大的为输出分类。
使用这些参数保留置信度高的识别结果(confidence>confThreshold)

def postprocess(frame, outs):
    frameHeight = frame.shape[0]
    frameWidth = frame.shape[1]
    classIds = []
    confidences = []
    boxes = []
    classIds = []
    confidences = []
    boxes = []
    for out in outs:
        for detection in out:
            scores = detection[5:]
            classId = np.argmax(scores)
            confidence = scores[classId]
            if confidence > confThreshold:
                center_x = int(detection[0] * frameWidth)
                center_y = int(detection[1] * frameHeight)
                width = int(detection[2] * frameWidth)
                height = int(detection[3] * frameHeight)
                left = int(center_x - width / 2)
                top = int(center_y - height / 2)
                classIds.append(classId)
                confidences.append(float(confidence))
                boxes.append([left, top, width, height])
    print(boxes)
    print(confidences)

(6)后处理(postrocess)

使用NMSBoxes函数过滤掉重复识别的区域。

    indices = cv.dnn.NMSBoxes(boxes, confidences, confThreshold, nmsThreshold)  
    for i in indices:
        box = boxes[i]
        left = box[0]
        top = box[1]
        width = box[2]
        height = box[3]
        drawPred(classIds[i], confidences[i], left, top, left + width, top + height)

(7)画出检测到的对象

def drawPred(classId, conf, left, top, right, bottom):
    # Draw a bounding box.
    cv.rectangle(frame, (left, top), (right, bottom), (0, 0, 255))

    label = '%.2f' % conf

    # Get the label for the class name and its confidence
    if classes:
        assert(classId < len(classes))
        label = '%s:%s' % (classes[classId], label)

    #Display the label at the top of the bounding box
    labelSize, baseLine = cv.getTextSize(label, cv.FONT_HERSHEY_SIMPLEX, 0.5, 1)
    top = max(top, labelSize[1])
    cv.putText(frame, label, (left, top), cv.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255))

(8)完整源码及检测结果(cv_call_yolo.py)

import cv2
cv=cv2
import numpy as np
import time
net = cv2.dnn.readNetFromDarknet("yolov3/yolov3.cfg", "yolov3/yolov3.weights")
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)

confThreshold = 0.5  #Confidence threshold
nmsThreshold = 0.4   #Non-maximum suppression threshold
frame=cv2.imread("dog.jpg")
classesFile = "coco.names";
classes = None
with open(classesFile, 'rt') as f:
    classes = f.read().rstrip('\n').split('\n')

def getOutputsNames(net):
    # Get the names of all the layers in the network
    layersNames = net.getLayerNames()
    # Get the names of the output layers, i.e. the layers with unconnected outputs
    return [layersNames[i - 1] for i in net.getUnconnectedOutLayers()]
print(getOutputsNames(net))
# Remove the bounding boxes with low confidence using non-maxima suppression

def postprocess(frame, outs):
    frameHeight = frame.shape[0]
    frameWidth = frame.shape[1]
    classIds = []
    confidences = []
    boxes = []
    # Scan through all the bounding boxes output from the network and keep only the
    # ones with high confidence scores. Assign the box's class label as the class with the highest score.
    classIds = []
    confidences = []
    boxes = []
    for out in outs:
        for detection in out:
            scores = detection[5:]
            classId = np.argmax(scores)
            confidence = scores[classId]
            if confidence > confThreshold:
                center_x = int(detection[0] * frameWidth)
                center_y = int(detection[1] * frameHeight)
                width = int(detection[2] * frameWidth)
                height = int(detection[3] * frameHeight)
                left = int(center_x - width / 2)
                top = int(center_y - height / 2)
                classIds.append(classId)
                confidences.append(float(confidence))
                boxes.append([left, top, width, height])

    # Perform non maximum suppression to eliminate redundant overlapping boxes with
    # lower confidences.
    print(boxes)
    print(confidences)  
    indices = cv.dnn.NMSBoxes(boxes, confidences, confThreshold, nmsThreshold) 
    for i in indices:
        #print(i)
        #i = i[0]
        box = boxes[i]
        left = box[0]
        top = box[1]
        width = box[2]
        height = box[3]
        drawPred(classIds[i], confidences[i], left, top, left + width, top + height)

    # Draw the predicted bounding box
def drawPred(classId, conf, left, top, right, bottom):
    # Draw a bounding box.
    cv.rectangle(frame, (left, top), (right, bottom), (0, 0, 255))
    label = '%.2f' % conf    
    # Get the label for the class name and its confidence
    if classes:
        assert(classId < len(classes))
        label = '%s:%s' % (classes[classId], label)
    #Display the label at the top of the bounding box
    labelSize, baseLine = cv.getTextSize(label, cv.FONT_HERSHEY_SIMPLEX, 0.5, 1)
    top = max(top, labelSize[1])
    cv.putText(frame, label, (left, top), cv.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255))
blob = cv2.dnn.blobFromImage(frame, 1/255, (416, 416), [0,0,0], 1, crop=False)
t1=time.time()
net.setInput(blob)
outs = net.forward(getOutputsNames(net))
print(time.time()-t1)
postprocess(frame, outs)
t, _ = net.getPerfProfile()
label = 'Inference time: %.2f ms' % (t * 1000.0 / cv.getTickFrequency())
cv.putText(frame, label, (0, 15), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255))
cv2.imshow("result",frame)

image.png

3、LabVIEW调用darknet模型实现物体识别yolo_example.vi

(1)LabVIEW调用yolov3的方式及步骤和python类似,源码如下所示:
image.png

将带识别图片与yolo_example.vi置于同一路径下,即可进行物体识别

(2)识别结果如下:
image.png

4、LabVIEW实现实时摄像头物体识别(yolo_example_camera.vi)

(1)使用GPU加速

使用顺序结构检测神经网络推理的时间
image.png

比较使用GPU和不使用GPU两种情况下的推理速度
普通模式:net.serPerferenceBackend(0),net.serPerferenceTarget(0)
Nvidia GPU模式:net.serPreferenceBackend(5), net.serPerferenceTarget(6)
image.png

注:普通的c++、python、LabVIEW版本的opencv,即便选了GPU模式也没用,程序仍然运行在CPU上,需要安装CUDA和CUDNN后重新从源码编译opencv

(2)程序源码如下:
image.png

(3)物体识别结果如下:
image.png

注意,使用如上程序,可以点击STOP按钮,停止本次物体识别,也可勾选使用GPU进行加速

(4)使用GPU加速结果:
image.png

三、tensorflow的物体识别模型调用

相关源码及模型在tf1文件夹下
image.png

1、下载预训练模型并生成pbtxt文件

(1)下载ssd_mobilenet_v2_coco,下载地址如下:
http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v2_coco_2018_03_29.tar.gz

(2)解压后的文件内容
image.png

(3)根据pb模型生成pbtxt文件
运行 tf_text_graph_ssd.py以生成pptxt文件
在cmd中运行:
python tf_text_graph_ssd.py --input ssd_mobilenet_v1_coco_2017_11_17/frozen_inference_graph.pb --config ssd_mobilenet_v1_coco_2017_11_17/ssd_mobilenet_v1_coco.config --output ssd_mobilenet_v1_coco_2017_11_17.pbtxt

2、LabVIEW调用tensorflow模型推理并实现物体识别(callpb.vi)

(1)程序源码如下:
image.png

(2)运行结果如下:
image.png

四、项目源码及模型下载

关注微信公众号:VIRobotics,回复:yolov3 即可获取源码及模型

总结拓展

可以使用Yolov3训练自己的数据集,具体训练方法可参考博客:https://blog.csdn.net/qq_38915710/article/details/97112788
可实现案例:口罩佩戴识别、肺炎分类、CT等,如口罩佩戴检测

image.png

如果有问题可以在评论区里讨论,如您想要探讨更多关于LabVIEW与人工智能技术,欢迎加入我们的技术交流群:705637299。进群请备注:LabVIEW机器视觉

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
24天前
|
机器学习/深度学习 监控 算法
基于计算机视觉(opencv)的运动计数(运动辅助)系统-源码+注释+报告
基于计算机视觉(opencv)的运动计数(运动辅助)系统-源码+注释+报告
40 3
|
27天前
|
缓存 并行计算 Ubuntu
Jetson 学习笔记(十一):jetson agx xavier 源码编译ffmpeg(3.4.1)和opencv(3.4.0)
本文是关于在Jetson AGX Xavier上编译FFmpeg(3.4.1)和OpenCV(3.4.0)的详细教程,包括编译需求、步骤、测试和可能遇到的问题及其解决方案。还提供了Jetson AGX Xavier编译CUDA版本的OpenCV 4.5.0的相关信息。
57 4
Jetson 学习笔记(十一):jetson agx xavier 源码编译ffmpeg(3.4.1)和opencv(3.4.0)
|
27天前
|
Ubuntu 应用服务中间件 nginx
Ubuntu安装笔记(三):ffmpeg(3.2.16)源码编译opencv(3.4.0)
本文是关于Ubuntu系统中使用ffmpeg 3.2.16源码编译OpenCV 3.4.0的安装笔记,包括安装ffmpeg、编译OpenCV、卸载OpenCV以及常见报错处理。
114 2
Ubuntu安装笔记(三):ffmpeg(3.2.16)源码编译opencv(3.4.0)
|
16天前
|
Ubuntu 编译器 计算机视觉
Ubuntu系统编译OpenCV4.8源码
【10月更文挑战第17天】只要三步即可搞定,第一步是下载指定版本的源码包;第二步是安装OpenCV4.8编译需要的编译器与第三方库支持;第三步就是编译OpenCV源码包生成安装文件并安装。
|
24天前
|
机器学习/深度学习 算法 安全
基于深度学习的目标检测的介绍(Introduction to object detection with deep learning)
基于深度学习的目标检测的介绍(Introduction to object detection with deep learning)
22 0
|
3月前
|
UED 开发工具 iOS开发
Uno Platform大揭秘:如何在你的跨平台应用中,巧妙融入第三方库与服务,一键解锁无限可能,让应用功能飙升,用户体验爆棚!
【8月更文挑战第31天】Uno Platform 让开发者能用同一代码库打造 Windows、iOS、Android、macOS 甚至 Web 的多彩应用。本文介绍如何在 Uno Platform 中集成第三方库和服务,如 Mapbox 或 Google Maps 的 .NET SDK,以增强应用功能并提升用户体验。通过 NuGet 安装所需库,并在 XAML 页面中添加相应控件,即可实现地图等功能。尽管 Uno 平台减少了平台差异,但仍需关注版本兼容性和性能问题,确保应用在多平台上表现一致。掌握正确方法,让跨平台应用更出色。
49 0
|
3月前
|
数据采集 API TensorFlow
简化目标检测流程:深入探讨TensorFlow Object Detection API的高效性与易用性及其与传统方法的比较分析
【8月更文挑战第31天】TensorFlow Object Detection API 是一项强大的工具,集成多种先进算法,支持 SSD、Faster R-CNN 等模型架构,并提供预训练模型,简化目标检测的开发流程。用户只需准备数据集并按要求处理,选择预训练模型进行微调训练即可实现目标检测功能。与传统方法相比,该 API 极大地减少了工作量,提供了从数据预处理到结果评估的一站式解决方案,降低了目标检测的技术门槛,使初学者也能快速搭建高性能系统。未来,我们期待看到更多基于此 API 的创新应用。
34 0
|
4月前
|
Ubuntu 编译器 计算机视觉
Ubuntu系统下编译OpenCV4.8源码
在Ubuntu上源码安装OpenCV 4.8分为三步:1) 下载源码包,使用`wget`命令;2) 安装依赖,如`g++`, `cmake`, `make`等;3) 创建编译目录,运行`cmake`配置,接着`make`编译,最后`sudo make install`安装。安装完成后,通过编写和运行一个简单的OpenCV C++程序来验证环境配置正确性。
125 10
|
4月前
|
计算机视觉 iOS开发 C++
【OpenCV】在MacOS上源码编译OpenCV
【7月更文挑战第9天】在MacOS上源码编译OpenCV需分步进行: 1. 准备工作: 安装Xcode, Command Line Tools及依赖如CMake, Homebrew. 2. 获取OpenCV源码: 从官网下载并解压所需版本. 3. 编译OpenCV. 4. 安装OpenCV: 编译后使用`sudo make install`进行安装. 5. 验证安装: 编写简单C++程序测试OpenCV功能, 如读取并显示图片.
140 1
|
5月前
|
机器学习/深度学习 算法 数据库
【功能超全】基于OpenCV车牌识别停车场管理系统软件开发【含python源码+PyqtUI界面+功能详解】-车牌识别python 深度学习实战项目
【功能超全】基于OpenCV车牌识别停车场管理系统软件开发【含python源码+PyqtUI界面+功能详解】-车牌识别python 深度学习实战项目
下一篇
无影云桌面