PP-Matting——支持多场景精细化高精度人像抠图(C++模型推理)

简介

Matting和分割是图像处理中两个重要的任务,它们在抠图和图像分析中起着不同的作用。

分割方法将图像分成不同的区域,并为每个像素分配一个分类标签,因此其输出是一个像素级别的分类标签图,通常是整型数据。这种方法适用于将图像中的不同对象或区域进行明确的区分。

而Matting方法则更侧重于提供像素级别的前景和背景的概率信息,通常表示为概率值P。Matting模型会为图像中的每个像素生成一个代表其属于前景的概率,从而在前景和背景交界处产生渐变效果,使得抠图更加自然。Matting模型训练完成后,会生成一个称为Alpha的值,用于表示每个像素的前景透明度。所有Alpha值的集合称为Alpha Matte,它可以被用来对原始图像进行精细的背景替换,使得合成的效果更加逼真。

PP-Matting

PP-Matting是一种无三分图的Matting架构,旨在实现高精度的自然图像Matting。其主要贡献包括:

  • 提出了双分支架构,包括上下文分支(SCB)和高分辨率细节分支(HRDB),共享一个编码器。这种结构有助于并行高效地提取细节和语义特征,并通过引导流机制实现适当的交互,从而提高了Matting的准确性和自然度。
  • 应用金字塔池模块(PPM)来加强语义上下文信息,并通过引导流策略帮助HRDB进行细节预测。这些方法使得PP-Matting能够在没有任何辅助信息的情况下进行端到端的训练,从而轻松地实现高精度的Matting。
  • 在多个数据集上评估了PP-Matting的性能,结果表明其在消光任务上优于其他方法,并在人体抠图实验中展现出突出的性能。
    在这里插入图片描述
    PP-Matting的模型可根据用户对图像分辨率的需求,提供最匹配的模型,并在Trimap Free方向上实现了SOTA级别的精度。除了考虑模型性能外,PaddleSeg还特别优化了模型的部署环境,包括边缘端和服务端,针对模型体积等指标进行了优化。

针对人像场景,PaddleSeg还进行了特殊优化处理,提供了不同场景下的预训练模型和部署模型。这些模型既可直接部署使用,也可以根据具体任务进行微调,为用户提供了更加灵活的选择。

在技术实现方面,基于深度学习的Matting方法通常分为两大类:一种是基于辅助信息输入,另一种是不依赖任何辅助信息直接进行Alpha预测。
在这里插入图片描述

PP-Matting的设计初衷是为了方便用户快速实现抠图,因此用户在使用时无需依赖辅助信息的输入,即可直接获得预测结果。为了实现更高的效果,PP-Matting采用了Semantic context branch (SCB)和high-resolution detail branch (HRDB)两个分支,分别进行语义和细节预测,并通过引导流机制实现了语义引导下的高分辨率细节预测,从而实现了Trimap-free高精度图像抠图。
在这里插入图片描述

模型推理

