点击上方“3D视觉工坊”,选择“星标”

干货第一时间送达

引言

本文基于YOLOX的ONNX模型分别测试了YOLOX-Small与YOLOX-Tiny版本的模型。硬件配置与软件版本:

Win10 64位CPU CORE i7 8thVS2017OpenVINO2021.4

模型说明

两个模型的输入与输出格式分别如下:

以YOLOX small版本为例,解释输出的内容是什么,看模型的输出图示如下:

有三个输出层,分别是8倍、16倍、32倍的降采样,输出的8400计算方法为:

80x80+40x40+20x20 = 6400+1600+400=8400

分别对应640的8倍、16倍、32倍的降采样大小。85的前四个是cx、cy、w、h大小,第五个是object预测得分,后面80个是COCO类别。

看到这里就知道它跟YOLOv5的解析极其类似。然后它对图象的预测要求如下:

输入通道顺序:RGB、类型浮点数0~1之间输入的均值:0.485f, 0.456f, 0.406f输入的归一化方差:0.229f, 0.224f, 0.225f

代码实现部分

首先需要加载模型,从github上下载好对应的模型ONNX格式文件之后,首先通过IECore来加载YOLOX模型,代码如下:

std::cout << "YOLOX Demo" << std::endl;
Core ie;
std::vector<std::string> availableDevices = ie.GetAvailableDevices();
for (int i = 0; i < availableDevices.size(); i++) {printf("supported device name : %s \n", availableDevices[i].c_str());
}//  加载检测模型
auto network = ie.ReadNetwork("D:/yolox.onnx");

设置模型的输入与输出,这里需要注意,输入设置为FP32,读取输入与输出层名称,代码如下:

// 请求网络输入与输出信息
InferenceEngine::InputsDataMap input_info(network.getInputsInfo());
InferenceEngine::OutputsDataMap output_info(network.getOutputsInfo());
// 设置输入格式
std::string input_name = "";
for (auto &item : input_info) {auto input_data = item.second;input_name = item.first;input_data->setPrecision(Precision::FP32);input_data->setLayout(Layout::NCHW);
}
printf("get it \n");// 设置输出格式
std::string output_name = "";
for (auto &item : output_info) {auto output_data = item.second;output_name = item.first;std::cout <<"output name: "<< item.first << std::endl;output_data->setPrecision(Precision::FP32);
}

下面就是生成三个输出层的grid,每个grid上的每个点的坐标信息,后面解析输出数据的时候需要根据index来取每个grid对应的数据

// 生成三个输出层的grid与anchor信息
std::vector<int> strides = { 8, 16, 32 };
std::vector<GridAndStride> grid_strides;
generate_grids_and_stride(IMG_W, strides, grid_strides);

其中generate_grids_and_stride是我借鉴了官方的代码,这部分我感觉是可以省去的,可以从index中直接计算的,也许这样会更快点,暂时我就借用了,该方法的代码如下:

const float IMG_W = 640.0f;
struct GridAndStride
{int gh;int gw;int stride;
};void generate_grids_and_stride(int target_size, std::vector<int>& strides, std::vector<GridAndStride>& grid_strides)
{for (auto stride : strides){int num_grid = target_size / stride;for (int g1 = 0; g1 < num_grid; g1++){for (int g0 = 0; g0 < num_grid; g0++){GridAndStride gs;gs.gh = g0;gs.gw = g1;gs.stride = stride;grid_strides.push_back(gs);}}}
}

下面就很容易啦,创建推理请求,开始执行推理,推理的解析部分,代码如下:

// 开始推理处理 - 支持图象与视频
cv::Mat image = cv::imread("D:/zidane.jpg");
inferAndOutput(image, grid_strides, input_name, output_name, infer_request);

其中inferAndOutput是我的推理与解析输出结果的方法,该方法首先得到输出,然后根据index来从grid_strides里面查询对应grid的对应位置信息,原来官方的方法比较比较啰嗦,代码不够简洁,我稍微改动了一下,借助OpenVINO中OpenCV自带的NMS函数功能,重新整理一下,改成现在的方法,发现可以降低代码量,提升可读性,该方法的代码如下:

void inferAndOutput(cv::Mat &image, std::vector<GridAndStride> &grid_strides, std::string &input_name, std::string &output_name, InferRequest &infer_request) {int64 start = cv::getTickCount();Blob::Ptr imgBlob = infer_request.GetBlob(input_name);float sx = static_cast<float>(image.cols) / IMG_W;float sy = static_cast<float>(image.rows) / IMG_W;// 推理blobFromImage(image, imgBlob);infer_request.Infer();const Blob::Ptr output_blob = infer_request.GetBlob(output_name);const float* outblob = static_cast<PrecisionTrait<Precision::FP32>::value_type*>(output_blob->buffer());const SizeVector outputDims = output_blob->getTensorDesc().getDims();const int num_anchors = grid_strides.size();const int num_class = 80;// 处理解析输出结果std::vector<cv::Rect> boxes;std::vector<int> classIds;std::vector<float> confidences;for (int anchor_idx = 0; anchor_idx < num_anchors; anchor_idx++){const int grid0 = grid_strides[anchor_idx].gh; // Hconst int grid1 = grid_strides[anchor_idx].gw; // Wconst int stride = grid_strides[anchor_idx].stride; // strideconst int basic_pos = anchor_idx * 85;float x_center = (outblob[basic_pos + 0] + grid0) * stride * sx;float y_center = (outblob[basic_pos + 1] + grid1) * stride * sy;float w = exp(outblob[basic_pos + 2]) * stride * sx;float h = exp(outblob[basic_pos + 3]) * stride * sy;float x0 = x_center - w * 0.5f;float y0 = y_center - h * 0.5f;float box_objectness = outblob[basic_pos + 4];for (int class_idx = 0; class_idx < num_class; class_idx++){float box_cls_score = outblob[basic_pos + 5 + class_idx];float box_prob = box_objectness * box_cls_score;if (box_prob > 0.25){cv::Rect rect;rect.x = x0;rect.y = y0;rect.width = w;rect.height = h;classIds.push_back(class_idx);confidences.push_back((float)box_prob);boxes.push_back(rect);}} // class loop}std::vector<int> indices;cv::dnn::NMSBoxes(boxes, confidences, 0.25, 0.5, indices);for (size_t i = 0; i < indices.size(); ++i){int idx = indices[i];cv::Rect box = boxes[idx];rectangle(image, box, cv::Scalar(140, 199, 0), 4, 8, 0);}float fps = cv::getTickFrequency() / (cv::getTickCount() - start);float time = (cv::getTickCount() - start) / cv::getTickFrequency();std::ostringstream ss;ss << "FPS : " << fps << " detection time: " << time * 1000 << " ms";cv::putText(image, ss.str(), cv::Point(20, 50), 0, 1.0, cv::Scalar(0, 0, 255), 2);cv::imshow("OpenVINO2021.4+YOLOX Demo@JiaZhiGang", image);
}

运行与测试

首先用YOLOv5的一张测试图象测试一下,基于YOLOX的samll版本模型运行结果如下:

跟YOLOV5 small版本测试结果完成一致,毫无违和感!

视频测试(YOLOX Small版本模型)运行结果如下:

感觉没有YOLOv5的small版本推理速度快(在我的机器上)!还需进一步优化输出解析代码。

视频测试(YOLOX Tiny版本模型)运行结果如下:

CPU果然可以30+ FPS的。

本文仅做学术分享,如有侵权,请联系删文。

下载1

在「3D视觉工坊」公众号后台回复:3D视觉即可下载 3D视觉相关资料干货,涉及相机标定、三维重建、立体视觉、SLAM、深度学习、点云后处理、多视图几何等方向。

下载2

在「3D视觉工坊」公众号后台回复:3D视觉github资源汇总即可下载包括结构光、标定源码、缺陷检测源码、深度估计与深度补全源码、点云处理相关源码、立体匹配源码、单目、双目3D检测、基于点云的3D检测、6D姿态估计源码汇总等。

下载3

在「3D视觉工坊」公众号后台回复:相机标定即可下载独家相机标定学习课件与视频网址;后台回复:立体匹配即可下载独家立体匹配学习课件与视频网址。

重磅!3DCVer-学术论文写作投稿 交流群已成立

扫码添加小助手微信,可申请加入3D视觉工坊-学术论文写作与投稿 微信交流群,旨在交流顶会、顶刊、SCI、EI等写作与投稿事宜。

同时也可申请加入我们的细分方向交流群,目前主要有3D视觉CV&深度学习SLAM三维重建点云后处理自动驾驶、多传感器融合、CV入门、三维测量、VR/AR、3D人脸识别、医疗影像、缺陷检测、行人重识别、目标跟踪、视觉产品落地、视觉竞赛、车牌识别、硬件选型、学术交流、求职交流、ORB-SLAM系列源码交流、深度估计等微信群。

一定要备注:研究方向+学校/公司+昵称,例如:”3D视觉 + 上海交大 + 静静“。请按照格式备注,可快速被通过且邀请进群。原创投稿也请联系。

▲长按加微信群或投稿

▲长按关注公众号

3D视觉从入门到精通知识星球:针对3D视觉领域的视频课程(三维重建系列、三维点云系列、结构光系列、手眼标定、相机标定、orb-slam3等视频课程)、知识点汇总、入门进阶学习路线、最新paper分享、疑问解答五个方面进行深耕,更有各类大厂的算法工程人员进行技术指导。与此同时,星球将联合知名企业发布3D视觉相关算法开发岗位以及项目对接信息,打造成集技术与就业为一体的铁杆粉丝聚集区,近2000星球成员为创造更好的AI世界共同进步,知识星球入口:

学习3D视觉核心技术,扫描查看介绍,3天内无条件退款

