前言
明天和大家一起分享如何应用 LabVIEW 调用 pb 模型实现物体辨认,本博客中应用的智能工具包可到主页置顶博客 LabVIEW AI 视觉工具包(非 NI Vision)下载与装置教程中下载
一、物体辨认算法原理概述
1、物体辨认的概念
物体辨认 也称 指标检测,指标检测所要解决的问题是指标在哪里以及其状态的问题。然而,这个问题并不是很容易解决。状态不合理,对象呈现的区域不确定,更不用说对象也能够是多个类别。
指标检测用的比拟多的次要是 RCNN,spp- net,fast- rcnn,faster- rcnn;YOLO 系列,如 YOLOV3 和 YOLOV4;除此之外还有 SSD,ResNet 等。
2、Yolo 算法原理概述
Yolo 的辨认原理简略清晰。对于输出的图片,将整张图片分为 7×7(7 为参数,可调)个方格。当某个物体的中心点落在了某个方格中,该方格则负责预测该物体。每个方格会为被预测物体产生 2(参数,可调)个候选框并生成每个框的置信度。最初选取置信度较高的方框作为预测后果。
二、opencv 调用 darknet 物体辨认模型(yolov3/yolov4)
相干源码及模型在 darknt 文件夹下
应用 darknet 训练 yolo 的模型,生成 weights 文件。应用 opencv 调用生成的模型
1、darknet 模型的获取
文件含意:
- cfg 文件:模型形容文件
- weights 文件:模型权重文件
Yolov3 获取链接:
https://github.com/pjreddie/d…
https://pjreddie.com/media/fi…
Yolov4 获取链接:
https://github.com/AlexeyAB/d…
https://github.com/AlexeyAB/d…
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)
3、LabVIEW 调用 darknet 模型实现物体辨认 yolo_example.vi
(1)LabVIEW 调用 yolov3 的形式及步骤和 python 相似,源码如下所示:
将带辨认图片与 yolo_example.vi 置于同一门路下,即可进行物体辨认
(2)辨认后果如下:
4、LabVIEW 实现实时摄像头物体辨认(yolo_example_camera.vi)
(1)应用 GPU 减速
应用程序构造检测神经网络推理的工夫
比拟应用 GPU 和不应用 GPU 两种状况下的推理速度
一般模式:net.serPerferenceBackend(0),net.serPerferenceTarget(0)
Nvidia GPU 模式:net.serPreferenceBackend(5),net.serPerferenceTarget(6)
注:一般的 c ++、python、LabVIEW 版本的 opencv,即使选了 GPU 模式也没用,程序依然运行在 CPU 上,须要装置 CUDA 和 CUDNN 后从新从源码编译 opencv
(2)程序源码如下:
(3)物体辨认后果如下:
留神,应用如上程序,能够点击 STOP 按钮,进行本次物体辨认,也可勾选应用 GPU 进行减速
(4)应用 GPU 减速后果:
三、tensorflow 的物体辨认模型调用
相干源码及模型在 tf1 文件夹下
1、下载预训练模型并生成 pbtxt 文件
(1)下载 ssd_mobilenet_v2_coco,下载地址如下:
http://download.tensorflow.or…
(2)解压后的文件内容
(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)程序源码如下:
(2)运行后果如下:
四、我的项目源码及模型下载
链接:https://pan.baidu.com/s/1zwbL…
提取码:8888
总结拓展
能够应用 Yolov3 训练本人的数据集,具体训练方法可参考博客:https://blog.csdn.net/qq_3891…
可实现案例:口罩佩戴辨认、肺炎分类、CT 等,如口罩佩戴检测
更多对于 LabVIEW 与人工智能技术,可增加技术交换群进一步探讨。qq 群号:705637299,请备注暗号:LabVIEW 机器学习