源码下载地址:https://download.csdn.net/download/matt45m/89005564?spm=1001.2014.3001.5501 ,源码里面只有一个尺寸的模型,如果想更多尺寸模型,私信博主。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
#include <string>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
//#include <cuda_provider_factory.h>  ///cuda加速,要配合onnxruntime gpu版本使用
#include <onnxruntime_cxx_api.h>class Matting
{
public:Matting();Matting(std::string model_path);void inference(cv::Mat &cv_src,std::vector<cv::Mat> &cv_dsts);
private:void preprocess(cv::Mat &cv_src);int inpWidth;int inpHeight;std::vector<float> input_image_;const float conf_threshold = 0.65;Ort::Env env = Ort::Env(ORT_LOGGING_LEVEL_ERROR, "Matting");Ort::Session* ort_session = nullptr;Ort::SessionOptions sessionOptions = Ort::SessionOptions();std::vector<char*> input_names;std::vector<char*> output_names;std::vector<std::vector<int64_t>> input_node_dims; // >=1 outputsstd::vector<std::vector<int64_t>> output_node_dims; // >=1 outputs
};Matting::Matting()
{}Matting::Matting(std::string model_path)
{std::wstring widestr = std::wstring(model_path.begin(), model_path.end());  //windows//OrtStatus* status = OrtSessionOptionsAppendExecutionProvider_CUDA(sessionOptions, 0);   ///使用cuda加速sessionOptions.SetGraphOptimizationLevel(ORT_ENABLE_BASIC);ort_session = new Ort::Session(env, widestr.c_str(), sessionOptions); //windows写法//ort_session = new Session(env, model_path.c_str(), sessionOptions); //linux写法size_t numInputNodes = ort_session->GetInputCount();size_t numOutputNodes = ort_session->GetOutputCount();Ort::AllocatorWithDefaultOptions allocator;for (int i = 0; i < numInputNodes; i++){input_names.push_back(ort_session->GetInputName(i, allocator));Ort::TypeInfo input_type_info = ort_session->GetInputTypeInfo(i);auto input_tensor_info = input_type_info.GetTensorTypeAndShapeInfo();auto input_dims = input_tensor_info.GetShape();input_node_dims.push_back(input_dims);}for (int i = 0; i < numOutputNodes; i++){output_names.push_back(ort_session->GetOutputName(i, allocator));Ort::TypeInfo output_type_info = ort_session->GetOutputTypeInfo(i);auto output_tensor_info = output_type_info.GetTensorTypeAndShapeInfo();auto output_dims = output_tensor_info.GetShape();output_node_dims.push_back(output_dims);}this->inpHeight = input_node_dims[0][2];this->inpWidth = input_node_dims[0][3];
}void Matting::preprocess(cv::Mat &cv_src)
{cv::Mat cv_dst;cv::resize(cv_src, cv_dst, cv::Size(this->inpWidth, this->inpHeight), cv::INTER_LINEAR);int row = cv_dst.rows;int col = cv_dst.cols;this->input_image_.resize(row * col * cv_dst.channels());for (int c = 0; c < 3; c++){for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){float pix = cv_dst.ptr<uchar>(i)[j * 3 + 2 - c];this->input_image_[c * row * col + i * col + j] = pix / 255.0;}}}
}void Matting::inference(cv::Mat &cv_src,std::vector<cv::Mat> &cv_dsts)
{this->preprocess(cv_src);std::array<int64_t, 4> input_shape_{ 1, 3, this->inpHeight, this->inpWidth };auto allocator_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);Ort::Value input_tensor_ = Ort::Value::CreateTensor<float>(allocator_info, input_image_.data(),input_image_.size(), input_shape_.data(), input_shape_.size());std::vector<Ort::Value> ort_outputs = ort_session->Run(Ort::RunOptions{ nullptr }, input_names.data(), &input_tensor_, 1, output_names.data(), output_names.size());   // 开始推理Ort::Value& mask_pred = ort_outputs.at(0);const int out_h = this->output_node_dims[0][2];const int out_w = this->output_node_dims[0][3];float* mask_ptr = mask_pred.GetTensorMutableData<float>();cv::Mat cv_map;cv::Mat cv_mask_out(out_h, out_w, CV_32FC1, mask_ptr);cv::resize(cv_mask_out, cv_map, cv::Size(cv_src.cols, cv_src.rows));cv::Mat cv_three_channel = cv::Mat::zeros(cv_src.rows, cv_src.cols, CV_32FC3);std::vector<cv::Mat> channels(3);for (int i = 0; i < 3; i++){channels[i] = cv_map;}merge(channels, cv_three_channel);cv::Mat cv_rgbimg = cv_src.clone();cv_rgbimg.setTo(cv::Scalar(0, 255, 0), cv_three_channel > this->conf_threshold);cv::Mat dstimg;cv::addWeighted(cv_src, 0.5, cv_rgbimg, 0.5, 0, dstimg);cv_dsts.push_back(cv_map);cv_dsts.push_back(dstimg);
}cv::Mat replaceBG(const cv::Mat cv_src, cv::Mat& alpha, std::vector<int>& bg_color)
{int width = cv_src.cols;int height = cv_src.rows;cv::Mat cv_matting = cv::Mat::zeros(cv::Size(width, height), CV_8UC3);float* alpha_data = (float*)alpha.data;for (int i = 0; i < height; i++){for (int j = 0; j < width; j++){float alpha_ = alpha_data[i * width + j];cv_matting.at < cv::Vec3b>(i, j)[0] = cv_src.at < cv::Vec3b>(i, j)[0] * alpha_ + (1 - alpha_) * bg_color[0];cv_matting.at < cv::Vec3b>(i, j)[1] = cv_src.at < cv::Vec3b>(i, j)[1] * alpha_ + (1 - alpha_) * bg_color[1];cv_matting.at < cv::Vec3b>(i, j)[2] = cv_src.at < cv::Vec3b>(i, j)[2] * alpha_ + (1 - alpha_) * bg_color[2];}}return cv_matting;
}int main()
{cv::Mat cv_src = cv::imread("images/6.jpg");Matting net("models/ppmatting_736x1280.onnx");std::vector<cv::Mat> cv_dsts;net.inference(cv_src, cv_dsts);std::vector<int> color{ 255, 255, 255 };cv::Mat cv_dst = replaceBG(cv_src, cv_dsts[0], color);cv::namedWindow("src", 0);cv::namedWindow("alpha", 0);cv::namedWindow("BG", 0);cv::imshow("src", cv_src);cv::imshow("alpha", cv_dsts[0]);cv::imshow("BG", cv_dst);cv::waitKey();
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

有ai写文案的工具吗?分享5款好用的工具!

在数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;已渗透到我们生活的方方面面&#xff0c;包括内容创作领域。AI写文案的软件以其高效、便捷的特点&#xff0c;正逐渐受到广大内容创作者、营销人员、甚至普通用户的青睐。本文将为您盘点几款热门的AI写文案软件&…

matlab 最小二乘拟合圆柱

目录 一、算法原理1、算法简介2、参考文献二、代码实现三、结果展示四、测试数据本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、算法原理 1、算法简介 圆柱拟合步骤主要包括两步: 一是确定柱面模型参数初始值; 二是…

记一次由于buff/cache导致服务器内存爆满的问题

目录 前言 复现 登录服务器查看占用内存进程排行 先了解一下什么是buff/cache&#xff1f; 尝试释放buffer/cache /proc/sys/vm/drop_caches dirty_ratio dirty_background_ratio dirty_writeback_centisecs dirty_expire_centisecs drop_caches page-cluster swap…

关于在CentOS中卸载MySQL

想要卸载MySQL当然要知道自己的MySQL是用那种方法来安装的了&#xff0c;一般来说MySQL的安装方法在市面上有三种 编译安装、YUM安装、RPM安装&#xff0c;下面会介绍到后两种安装的卸载方法 首先查看是否安装MySQL&#xff0c;一般可以看到版本信息就证明安装了 mysql -V 卸载…

Linux虚拟主机如何快速卸载一键安装的网站程序

接到一位用户发送的请求帮助&#xff0c;想要卸载通过Softaculous一键安装的网站程序&#xff0c;但是没有找到地方&#xff0c;根据与该用户的沟通得知是一个小白用户&#xff0c;想要自己搭建一个博客类的网站&#xff0c;了解到Hostease 有适合新用户并且带管理面板的产品Li…

nacos 更新报错“发布失败。请检查参数是否正确”

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容起因解决方案结果 &#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介绍 &#x1f31f;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华…

从底层结构开始学习FPGA(0)----FPGA的硬件架构层次(BEL Site Tile FSR SLR Device)

系列目录与传送门 《从底层结构开始学习FPGA》目录与传送门 Xilinx的FPGA&#xff0c;从硬件架构的角度可以划分为6个层次&#xff0c;从底层到顶层依次是&#xff1a; BEL&#xff08;最底层单元&#xff09;SiteTileFSRSLRDevice&#xff08;FPGA芯片&#xff09; 接下来我…

【研究僧总结】回顾第1095个创作日

目录 前言一. 机缘二. 日常三. 展望 前言 感觉刚过1024不久&#xff0c;现在又来个1095创作日 一. 机缘 研究僧一直在找平台做笔记&#xff0c;方便之后的回顾总结&#xff0c;也让各位网友见证你我的成长&#xff0c;相互学习 止不住的写文止不住的成长&#xff0c;大家共同…

Halcon 路标牌识别

文章目录 gray_closing_shape 使用选定的掩码执行灰度值关闭create_planar_uncalib_deformable_model 为未校准的透视匹配创建一个可变形的模型get_deformable_model_params 返回可变形模型的参数find_planar_uncalib_deformable_model 在图像中寻找平面投影不变变形模型的最佳…

面试常问:为什么 Vite 速度比 Webpack 快?

前言 最近作者在学习 webpack 相关的知识&#xff0c;之前一直对这个问题不是特别了解&#xff0c;甚至讲不出个123....&#xff0c;这个问题在面试中也是常见的&#xff0c;作者在学习的过程当中总结了以下几点&#xff0c;在这里分享给大家看一下&#xff0c;当然最重要的是…

asp.net在线租车平台

说明文档 运行前附加数据库.mdf&#xff08;或sql生成数据库&#xff09; 主要技术&#xff1a; 基于asp.net架构和sql server数据库 功能模块&#xff1a; asp.net在线租车平台 用户功能有首页 行业新闻用户注册车辆查询租车介绍访问后台 后台管理员可以进行用户管理 管…

Python 解析CSV文件 使用Matplotlib绘图

数据存储在CSV文件中&#xff0c;使用Matplotlib实现数据可视化。 CSV文件&#xff1a;comma-separated values&#xff0c;是在文件中存储一系列以‘&#xff0c;’分隔的值。 例如&#xff1a;"0.0","2016-01-03","1","3","20…

Linux:网络的初步认知

文章目录 网络的认知如何理解协议网络分层OSI模型TCP/IP五层(或四层)模型网络传输的基本流程协议的参与局域网通信原理 本篇将会引入到网络的话题 网络的认知 第一个问题是&#xff0c;网卡是文件吗&#xff1f;答案是显然的&#xff0c;在Linux下一切皆文件&#xff0c;基于…

【Linux】进程控制 -- 详解

一、进程创建 目前学习到的进程创建的两种方式&#xff1a; 命令行启动命令&#xff08;程序、指令等&#xff09; 。通过程序自身&#xff0c;调用 fork 函数创建出子进程。 1、fork 函数初识 在 Linux 中的系统接口 fork 函数是非常重要的函数&#xff0c;它从已存在进程中…

【Linux】深入了解Linux磁盘配额:限制用户磁盘空间的利器

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Linux ⛳️ 功不唐捐&#xff0c;玉汝于成 前言 在多用户环境下管理磁盘空间是服务器管理中的一项重要任务。Linux提供了强大的磁盘配额功能&#xff0c;可以帮助管理员限制用户或组对文件系统…

一分钟了解自动化测试【建议收藏】

引子 写在最前面&#xff1a;目前自动化测试并不属于新鲜的事物&#xff0c;或者说自动化测试的各种方法论已经层出不穷&#xff0c;但是&#xff0c;能够明白自动化测试并很好落地实施的团队还不是非常多&#xff0c;我们接来下用通俗的方式来介绍自动化测试…… 本文共有2410…

Zookeeper的ZAB协议原理详解

Zookeeper的ZAB协议原理详解 如何保证数据一致性。 Paxos&#xff0c; 吸收了主从。 zk 数据模型Watch机制 zab zookeeper原子广播协议。 ZAB概念 ZooKeeper是通过Zab协议来保证分布式事务的最终一致性。 Zab(ZooKeeper Atomic Broadcast,.ZooKeeper原子广播协议)支持…

企业员工上班摸鱼行为老板怎么管?

在数字化时代&#xff0c;员工摸鱼现象成为企业普遍面临的挑战。摸鱼不仅会降低工作效率&#xff0c;影响企业的正常运营&#xff0c;还可能引发数据泄露等安全问题。因此&#xff0c;企业需要采取有效的措施来防止员工上班摸鱼。 来百度APP畅享高清图片 一、制定明确的规章制…

NBlog Java定时任务-备份MySQL数据

NBlog部署维护流程记录&#xff08;持续更新&#xff09;&#xff1a;https://blog.csdn.net/qq_43349112/article/details/136129806 为了避免服务器被攻击&#xff0c;给博客添加了一个MySQL数据备份功能。 此功能是配合博客写的&#xff0c;有些方法直接用的已有的&#xf…

【LAMMPS学习】三、构建LAMMPS(7)具有额外构建选项的软件包

3. 构建 LAMMPS 3.7.具有额外构建选项的软件包 当使用某些包进行构建时&#xff0c;除了Build_package页面上描述的步骤之外&#xff0c;可能还需要额外的步骤。 ​ 对于CMake构建&#xff0c;可能有额外的可选或必需的变量要设置。对于使用make进行构建&#xff0c;可能需…