Fast SAM与YOLOV8检测模型一起使用实现实例分割以及指定物体分割

Fast SAM与YOLOV8检测模型一起使用
部分源代码在结尾处可获取
晓理紫

1 使用场景

实例分割数据集的获取要比检测数据的获取更加困难,在已有检测模型不想从新标注分割数据进行训练但是又想获取相关物体的mask信息以便从像素级别对物体进行操作,这时就可以把检测模型与FastSAM模型配合进行时候实现分割的效果。

2 检测加分割效果

2.1 检测+分割

请添加图片描述

2.2 分割指定物体(分割交通灯,汽车,公交车)

请添加图片描述

3 部署使用

3.1 检测模型

这里使用的检测模型使用YOLOV8,使用TensorRT对YOLOV8进行部署

  • 部署条件

安装YOLOv8环境,可按照git进行配置

需要配置TensorRt相关环境,需要有显卡,安装驱动,CUDA以及TensorRT

需要把原始权重模型转为trt模型

2.2 trt模型转换

trt模型转换有多种方式,本文采用的是先把pt模型转成onnx模型参考,再把onnx通过trtexec工具进行转换。转换命令如下:

yolo mode=export model=yolov8s.pt  format=onnx dynamic=False
trtexec --onnx=yolov8.onnx --saveEngine=yolov8.engine 

注意: trtexec -h查看帮助,转fp16或者int8等参数
部署核心代码

模型转换完成以后,剩下的就是部署推理。部署推理里面最为重要也是最难搞的是数据解析部分。其中模型加载是很标准的流程,当然我这里不一定是标准的。

  • 加载模型并初始化核心代码
  cudaSetDevice(DEVICE);INPUT_W = input_w;INPUT_H = input_h;in_size = 1 * 3 * INPUT_W * INPUT_H;w = INPUT_W;h = INPUT_H;std::ifstream file(engine_file_path, std::ios::binary);assert(file.good());file.seekg(0, std::ios::end);auto size = file.tellg();std::ostringstream fmt;file.seekg(0, std::ios::beg);char *trtModelStream = new char[size];assert(trtModelStream);file.read(trtModelStream, size);file.close();initLibNvInferPlugins(&this->gLogger, "");this->runtime = nvinfer1::createInferRuntime(this->gLogger);assert(this->runtime != nullptr);this->engine = this->runtime->deserializeCudaEngine(trtModelStream, size);assert(this->engine != nullptr);this->context = this->engine->createExecutionContext();assert(this->context != nullptr);cudaStreamCreate(&this->stream);const nvinfer1::Dims input_dims =this->engine->getBindingDimensions(this->engine->getBindingIndex(INPUT));this->in_size = get_size_by_dims(input_dims);CHECK(cudaMalloc(&this->buffs[0], this->in_size * sizeof(float)));this->context->setBindingDimensions(0, input_dims);const int32_t num_dets_idx = this->engine->getBindingIndex(NUM_DETS);const nvinfer1::Dims num_dets_dims =this->context->getBindingDimensions(num_dets_idx);this->out_sizes[num_dets_idx - NUM_INPUT].first =get_size_by_dims(num_dets_dims);this->out_sizes[num_dets_idx - NUM_INPUT].second =DataTypeToSize(this->engine->getBindingDataType(num_dets_idx));const int32_t bboxes_idx = this->engine->getBindingIndex(BBOXES);const nvinfer1::Dims bboxes_dims =this->context->getBindingDimensions(bboxes_idx);this->out_sizes[bboxes_idx - NUM_INPUT].first = get_size_by_dims(bboxes_dims);this->out_sizes[bboxes_idx - NUM_INPUT].second =DataTypeToSize(this->engine->getBindingDataType(bboxes_idx));const int32_t scores_idx = this->engine->getBindingIndex(SCORES);const nvinfer1::Dims scores_dims =this->context->getBindingDimensions(scores_idx);this->out_sizes[scores_idx - NUM_INPUT].first = get_size_by_dims(scores_dims);this->out_sizes[scores_idx - NUM_INPUT].second =DataTypeToSize(this->engine->getBindingDataType(scores_idx));const int32_t labels_idx = this->engine->getBindingIndex(LABELS);const nvinfer1::Dims labels_dims =this->context->getBindingDimensions(labels_idx);this->out_sizes[labels_idx - NUM_INPUT].first = get_size_by_dims(labels_dims);this->out_sizes[labels_idx - NUM_INPUT].second =DataTypeToSize(this->engine->getBindingDataType(labels_idx));for (int i = 0; i < NUM_OUTPUT; i++) {const int osize = this->out_sizes[i].first * out_sizes[i].second;CHECK(cudaHostAlloc(&this->outputs[i], osize, 0));CHECK(cudaMalloc(&this->buffs[NUM_INPUT + i], osize));}if (warmup) {for (int i = 0; i < 10; i++) {size_t isize = this->in_size * sizeof(float);auto *tmp = new float[isize];CHECK(cudaMemcpyAsync(this->buffs[0], tmp, isize, cudaMemcpyHostToDevice,this->stream));this->xiaoliziinfer();}}

