手把手教你使用LabVIEW实现Mask R-CNN图像实例分割(含源码)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手把手教你使用LabVIEW实现Mask R-CNN图像实例分割(含源码)相关的知识,希望对你有一定的参考价值。
(文章目录)
前言
前面给大家介绍了使用LabVIEW工具包实现图像分类,目标检测,今天我们来看一下如何使用LabVIEW实现Mask R-CNN图像实例分割。
一、什么是图像实例分割?
图像实例分割(Instance Segmentation)是在语义检测(Semantic Segmentation)的基础上进一步细化,分离对象的前景与背景,实现像素级别的对象分离。并且图像的语义分割与图像的实例分割是两个不同的概念,语义分割仅仅会区别分割出不同类别的物体,而实例分割则会进一步的分割出同一个类中的不同实例的物体。
计算机视觉中常见的一些任务(分类,检测,语义分割,实例分割)
二、什么是Mask R-CNN
Mask R-CNN是一个实例分割(Instance segmentation)算法,可以用来做“目标检测”、“目标实例分割”、“目标关键点检测”。 Mask R-CNN算法步骤:
- 首先,输入一幅你想处理的图片,然后进行对应的预处理操作,或者预处理后的图片;
- 将其输入到一个预训练好的神经网络中(ResNeXt等)获得对应的feature map;
- 对这个feature map中的每一点设定预定的ROI,从而获得多个候选ROI;
- 将这些候选的ROI送入RPN网络进行二值分类(前景或背景)和BB回归,过滤掉一部分候选的ROI
- 接着,对这些剩下的ROI进行ROIAlign操作(即先将原图和feature map的pixel对应起来,然后
- feature map和固定的feature对应起来);
- 最后,对这些ROI进行分类(N类别分类)、BB回归和MASK生成(在每一个ROI里面进行FCN操作)
三、LabVIEW调用Mask R-CNN图像实例分割模型
1、Mask R-CNN模型获取及转换
- 安装pytorch和torchvision
- 获取torchvision中的模型(我们获取预训练好的模型):
model = models.detection.maskrcnn_resnet50_fpn(pretrained=True)
- 转onnx
def get_pytorch_onnx_model(original_model):
model=original_model
# define the directory for further converted model save
onnx_model_path = dirname
# define the name of further converted model
onnx_model_name = "maskrcnn_resnet50.onnx"
# create directory for further converted model
os.makedirs(onnx_model_path, exist_ok=True)
# get full path to the converted model
full_model_path = os.path.join(onnx_model_path, onnx_model_name)
model.eval()
x = torch.rand(1, 3, 640, 640)
# model export into ONNX format
torch.onnx.export(
original_model,
x,
full_model_path,
input_names=["input"],
output_names=["boxes", "labels", "scores", "masks"],
dynamic_axes="input": [0, 1, 2, 3],"boxes": [0, 1],"labels": [0],"scores": [0],"masks": [0, 1, 2, 3],
verbose=True,opset_version=11
)
return full_model_path
完整获取及模型转换python代码如下:
import os
import torch
import torch.onnx
from torch.autograd import Variable
from torchvision import models
dirname, filename = os.path.split(os.path.abspath(__file__))
print(dirname)
def get_pytorch_onnx_model(original_model):
model=original_model
# define the directory for further converted model save
onnx_model_path = dirname
# define the name of further converted model
onnx_model_name = "maskrcnn_resnet50.onnx"
# create directory for further converted model
os.makedirs(onnx_model_path, exist_ok=True)
# get full path to the converted model
full_model_path = os.path.join(onnx_model_path, onnx_model_name)
model.eval()
x = torch.rand(1, 3, 640, 640)
# model export into ONNX format
torch.onnx.export(
original_model,
x,
full_model_path,
input_names=["input"],
output_names=["boxes", "labels", "scores", "masks"],
dynamic_axes="input": [0, 1, 2, 3],"boxes": [0, 1],"labels": [0],"scores": [0],"masks": [0, 1, 2, 3],
verbose=True,opset_version=11
)
return full_model_path
model = models.detection.maskrcnn_resnet50_fpn(pretrained=True)
print(get_pytorch_onnx_model(model))
2、LabVIEW调用 Mask R-CNN (mask rcnn.vi)
注意:Mask R-CNN模型是没办法使用OpenCV dnn去加载的,因为有些算子不支持,所以我们主要使用LabVIEW开放神经网络交互工具包(ONNX)来加载推理模型。
-
onnxruntime调用onnx模型并选择加速方式
-
图像预处理
-
执行推理 我们使用的模型是:maskrcnn_resnet50_fpn,其输出有四层,分别为boxes,labels,scores,masks,数据类型如下: 可以看到,labels的类型为INT64,所以我们的源码中需要“Get_Rresult_int64.vi,index为1,因为labels为第二层,即下标为1; 另外三个输出我们都可以使用float32来获取了,masks虽然数据类型是uint8,但在实操过程中发现,它其实做过归一化处理了,也可以使用float32.
-
后处理并实现实例分割 因为后处理内容较多,所以直接封装为了一个子VI, mask_rcnn_post_process.vi,源码如下: 整体的程序框架如下: 实例分割结果如下,我们会发现这个模型跑起来,他花的时间比之前就更长了。因为他不但要获取每一个对象的区域,还要也要把这个区域的轮廓给框出来,我们可以看到五个人及篮球都框出来了,使用不同的颜色分割出来了。
3、LabVIEW调用 Mask R-CNN 实现实时图像分割(mask rcnn_camera.vi)
整体思想和上面检测图片的实力分割差不多,不过使用了摄像头,并加了一个循环,对每一帧对象进行实力分割,3080系列显卡可选择TensorRT加速推理,分割会更加流畅。我们发现这个模型其实很考验检测数量的,所以如果你只是对人进行分割,那可以选择一个干净一些的背景,整体检测速度就会快很多。
四、Mask-RCNN训练自己的数据集(检测行人)
1.准备工作
- 训练需要jupyterlab环境,没有安装的同学需要通过pip install jupyterlab 安装
- 如果无法解决jupyterlab环境 可以使用colab或者kaggle提供的免费gpu环境进行训练
- 训练源码:mask-rcnn.ipynb
2.开始训练
- 根据提示运行这段代码,自动或手动下载依赖文件数据集并建立数据集解析类
- 定义单轮训练的函数:网络结构直接采用torchvison里现有的,不再重新定义
- 出现如下输出表示训练进行中
- 修改这个文件名,改成自己的图片名字,运行看下训练效果
3、训练效果
4、导出ONNX
五、获取源码
大家可关注微信公众号:VIRobotics,回复关键字:Mask R-CNN图像实例分割源码 获取本次分享内容的完整项目源码及模型。
总结
以上就是今天要给大家分享的内容。
如果有问题可以在评论区里讨论,提问前请先点赞支持一下博主哦,如您想要探讨更多关于LabVIEW与人工智能技术,欢迎加入我们进行技术交流:705637299,进群请备注暗号:LabVIEW 机器学习。
手把手教你使用LabVIEW OpenCV dnn实现物体识别(Object Detection)含源码
(文章目录)
前言
今天和大家一起分享如何使用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/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 boxs 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.org/models/object_detection/ssd_mobilenet_v2_coco_2018_03_29.tar.gz
(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/1zwbLQe0VehGhsqNIHyaFRw?pwd=8888 提取码:8888
总结拓展
可以使用Yolov3训练自己的数据集,具体训练方法可参考博客:https://blog.csdn.net/qq_38915710/article/details/97112788 可实现案例:口罩佩戴识别、肺炎分类、CT等,如口罩佩戴检测
更多关于LabVIEW与人工智能技术,可添加技术交流群进一步探讨。qq群号:705637299,请备注暗号:LabVIEW 机器学习
以上是关于手把手教你使用LabVIEW实现Mask R-CNN图像实例分割(含源码)的主要内容,如果未能解决你的问题,请参考以下文章
手把手教你使用LabVIEW OpenCV dnn实现图像分类(含源码)
手把手教你使用LabVIEW OpenCV dnn实现物体识别(Object Detection)含源码
手把手教你使用LabVIEW人工智能视觉工具包快速实现图像读取与采集
手把手教你使用LabVIEW人工智能视觉工具包快速实现传统Opencv算子的调用(含源码)