YOLOv8-Segment C++

YOLOv8-Segment C++

https://github.com/triple-Mu/YOLOv8-TensorRT

这张图像是运行yolov8-seg程序得到的结果图,首先是检测到了person、bus及skateboard(这个是检测错误,将鞋及其影子检测成了滑板,偶尔存在错误也属正常),然后用方框将他们标出,之后由分割将其轮廓标出。

接下来看看具体怎么实现的,这个程序主要由YOLOv8_seg::infer()与YOLOv8_seg::postprocess()函数实现,之后利用YOLOv8_seg::draw_objects()函数将结果展示在图像中。

segment

接下来分割部分进行解读:

YOLOv8_seg::postprocess()函数得到了objs, 其中包含了检测目标box的尺寸及位置,还包含了目标轮廓数据,在box中是目标的像素块的像素值为255,其余区域均为0。上面结果可以看到目标既被方框标出,又有颜色涂抹,这里其实是利用cv::addWeighted()函数实现的,是将两张图像按照不同权重融合在了一起。

下面这张图像是仅展现出了分割的效果:

所有被检测到的目标均被分割。如果只需要对person分割,由于person的标签序索引0,所以将检测到的目标标签与0作判断即可。

cv::Mat segmask = image.clone();
for (auto& obj : objs) {
    int        idx   = obj.label;
    if (idx == 0)
    {
        cv::Scalar mask_color =
            cv::Scalar(MASK_COLORS[idx % 20][0], MASK_COLORS[idx % 20][1], MASK_COLORS[idx % 20][2]);
        segmask(obj.rect).setTo(mask_color, obj.boxMask);
    }
}

于是就得到了:
在这里插入图片描述

看一下objs具体包含了什么样的数据

for (auto& obj : resultObjs)
{
std::cout << "----------------------------------------------" << std::endl;
std::cout << "Rect: " << obj.rect << std::endl;
std::cout << "Label: " << CLASS_NAMES[obj.label] << std::endl;
std::cout << "boxMask: " << obj.boxMask << std::endl;
}

循环中的一次输出:

----------------------------------------------
Rect: [77 x 324 from (2, 545)]
Label: person
boxMask: [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;

...
...
...;
 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0]

从输出结果可以看出这个目标尺寸为77 x 324,从图像中坐标 (2, 545) 开始,目标类别是person,boxMask中的数据为255的则是目标所在的像素,数据为0的则是目标之外的像素。

boxMask的数据可以在yolov8-seg.hpp中找到其赋值语句:

objs[i].boxMask = mask(objs[i].rect) > 0.5f;

可以看出boxMask为什么只有0与255了。

获取坐标

那么根据输出结果我们可以利用rect与boxMask获取目标(这里的目标是person)的坐标,首先可以利用函数cv::findNonZero()找出boxMask中值为255的坐标,然后再加上rect包含的目标框的起点坐标就可以了

// 创建白色画布((1080,810)是图像尺寸,画布要与原图像尺寸一致)
cv::Mat segImg(1080, 810, CV_8UC3, cv::Scalar(255, 255, 255));
std::vector<cv::Point> segpoints;
cv::Mat segmask = image.clone();
for (auto& obj : objs) {
    int        idx   = obj.label;
    if (idx == 0)
    {
        cv::Scalar mask_color =
            cv::Scalar(MASK_COLORS[idx % 20][0], MASK_COLORS[idx % 20][1], MASK_COLORS[idx % 20][2]);
        segmask(obj.rect).setTo(mask_color, obj.boxMask);
        cv::Mat locations;
        cv::findNonZero(obj.boxMask == 255, locations);
        // 打印位置
        std::cout << "值为 255 的位置:" << std::endl;
        for (int i = 0; i < locations.rows; ++i) {
            std::cout << "(" << locations.at<cv::Point>(i).x << ", " << locations.at<cv::Point>(i).y << ")" << std::endl;
            // 这里是目标方框bbox中的坐标,之后需要加上方框起点
            cv::Point segpoint = locations.at<cv::Point>(i);
            segpoint.x += obj.rect.x;
            segpoint.y += obj.rect.y;
            // 将所有坐标(x,y)存储在segpoints中
            segpoints.push_back(segpoint);
        }
    }
}
for (const auto& segpoint : segpoints) {
    segImg.at<cv::Vec3b>(segpoint) = cv::Vec3b(255, 0, 0);
}
cv::imshow("segImg",segImg);
cv::imwrite("segImg.jpg",segImg);

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue 环境准备