模型加载以后,就可以送入数据进行推理

  • 送入数据并推理
  float height = (float)image.rows;float width = (float)image.cols;float r = std::min(INPUT_H / height, INPUT_W / width);int padw = (int)std::round(width * r);int padh = (int)std::round(height * r);if ((int)width != padw || (int)height != padh) {cv::resize(image, tmp, cv::Size(padw, padh));} else {tmp = image.clone();}float _dw = INPUT_W - padw;float _dh = INPUT_H - padh;_dw /= 2.0f;_dh /= 2.0f;int top = int(std::round(_dh - 0.1f));int bottom = int(std::round(_dh + 0.1f));int left = int(std::round(_dw - 0.1f));int right = int(std::round(_dw + 0.1f));cv::copyMakeBorder(tmp, tmp, top, bottom, left, right, cv::BORDER_CONSTANT,PAD_COLOR);cv::dnn::blobFromImage(tmp, tmp, 1 / 255.f, cv::Size(), cv::Scalar(0, 0, 0),true, false, CV_32F);CHECK(cudaMemcpyAsync(this->buffs[0], tmp.ptr<float>(),this->in_size * sizeof(float), cudaMemcpyHostToDevice,this->stream));this->context->enqueueV2(buffs.data(), this->stream, nullptr);for (int i = 0; i < NUM_OUTPUT; i++) {const int osize = this->out_sizes[i].first * out_sizes[i].second;CHECK(cudaMemcpyAsync(this->outputs[i], this->buffs[NUM_INPUT + i], osize,cudaMemcpyDeviceToHost, this->stream));}cudaStreamSynchronize(this->stream);