圈里有高质量教程资料、可答疑解惑、助你高效解决问题

觉得有用,麻烦给个赞和在看~  

OpenVINO2021.4+YOLOX目标检测模型部署测试相关推荐

  1. 树莓派4B部署YOLOv5目标检测模型部署(包含加速方法以及模型训练方法总结)

    树莓派4B部署YOLOv5目标检测模型部署 1.工作内容简介: (1)训练鱼类目标识别模型.首先建立水下鱼类目标数据集,由于目前国内暂时并没有可用红鳍东方鲀标注数据集,本文利用Labelimage软件 ...

  2. 使用TF lite 优化 MobileDet 目标检测模型部署

    文 / Sayak Paul,Google Developer Expert 今年,来自威斯康星大学麦迪逊分校和 Google 的研究人员发表了他们在 MobileDet 上所做的研究工作.他们在 M ...

  3. YOLOX目标检测模型Keras实现,超越Yolov5

    向AI转型的程序员都关注了这个号

  4. python模型预测_python:目标检测模型预测准确度计算方式(基于IoU)

    训练完目标检测模型之后,需要评价其性能,在不同的阈值下的准确度是多少,有没有漏检,在这里基于IoU(Intersection over Union)来计算. 希望能提供一些思路,如果觉得有用欢迎赞我表 ...

  5. 目标检测模型从训练到部署!

    Datawhale干货 作者:张强,Datawhale成员 训练目标检测模型并部署到你的嵌入式设备,让边缘设备长"眼睛". 目标检测的任务是找出图像中所有感兴趣的目标(物体),确定 ...

  6. 目标检测模型从训练到部署,其实如此简单

    目标检测的任务是找出图像中所有感兴趣的目标(物体),确定它们的类别和位置,是计算机视觉领域的核心问题之一.目标检测已应用到诸多领域,比如如安防.无人销售.自动驾驶和军事等. 在许多情况下,运行目标检测 ...

  7. 百度:YOLOX和NanoDet都没我优秀!轻量型实时目标检测模型PP-PicoDet开源

    作者丨happy    编辑丨极市平台 导读 百度提出新型移动端实时检测模型PP-PicoDet.本文对anchor-free策略在轻量型检测器中的应用进行了探索:对骨干结构进行了增强并设计了一种轻量 ...

  8. 【深度学习】百度:YOLOX和NanoDet都没我优秀!轻量型实时目标检测模型PP-PicoDet开源...

    作者丨happy 编辑丨极市平台 导读 百度提出新型移动端实时检测模型PP-PicoDet.本文对anchor-free策略在轻量型检测器中的应用进行了探索:对骨干结构进行了增强并设计了一种轻量Nec ...

  9. 1.8M超轻量目标检测模型NanoDet,比YOLO跑得快

    机器之心报道,项目作者:RangiLyu 目标检测一直是计算机视觉领域的一大难题,其目标是找出图像中的所有感兴趣区域,并确定这些区域的位置和类别.目标检测中的深度学习方法已经发展了很多年,并出现了不同 ...

最新文章

  1. 开发工具Drawscript
  2. APUE学习笔记——第十章信号中10.15节例程的运行结果与书本里的不一样
  3. python3 文本文件内容去除重复行
  4. DOS循环:bat/批处理for命令详解之一 (史上虽详尽的总结和说明~~)
  5. 浅谈百度新一代query-ad 推荐引擎如何提升广告收益率
  6. 算法优化:动态规划加速,货物运输问题,四边形不等式, 从O(n^2)到O(n^3)
  7. Neo4j: 迁移MySQL的数据到Neo4j
  8. ⑨④-如果不发展就可能面临生存窘境
  9. 【音效处理】Delay/Echo 简介
  10. 王者权志龙回归!支持爱豆壁纸少不了
  11. python人工智能能干啥_人工智能首选什么语言 Python能做哪些事情
  12. 052011GR2 _optimizer_null_aware_antijoin
  13. java 文件工具类_java文件工具类,文件的一些基本操作
  14. APP安全测试点概述
  15. 杭州学车 富阳场口考场考试 经验分享
  16. 使用皮卡(pika)操作RabbitMQ
  17. [labview]做一个简单实用可扩展功能的高速串口发送(接收)调试器
  18. 【UVM基础】uvm_agent 中的 is_active 变量释义
  19. so-vits-svc4.0 中文详细安装、训练、推理使用教程
  20. VSCode安装及配置

热门文章

  1. RHEL7升级openssh7.4p1教程
  2. 【C语言入门教程】7.1 结构体类型变量的定义和引用
  3. 将简历挂到云服务器网站上记
  4. Map集合中value()方法与keySet()、entrySet()区别 ——转载
  5. Android AndFix热补丁动态修复框架使用教程
  6. Android的ViewPager的初步使用
  7. 九、OLTP 性能调整与优化--结语
  8. 服务器测速,php在线测速
  9. 2021年2月反思与总结
  10. 这54个docker命令!你必须懂!