1.安装vscode https://code.visualstudio.com/ 2.安装开发vue所需插件&#xff1a; Vetur —— 语法高亮、智能感知、Emmet等 包含格式化功能&#xff0c; AltShiftF &#xff08;格式化全文&#xff09;&#xff0c;CtrlK CtrlF&#xff08;格式化选中 代码&#xff0c;两…

分库分表原则

分库分表原则 单表数据到达千万级别或者20存储空间 优化已经解决不了问题一 IO瓶颈导致性能问题 拆分策略 垂直分库 以表为依据&#xff0c;根据业务将不同的表拆分到不同库中&#xff0c;有点像微服务 垂直分表 以字段为依据&#xff0c;根据字段属性将不同字段拆分到不同…

App ICP备案获取iOS和Android的公钥和证书指纹

依照《工业和信息化部关于开展移动互联网应用程序备案工作的通知》&#xff0c;向iOS和安卓平台提交App时需要先提交ICP备案信息。 iOS平台&#xff1a; 1、下载appuploader工具&#xff1a;Appuploader home -- A tool improve ios develop efficiency such as submit ipa to…

Tencent Tinker:移动应用热修复的未来之路

Tencent Tinker&#xff1a;移动应用热修复的未来之路 1 引言 移动应用热修复是一项在移动应用开发领域中日益重要的技术&#xff0c;它可以帮助应用程序开发者快速修复线上应用的bug、漏洞和功能问题&#xff0c;而无需重新发布整个应用。这种能力对于提高用户体验、降低用户…

Pymysql将爬取到的信息存储到数据库中

爬取平台为电影天堂 获取到的数据仅为测试学习而用 爬取内容为电影名和电影的下载地址 创建表时需要建立三个字段即可 import urllib.request import re import pymysqldef film_exists(film_name, film_link):"""判断插入的数据是否已经存在""&qu…

Flink 1.18.1 部署与配置[CentOS7]

静态IP设置 # 修改网卡配置文件 vim /etc/sysconfig/network-scripts/ifcfg-ens33# 修改文件内容 TYPEEthernet PROXY_METHODnone BROWSER_ONLYno BOOTPROTOstatic IPADDR192.168.18.128 NETMASK255.255.255.0 GATEWAY192.168.18.2 DEFROUTEyes IPV4_FAILURE_FATALno IPV6INIT…

在openfeign客户端如何获取到服务端抛出的准确异常信息?? openfeign调用(请求/响应)的各个大致过程

在openfeign客户端如何获取到服务端抛出的准确异常信息&#xff1f;&#xff1f; 相关参考背景引入浏览器直接访问Spring的Restful接口&#xff08;最普遍、简单的访问&#xff09;示例结论 openfeign客户端调用的情况调用过程示例场景之一&#xff08;其他场景可类比&#xff…

数据结构与算法面试系列-03

1. 一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在 第10次落地时,共经过多少米?第10次反弹多高? 程序代码 package com.jingxuan.system;public class Sphere {public static void main(String[] args) {double s = 0;double t = 100;for (int i…

vue2 组件注册

简单分享怎么将组件注册为全局组件&#xff0c;主要分为三部分&#xff1a; 一、使用 Vue.install 方法将自义定的组件挂载到 Vue 实例上&#xff0c;如下&#xff1a; 二、注册为全局组件&#xff0c;如下&#xff1a; 三、页面使用&#xff0c;如下&#xff1a;

Vue3+vite引入Tailwind CSS

Tailwind CSS 是一个为快速创建定制化 UI 组件而设计的实用型框架。与其他 CSS 框架或库不同&#xff0c;Tailwind CSS 组件没有预先设置好样式。可以使用 Tailwind 的低级实用类来为 CSS 元素设置样式&#xff0c;如 margin、flex、color 等。 自从 2017 年发布以来&#xff…

vue全家桶之路由管理Vue-Router

一、前端路由的发展历程 1.认识前端路由 路由其实是网络工程中的一个术语&#xff1a; 在架构一个网络时&#xff0c;非常重要的两个设备就是路由器和交换机。当然&#xff0c;目前在我们生活中路由器也是越来越被大家所熟知&#xff0c;因为我们生活中都会用到路由器&#…

用VScode写Latex

主要内容可以直接导到这里 A Fast Guide on Writing LaTeX with LaTeX Workshop in VS Code - Jia Jia Math 其中关于TexLive安装完成之后的路径设置有一些迷惑&#xff0c;win11下测试是不需要手动去添加的&#xff0c;去系统变量里检查一下就可以了&#xff0c;应该点开path…

nginx+nginx-rtmp-module+ffmpeg进行局域网推流rtmp\m3u8

局域网推流的简单方式 这里以ubuntu为例 一、先下载安装包 nginx、nginx-rtmp-module&#xff0c;再一起安装 # 下载nginx # 这里我安装的是 nginx-1.10.3 版本 cd /usr/software wget http://nginx.org/download/nginx-1.25.0.tar.gz tar -zxvf nginx-1.25.0.tar.gz# 下载ng…

2024美赛数学建模B题思路源码

赛题目的 赛题目的&#xff1a; 问题描述&#xff1a; 解题的关键&#xff1a; 问题一. 问题分析 要开发一个模型来预测潜水器随时间的位置&#xff0c;我们需要考虑以下几个关键因素&#xff1a; 海洋环境因素&#xff1a;当前和预测的洋流、海水密度&#xff08;可能会随…

Java基础 集合(三)Queue详解

目录 简介 Queue接口 方法介绍 Deque 接口 LinkedList ArrayDeque AbstractQueue 抽象类 PriorityQueue 基础用法示例 前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&#xff0c;我们往往…

企业申请sectigo ip https证书

Sectigo&#xff08;原名Comodo&#xff0c;在整合https证书业务后改名为Sectigo&#xff09;是一家知名的数字证书提供商&#xff0c;拥有多种类型的数字证书&#xff0c;例如单域名https证书、多域名https证书、通配符https证书、IP https证书和代码签名证书等满足各类用户的…

情人节精选礼物指南:五款必考虑情人节精选佳品

随着一年中最浪漫的节日——情人节的脚步越来越近&#xff0c;许多人可能正在纠结如何挑选一份独特的礼物来表达对另一半的爱意。一份精心挑选的礼物不仅能在这个特殊的日子里为对方带来惊喜&#xff0c;还能加深双方的情感联系。为了帮助那些还在犹豫不决的朋友们&#xff0c;…

RS485通信在钡铼技术的LoRa网关中的应用

在钡铼技术的LoRa网关中&#xff0c;RS485通信协议的应用是一个典型的示例&#xff0c;展现了如何将传统的工业通信技术与现代的物联网(IoT)解决方案相结合&#xff0c;以实现更加高效、可靠的数据传输和设备管理。RS485作为一种广泛使用的串行通信协议&#xff0c;因其稳定性高…

Pandas 数据结构 – Pandas CSV 文件

Pandas CSV 文件 CSV&#xff08;Comma-Separated Values&#xff0c;逗号分隔值&#xff0c;有时也称为字符分隔值&#xff0c;因为分隔字符也可以不是逗号&#xff09;&#xff0c;其文件以纯文本形式存储表格数据&#xff08;数字和文本&#xff09;。 CSV 是一种通用的、…

OpenCV学习记录——形态学处理

文章目录 前言一、腐蚀和膨胀二、高级形态学运算三、具体应用代码 前言 形态学是图像处理中最常用的技术之一&#xff0c;它主要用于从图像中提取有意义的形状信息&#xff0c;例如边界和连通区域&#xff0c;以便后续的识别工作能够捕捉到目标对象最重要的形状特征。此外&…
最新文章