推理以后就可以获取数据并进行解析

  • 数据获取并进行解析
  int *num_dets = static_cast<int *>(this->outputs[0]);auto *boxes = static_cast<float *>(this->outputs[1]);auto *scores = static_cast<float *>(this->outputs[2]);int *labels = static_cast<int *>(this->outputs[3]);for (int i = 0; i < num_dets[0]; i++) {float *ptr = boxes + i * 4;Object obj;float x0 = *ptr++ - this->dw;float y0 = *ptr++ - this->dh;float x1 = *ptr++ - this->dw;float y1 = *ptr++ - this->dh;x0 = clamp(x0 * this->ratio, 0.f, this->w);y0 = clamp(y0 * this->ratio, 0.f, this->h);x1 = clamp(x1 * this->ratio, 0.f, this->w);y1 = clamp(y1 * this->ratio, 0.f, this->h);if (!filterClass.empty() &&std::find(filterClass.begin(), filterClass.end(), int(*(labels + i))) ==filterClass.end())continue;if (x0 < 0 || y0 < 0 || x1 > this->w || y1 > this->h || (x1 - x0) <= 0 ||(y1 - y0) <= 0)continue;obj.rect.x = x0;obj.rect.y = y0;obj.rect.width = x1 - x0;obj.rect.height = y1 - y0;obj.prob = *(scores + i);obj.label = *(labels + i);obj.pixelBox.push_back(std::vector<float>{x0, y0});obj.pixelBox.push_back(std::vector<float>{x1, y1});obj.pixelBoxCent = std::vector<float>{(x0 + x1) / 2, (y0 + y1) / 2};obj.className = CLASS_NAMES[int(obj.label)];const std::vector<float> box = {x0, y0, x1, y1};cv::Mat maskmat;
  • 获取对应物体mask(前提已经使用FastSAM进行推理)
  float boxarea = (box[2] - box[0]) * (box[3] - box[1]);std::tuple<float, float, float, float> mapkey;float maxIoU = FLT_MIN;for (auto mapdata : boxMaskMat) {cv::Mat maskmat = mapdata.second;if (maskmat.rows == 0 || maskmat.cols == 0)continue;float orig_masks_area = cv::sum(maskmat)[0];cv::Rect roi(box[0], box[1], box[2] - box[0], box[3] - box[1]);cv::Mat temmask = maskmat(roi);float masks_area = cv::sum(temmask)[0];float union_arrea = boxarea + orig_masks_area - masks_area;float IoUs = masks_area / union_arrea;if (IoUs > maxIoU) {maxIoU = IoUs;mapkey = mapdata.first;}}mask = boxMaskMat[mapkey].clone();
  • 对物体进行过滤

这里对物体进行过滤,主要采取的方式是在检测模块获取物体信息时对物体标签进行过滤。

3.2 FastSAM分割模型

FastSAM分割模型的部署可以参考这篇。

3.3效果视频

效果视频

3 核心代码

扫一扫,关注并回复yolov8+fastsam获取核心代码
在这里插入图片描述

晓理紫记录学习!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/34046.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学习内容散记

git下载网址 &#xff1a;https://registry.npmmirror.com/binary.html?pathgit-for-windows/ error: remote origin already exists 如果你clone下来一个别人的仓库&#xff0c;在此基础上完成你的代码&#xff0c;推送到自己的仓库可能遇到如下问题&#xff1a; error: r…

uniapp开发(由浅到深)

文章目录 1. 项目构建1.1 脚手架构建1.2 HBuilderX创建 uni-app项目步骤&#xff1a; 2 . 包依赖2.1 uView2.2 使用uni原生ui插件2.3 uni-modules2.4 vuex使用 3.跨平台兼容3.1 条件编译 4.API 使用4.1 正逆参数传递 5. 接口封装6. 多端打包3.1 微信小程序3.2 打包App3.2.1 自有…

支付整体架构

5.4 支付的技术架构 架构即未来&#xff0c;只有建立在技术架构设计良好的体系上&#xff0c;支付机构才能有美好的未来。如果支付的技术体系在架构上存在问题&#xff0c;那么就没有办法实现高可用性、高安全性、高效率和水平可扩展性。 总结多年来在海内外支付机构主持和参与…

C语言之位运算

一、什么是位运算 所谓位运算是指进行二进制位的运算 在系统软件中&#xff0c;常要处理二进位的问题 例如&#xff0c;将一个存储单元中的各二进位左移或右移一位&#xff0c;两个数按位相加等 二、位运算符和位运算 1、按位与 运算符(&) 参加运算的两个数据&#xff…

Exploiting Proximity-Aware Tasks for Embodied Social Navigation 论文阅读

论文信息 题目&#xff1a;Exploiting Proximity-Aware Tasks for Embodied Social Navigation 作者&#xff1a;Enrico Cancelli&#xff0c; Tommaso Campari 来源&#xff1a;arXiv 时间&#xff1a;2023 Abstract 学习如何在封闭且空间受限的室内环境中在人类之间导航&a…

uniapp 获取 view 的宽度、高度以及上下左右左边界位置

<view class"cont-box"></view> /* 获取节点信息的对象 */ getElementRect() {const query uni.createSelectorQuery().in(this);query.select(".cont-box").boundingClientRect(res > {console.log(res);console.log(res.height); // 10…

mysql数据库第十二课------mysql语句的拔高2------飞高高

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

研发工程师玩转Kubernetes——通过PV的节点亲和性影响Pod部署

在《研发工程师玩转Kubernetes——PVC通过storageClassName进行延迟绑定》一文中&#xff0c;我们利用Node亲和性&#xff0c;让Pod部署在节点ubuntud上。因为Pod使用的PVC可以部署在节点ubuntuc或者ubuntud上&#xff0c;而系统为了让Pod可以部署成功&#xff0c;则让PVC与Pod…

Spring-Cloud-Loadblancer详细分析_2

LoadBalancerClients 终于分析到了此注解的作用&#xff0c;它是实现不同服务之间的配置隔离的关键 Configuration(proxyBeanMethods false) Retention(RetentionPolicy.RUNTIME) Target({ ElementType.TYPE }) Documented Import(LoadBalancerClientConfigurationRegistrar…

Mongodb:业务应用(1)

环境搭建参考&#xff1a;mongodb&#xff1a;环境搭建_Success___的博客-CSDN博客 需求&#xff1a; 在文章搜索服务中实现保存搜索记录到mongdb 并在搜索时查询出mongdb保存的数据 1、安装mongodb依赖 <dependency><groupId>org.springframework.data</groupI…

Intellij IDEA 导入 eclipse web 项目详细操作

Eclipse当中的web项目都会有这两个文件。但是idea当中应该是没有的&#xff0c;所以导入会出现兼容问题。但是本篇文章会教大家如何导入&#xff0c;并且导入过后还能使用tomcat运行。文章尽可能以图片的形式进行演示。我的idea使用的版本是2022.3.3版本。当然按正常来说版本之…

C++ ModBUS TCP客户端工具 qModMaster 介绍及使用

qModMaster工具介绍 QModMaster是一个基于Qt的Modbus主站&#xff08;Master&#xff09;模拟器&#xff0c;用于模拟和测试Modbus TCP和RTU通信。它提供了一个直观的图形界面&#xff0c;使用户能够轻松设置和发送Modbus请求&#xff0c;并查看和分析响应数据。 以下是QModM…

图论——最短路算法

引入&#xff1a; 如上图&#xff0c;已知图G。 问节点1到节点3的最短距离。 可心算而出为d[1,2]d[2,3]112,比d[1,3]要小。 求最短路径算法&#xff1a; 1.Floyd(弗洛伊德) 是一种基于三角形不等式的多源最短路径算法。边权可以为负数 表现为a[i,j]a[j,k]<a[i,k]。 …

什么是响应式设计?列举几种实现响应式设计的方法。

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是响应式设计&#xff1f;⭐ 实现响应式设计的方法⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏…

Docker安装ElasticSearch/ES 7.4.0

目录 前言安装ElasticSearch/ES安装步骤1&#xff1a;准备1. 安装docker2. 搜索可以使用的镜像。3. 也可从docker hub上搜索镜像。4. 选择合适的redis镜像。 安装步骤2&#xff1a;拉取ElasticSearch镜像1 拉取镜像2 查看已拉取的镜像 安装步骤3&#xff1a;创建容器创建容器方…

android 如何分析应用的内存(十八)终章——使用Perfetto查看内存与调用栈之间的泄露

android 如何分析应用的内存&#xff08;十八&#xff09; 在前面两篇文章中&#xff0c;先是介绍了如何用AS查看Android的堆内存&#xff0c;然后介绍了使用MAT查看 Android的堆内存。AS能够满足基本的内存分析需求&#xff0c;但是无法进行多个堆的综合比较&#xff0c;因此…

ArcGIS Pro基础:【按顺序编号】工具实现属性字段的编号自动赋值

本次介绍一个字段的自动排序编号赋值工具&#xff0c;基于arcgis 的字段计算器工具也可以实现类似功能&#xff0c;但是需要自己写一段代码实现&#xff0c; 相对而言不是很方便。 如下所示&#xff0c;该工具就是【编辑】下的【属性】下的【按顺序编号】工具。 其操作方法是…

FreeRTOS(二值信号量)

资料来源于硬件家园&#xff1a;资料汇总 - FreeRTOS实时操作系统课程(多任务管理) 目录 一、信号量的概念 1、信号量的基本概念 2、信号量的分类 二、二值信号量的定义与应用 1、二值信号量的定义 2、二值信号量的应用 三、二值信号量的运作机制 1、FreeRTOS任务间二值…

Spring Web

◆ Spring整合web环境 - Javaweb三大组件及环境特点 - Spring整合web环境的思路及实现 把ApplicationContext放在ServleContent域【listen组件中】中 ContextLoaderListener &#xff1a;部分代码写死了 /*** 配置通用的Spring容器的创建&#xff0c;只需要创建一次就可以*/…

SQL server 与 MySQL count函数、以及sum、avg 是否包含 为null的值

sql server 与 mysql count 作用一样。 count 计算指定字段出现的个数&#xff0c; 不是计算 null的值 获取表的条数 count(n) n:常数 count(1),count&#xff08;0&#xff09;等 count(*) count(字段) 其中字段为null 不会统计在内。 avg(字段)、sum(字段) 跟count(字段)…