Fast SAM与YOLOV8检测模型一起使用实现实例分割

news2024/11/24 5:23:45

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等参数
部署核心代码

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

  • 加载模型并初始化核心代码
  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 output0_idx = this->engine->getBindingIndex(OUTPUT0);
  const nvinfer1::Dims output0_dims =
      this->context->getBindingDimensions(output0_idx);
  this->out_sizes[output0_idx - NUM_INPUT].first =
      get_size_by_dims(output0_dims);
  this->out_sizes[output0_idx - NUM_INPUT].second =
      DataTypeToSize(this->engine->getBindingDataType(output0_idx));

  const int32_t output1_idx = this->engine->getBindingIndex(OUTPUT1);
  const nvinfer1::Dims output1_dims =
      this->context->getBindingDimensions(output1_idx);

  this->out_sizes[output1_idx - NUM_INPUT].first =
      get_size_by_dims(output1_dims);
  this->out_sizes[output1_idx - NUM_INPUT].second =
      DataTypeToSize(this->engine->getBindingDataType(output1_idx));

  const int32_t Reshape_1252_idx = this->engine->getBindingIndex(Reshape_1252);
  const nvinfer1::Dims Reshape_1252_dims =
      this->context->getBindingDimensions(Reshape_1252_idx);
  this->out_sizes[Reshape_1252_idx - NUM_INPUT].first =
      get_size_by_dims(Reshape_1252_dims);
  this->out_sizes[Reshape_1252_idx - NUM_INPUT].second =
      DataTypeToSize(this->engine->getBindingDataType(Reshape_1252_idx));

  const int32_t Reshape_1271_idx = this->engine->getBindingIndex(Reshape_1271);
  const nvinfer1::Dims Reshape_1271_dims =
      this->context->getBindingDimensions(Reshape_1271_idx);
  this->out_sizes[Reshape_1271_idx - NUM_INPUT].first =
      get_size_by_dims(Reshape_1271_dims);
  this->out_sizes[Reshape_1271_idx - NUM_INPUT].second =
      DataTypeToSize(this->engine->getBindingDataType(Reshape_1271_idx));

  const int32_t Concat_1213_idx = this->engine->getBindingIndex(Concat_1213);
  const nvinfer1::Dims Concat_1213_dims =
      this->context->getBindingDimensions(Concat_1213_idx);
  this->out_sizes[Concat_1213_idx - NUM_INPUT].first =
      get_size_by_dims(Concat_1213_dims);
  this->out_sizes[Concat_1213_idx - NUM_INPUT].second =
      DataTypeToSize(this->engine->getBindingDataType(Concat_1213_idx));

  const int32_t OUTPUT1167_idx = this->engine->getBindingIndex(OUTPUT1167);
  const nvinfer1::Dims OUTPUT1167_dims =
      this->context->getBindingDimensions(OUTPUT1167_idx);
  this->out_sizes[OUTPUT1167_idx - NUM_INPUT].first =
      get_size_by_dims(OUTPUT1167_dims);
  this->out_sizes[OUTPUT1167_idx - NUM_INPUT].second =
      DataTypeToSize(this->engine->getBindingDataType(OUTPUT1167_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 核心代码

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

晓理紫记录学习!

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

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

相关文章

【JavaEE进阶】SpringBoot项目的创建

文章目录 一. SpringBoot简介1. 什么是SpringBoot?2. SpringBoot的优点 二. SpringBoot项目创建1. 使用IDEA创建2. 使用网页创建SpringBoot项目 三. 运行SpringBoot项目 一. SpringBoot简介 1. 什么是SpringBoot? Spring Boot 是一个用于快速构建基于 Spring 框架的应用程序…

使用 PyTorch 逐步检测单个对象

一、说明 在对象检测任务中&#xff0c;我们希望找到图像中对象的位置。我们可以搜索一种类型的对象&#xff08;单对象检测&#xff0c;如本教程所示&#xff09;或多个对象&#xff08;多对象检测&#xff09;。通常&#xff0c;我们使用边界框定义对象的位置。有几种方法可以…

概率论与数理统计:第四章:随机变量的数字特征

文章目录 Ch4. 随机变量的数字特征1. 数学期望E(X)(1)数学期望的概念1.离散型①一维离散型随机变量X的数学期望&#xff1a; E X EX EX②一维离散型随机变量的函数的期望&#xff1a; E [ g ( X ) ] E[g(X)] E[g(X)]③二维离散型随机变量的函数的期望&#xff1a; E [ g ( X , …

基于CentOS 7 部署社区版Haproxy

HAProxy是法国开发者 威利塔罗(Willy Tarreau) 在2000年使用C语言开发的一个开源软件&#xff0c;是一款具 备高并发(一万以上)、高性能的TCP和HTTP负载均衡器&#xff0c;支持基于cookie的持久性&#xff0c;自动故障切换&#xff0c;支 持正则表达式及web状态统计。 目录 1…

23款奔驰AMG GT50升级原厂香氛负离子系统,清香宜人,久闻不腻

奔驰原厂香氛合理性可通过车内空气调节组件营造芳香四溢的怡人氛围。通过更换手套箱内香氛喷雾发生器所用的香水瓶&#xff0c;可轻松选择其他香氛。香氛的浓度和持续时间可调。淡雅的香氛缓缓喷出&#xff0c;并且在关闭后能够立刻散去。车内气味不会永久改变&#xff0c;香氛…

nacos原理

不要纠结于具体代码&#xff0c;随着版本变化源码多变&#xff0c;要学习的是基本原理和思想&#xff1b; Nacos注册中心实现原理分析 Nacos架构图 其中分为这么几个模块&#xff1a; Provider APP&#xff1a;服务提供者。 Consumer APP&#xff1a;服务消费者。 Name Serv…

MiniPaint:在线图像编辑利器【在线PS】

MiniPaint在线图像编辑器使用 HTML5 实现图像的在线创建与编辑&#xff0c;在线PS&#xff0c;支持超过40种效果滤镜&#xff0c;无需本地安装&#xff0c;在很多应用场景中可以替代PhotopShop等传统软件。 访问地址&#xff1a;MiniPaint - 在线PS - 在线图像编辑。 1、打开图…

iOS- git对单个或者多个文件权限设置,使用pre-commit hook 和shell脚本,拦截校验

前提&#xff1a;最近&#xff0c;由于团队代码规范和安全问题&#xff0c;有一些文件只能是指定用户才能修改。 对比&#xff1a;调查了一下资料&#xff0c;发现好多人都在使用pre-commit技术。于是&#xff0c;就朝着这个方向去研究。于是抽空写了脚本&#xff0c;在提交的…

DOS、CMD、PowerShell、Shell 与 Windows (类Unix)Terminal 的区别

在计算机历史的演进中&#xff0c;命令行界面&#xff08;CLI&#xff09;始终是一个核心组件&#xff0c;它为用户提供了与计算机系统直接交互的能力。从早期的文本界面到现代的终端&#xff0c;命令行工具已经经历了长足的发展。 本文将深入探讨DOS、CMD、PowerShell、Shell和…

【Unity实战系列】Unity的下载安装以及汉化教程

君兮_的个人主页 即使走的再远&#xff0c;也勿忘启程时的初心 C/C 游戏开发 Hello,米娜桑们&#xff0c;这里是君兮_&#xff0c;怎么说呢&#xff0c;其实这才是我以后真正想写想做的东西&#xff0c;虽然才刚开始&#xff0c;但好歹&#xff0c;我总算是启程了。今天要分享…

阿里云Linux服务器安装FTP站点全流程

阿里云百科分享使用阿里云服务器安装FTP全教程&#xff0c;vsftpd&#xff08;very secure FTP daemon&#xff09;是Linux下的一款小巧轻快、安全易用的FTP服务器软件。本教程介绍如何在Linux实例上安装并配置vsftpd。 目录 前提条件 步骤一&#xff1a;安装vsftpd 步骤二…

Js小数运算精度缺失的解决方法

项目场景&#xff1a; 提示&#xff1a;项目需求截图&#xff1a; 问题描述 众所周知Js做运算时0.10.2不等于0.3,目前项目需要计算关于金额的选项&#xff0c;涉及到金额保留后两位。保单欠款是根据用户输入的保单应收和保单欠款自动计算的。 原因分析&#xff1a; 产生浮点数…

《Kubernetes知识篇:常见面试题汇总》

正在不断地完善中&#xff0c;预计1个月的时间完成&#xff0c;覆盖整个Kubernetes知识面总结&#xff01; 一、概述 1、简述什么是 Kubernetes&#xff1f; kubernetes&#xff08;常简称k8s&#xff09;&#xff0c;是一个 为容器化应用提供自动化部署、扩展和管理的开源平台…

Scractch3.0_Arduino_ESP32_学习随记_蓝牙键盘(三)

C02蓝牙键盘 目的器材程序联系我们 目的 通过C02实现蓝牙键盘 器材 硬件: 齐护机器人C02 购买地址 软件: scratch3.0 下载地址:官网下载 程序 在P5口连接按钮模块。 蓝牙键盘组合按键动作的实现。 当对应按键按下时模拟键盘动作&#xff0c;先按下ctrl然后按下对应组合键…

Scractch3.0_Arduino_ESP32_学习随记_IO中断(六)

IO中断 目的器材程序联系我们 目的 ESP32 IO中断的使用。 中断&#xff1a; 当IO中断事件发生时&#xff0c;MCU将优先执行中断的程序。 打个比方&#xff1a; 你正在读一本书&#xff0c;突然手机收到一条紧急消息。你不想错过这个重要的消息&#xff0c;所以你立即停下手中的…

【总结】Javaweb和Java项目的比较

&#x1f384;欢迎来到边境矢梦的csdn博文&#x1f384; &#x1f384;本文主要梳理Javaweb中的关键点和需要注意的地方&#x1f384; &#x1f308;我是边境矢梦&#xff0c;一个正在为秋招和算法竞赛做准备的学生&#x1f308; &#x1f386;喜欢的朋友可以关注一下&#x1f…

计算机网络核心-数据交换

1 概述 计算机网络的核心即数据交换。通过数据交换将数据从源主机发送到目的主机。 2 为什么需要数据交换 如果不是数据交换的方式&#xff0c;而是每两台主机直接连接&#xff0c;则会产生N^2链路问题。 即&#xff0c;假设有N台主机&#xff0c;两两间建立连接&#xff0c…

STM32F429IGT6使用CubeMX配置外部中断按键

1、硬件电路 2、设置RCC&#xff0c;选择高速外部时钟HSE,时钟设置为180MHz 3、配置GPIO引脚 4、NVIC配置 PC13相同 5、生成工程配置 6、部分代码 中断回调函数 /* USER CODE BEGIN 0 */void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {if(GPIO_Pin GPIO_PIN_0){HAL_GPIO…

自动测试框架airtest应用二:咪咕爱看能量兑换

一、背景介绍 咪咕爱看是中国移动旗下的一款视频播放软件&#xff0c;可以观看众多电影、电视剧、综艺视频&#xff0c;并且移动环境下观看视频还能获得能量&#xff0c;能量可以兑换流量和消费券。它曾经是一款良心APP&#xff0c;不过经过多年调整&#xff0c;现在大部分电影…

android,Compose,消息列表和动画(点击item的时候,就会删除)

Compose,消息列表和动画&#xff08;点击item的时候&#xff0c;就会删除&#xff09; package com.example.mycompose08import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundat…