基于RobustVideoMatting(RVM)进行视频人像分割(torch、onnx版本)

发表时间:2021年8月25日
项目地址:https://peterl1n.github.io/RobustVideoMatting/
论文阅读:https://hpg123.blog.csdn.net/article/details/134409222

RVM是字节团队开源的一个实时人像分割模型,基于LSTMConv实现,在效果与性能上取得良好效果。为此,对齐开源代码进行整理利用,实现对视频人像的实时分割。本博客包含,torch版本、onnx版本代码。请注意,RVM算法基于lstmconv实现,故推理时时序越长效果越稳定,屏闪概率越低。同时对比torch与onnx推理,发现torch推理速度比onnx快很多。
在这里插入图片描述

1、环境准备

1.1 模型下载

本项目一共开源了两个模型,有torch版本与onnx版本。这里需要下载torch模型与onnx模型
在这里插入图片描述

1.2 视频读写代码

from torch.utils.data import DataLoader
from torchvision.transforms import ToTensor
from torch.utils.data import Dataset
from torchvision.transforms.functional import to_pil_image
from PIL import Imageimport decord
from torch.utils.data import Dataset
from PIL import Image
import numpy as npclass VideoReader(Dataset):def __init__(self, path, transform=None):# 初始化decord视频读取器,使用GPU加速(如果可用)self.vr = decord.VideoReader(path, ctx= decord.cpu(0)) #decord.gpu(0) # 获取帧率self.rate = self.vr.get_avg_fps()self.transform = transform# 获取视频总帧数self.length = len(self.vr)@propertydef frame_rate(self):return self.ratedef __len__(self):return self.lengthdef __getitem__(self, idx):# 读取指定索引的帧,返回numpy数组 (H, W, C),格式为RGBframe = self.vr[idx].asnumpy()# 转换为PIL图像frame = Image.fromarray(frame)# 应用变换if self.transform is not None:frame = self.transform(frame)return frameimport cv2
import numpy as npclass VideoWriter:def __init__(self, path, frame_rate, bit_rate=1000000):self.path = pathself.frame_rate = frame_rateself.bit_rate = bit_rateself.writer = Noneself.width = 0self.height = 0def write(self, frames):# frames: [T, C, H, W]# 获取视频尺寸self.width = frames.size(3)self.height = frames.size(2)# 如果是灰度图则转换为RGBif frames.size(1) == 1:frames = frames.repeat(1, 3, 1, 1)  # convert grayscale to RGB#([1, 3, 1280, 720])# 转换为OpenCV需要的格式 [T, C, H, W] 且范围为0-255的uint8frames = frames.mul(255).cpu().permute(0, 2, 3, 1).numpy().astype(np.uint8)# OpenCV默认使用BGR格式,需要转换# 初始化视频写入器(首次调用write时)if self.writer is None:# 根据文件名后缀自动选择编码器fourcc = cv2.VideoWriter_fourcc(*'mp4v')  # 对于mp4格式# 如果是其他格式可以修改,例如'XVID'对应avi格式self.writer = cv2.VideoWriter(self.path,fourcc,self.frame_rate,(self.width, self.height))print(frames.shape,frames.dtype,frames.max(),self.width, self.height)for t in range(frames.shape[0]):frame = frames[t]frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)self.writer.write(frame)def close(self):if self.writer is not None:self.writer.release()

1.3 torch模型定义代码

这里需要下载项目源码与模型,注意是引入model目录下的模型定义。
在这里插入图片描述

2、视频人像分割(torch版本)

2.1 模型加载代码

import torch
from model import MattingNetworkmodel = MattingNetwork('mobilenetv3').eval().cuda()  # or "resnet50"
model.load_state_dict(torch.load('rvm_mobilenetv3.pth'))

2.3 调用代码

import torch
bgr = torch.tensor([.47, 1, .6]).view(3, 1, 1).cuda()  # Green background.
rec = [None] * 4                                       # Initial recurrent states.
downsample_ratio = 0.25                                # Adjust based on your video.writer = VideoWriter('output.mp4', frame_rate=30)
batch=60
with torch.no_grad():for src in DataLoader(reader,batch_size=batch):                     # RGB tensor normalized to 0 ~ 1.while src.shape[0]<batch:src=torch.cat([src,src[-1:]])fgr, pha, *rec = model(src.cuda(), *rec, downsample_ratio)  # Cycle the recurrent states.fgr=fgr[:batch]pha=pha[:batch]com = fgr * pha + bgr * (1 - pha)              # Composite to green background. writer.write(com)                              # Write frame.
writer.close()

2.3 处理效果

3060显卡,cuda12,torch 2.4,处理20s的720p,fps30 视频,耗时14s。
在这里插入图片描述

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

3、视频人像分割(onnx版本)

3.1 onnx模型加载代码

先将从github中下载的 模型在 https://netron.app/ 打开,确认是支持动态size的。
在这里插入图片描述

这里的代码为通用onnx模型推理代码

import onnxruntime as ort
import numpy as np
from typing import Dict, List, Union, Tupleclass ONNXModel:"""简化版ONNX Runtime封装,模拟PyTorch模型调用风格仅实现forward方法,输入输出均为numpy数组"""def __init__(self, onnx_path: str, device: str = 'cpu'):self.onnx_path = onnx_path# 根据设备选择执行提供程序providers = ['CPUExecutionProvider']if device.lower() == 'cuda' and 'CUDAExecutionProvider' in ort.get_available_providers():providers = ['CUDAExecutionProvider', 'CPUExecutionProvider']# 初始化ONNX Runtime会话self.session = ort.InferenceSession(onnx_path, providers=providers)# 获取输入和输出节点信息self.input_names = [input.name for input in self.session.get_inputs()]self.output_names = [output.name for output in self.session.get_outputs()]def forward(self, *args, **kwargs) -> Union[np.ndarray, Tuple[np.ndarray]]:"""前向传播方法,模拟PyTorch的forward输入: numpy数组,可以是位置参数(按输入顺序)或关键字参数(按输入名称)输出: numpy数组或numpy数组元组"""# 准备输入字典inputs = {}# 处理位置参数if args:if len(args) != len(self.input_names):raise ValueError(f"位置参数数量不匹配,预期{len(self.input_names)}个,得到{len(args)}个")for name, arg in zip(self.input_names, args):inputs[name] = arg# 处理关键字参数if kwargs:for name, value in kwargs.items():if name not in self.input_names:raise ValueError(f"未知的输入名称: {name},有效名称为: {self.input_names}")inputs[name] = value# 检查输入完整性if len(inputs) != len(self.input_names):missing = set(self.input_names) - set(inputs.keys())raise ValueError(f"缺少输入: {missing}")# for k in inputs.keys():#     print(k,inputs[k].shape,inputs[k].dtype)# 执行推理outputs = self.session.run(self.output_names,inputs)# 处理输出格式if len(outputs) == 1:return outputs[0]return tuple(outputs)def __call__(self, *args, **kwargs) -> Union[np.ndarray, Tuple[np.ndarray]]:"""重载调用方法,使实例可以像PyTorch模型一样被调用"""return self.forward(*args, **kwargs)
model = ONNXModel('rvm_mobilenetv3_fp16.onnx','cuda')

3.2 调用代码

这里推理代码与torch推理代码高度一致,注意数据类型。


import torch
import time
bgr = torch.tensor([.47, 1, .6]).view(3, 1, 1).numpy().astype(np.float16)  # Green background.
rec = None                                    # Initial recurrent states.
downsample_ratio = np.array([0.25]).astype(np.float32)                             # Adjust based on your video.writer = VideoWriter('output.mp4', frame_rate=30)
batch=32
t0=time.time()
with torch.no_grad():for src in DataLoader(reader,batch_size=batch):                     # RGB tensor normalized to 0 ~ 1.while src.shape[0]<batch:src=torch.cat([src,src[-1:]])src=src.numpy().astype(np.float16)if rec is None:rec=[np.zeros((1,1,1,1),dtype=np.float16)]*4fgr, pha, *rec = model(src, *rec, downsample_ratio)  # Cycle the recurrent states.fgr=fgr[:batch]pha=pha[:batch]com = fgr * pha + bgr * (1 - pha)              # Composite to green background. com=torch.tensor(com)writer.write(com)                              # Write frame.
writer.close()
rt=time.time()-t0
print(f"视频处理耗时:{rt:.4f}")

此时代码耗时为46s,相比于torch慢了很多。

(32, 1280, 720, 3) uint8 255 720 1280
视频处理耗时:45.9930

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

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

相关文章

强制从不抱怨环境。

警世俗语&#xff1a;强者逆袭心法&#xff08;句句穿心&#xff09;环境是泥潭&#xff1f;那就让它开出金莲&#xff01; —— 抱怨是弱者的裹脚布&#xff0c;行动是强者的登天梯。烂泥里也能种出摇钱树&#xff0c;关键看你敢不敢下手挖&#xff01;老天爷发牌烂&#xff1…

MC0439符号统计

码蹄集OJ-符号统计 MC0439・符号统计 难度&#xff1a;黄金 时间限制&#xff1a;1 秒 占用内存&#xff1a;256 M 收藏 报错 在华容道放曹的紧张时刻&#xff0c;小码哥接到了一个看似微不足道却至关重要的任务&#xff1a;解读一条仅由小写英文字母组成的神秘字符串 s&#…

Android Jetpack 系列(五)Room 本地数据库实战详解

1. 简介 在需要轻量级本地持久化的场景中&#xff0c;DataStore 是一个理想的选择&#xff08;详见《Android Jetpack 系列&#xff08;四&#xff09;DataStore 全面解析与实践》&#xff09;。但当你面临如下需求时&#xff0c;本地数据库便显得尤为重要&#xff1a; 复杂的…

C语言实现类似C#的格式化输出

在C#中&#xff0c;格式化输出可以使用索引占位符以及复合格式的占位符&#xff0c;可以不用关心后面参数是什么类型&#xff0c;使用起来非常方便&#xff0c;如下简单的示例&#xff1a; Console.WriteLine("{2} {1} {0} {{{2}}}", "Hello, World!", 1,…

一人公司方法论

** 一人公司方法论 ** 那什么是一人公司&#xff1f; 字面的理解就是一个人运营的公司&#xff0c;但实际上它指代的是比较少的人运营的小公司&#xff0c;一般来说 1 ~ 3 个人运营的公司&#xff0c;也可以把它放到一人公司的范围以内。其他一些形式&#xff0c;比如说一个人再…

Ceph CSI 镜像删除流程与 Trash 机制失效问题分析文档

#作者&#xff1a;闫乾苓 文章目录一、问题背景二、实际行为三、源码分析四、分析与推论五、期望行为与建议优化六、结论一、问题背景 在生产环境中&#xff0c;为避免因误操作导致的永久数据丢失&#xff0c;Ceph RBD 提供了 Trash 功能&#xff0c;允许将镜像“软删除”至回…

.NET Framework 3.5 不原生支持PreApplicationStartMethod特性

.NET Framework 3.5 不原生支持PreApplicationStartMethod特性。这个特性是在 .NET Framework 4.0 中引入的&#xff0c;用于在应用程序启动早期执行初始化逻辑。 在.NET 3.5 中&#xff0c;如果你需要实现类似的 “应用启动时自动注册模块” 功能&#xff0c;需要通过手动配置…

智能巡检技术浅析

从机载智能硬件到深度学习算法&#xff0c;从实时边缘计算到数字孪生平台&#xff0c;无人机AI智能巡检通过多模态感知、自主决策和持续进化&#xff0c;实现从"被动检查"到"主动预防"的跨越式发展。机载智能硬件边缘计算与机载AI芯片当代先进巡检无人机已…

【图像算法 - 11】基于深度学习 YOLO 与 ByteTrack 的目标检测与多目标跟踪系统(系统设计 + 算法实现 + 代码详解 + 扩展调优)

前言 详细视频介绍 【图像算法 - 11】基于深度学习 YOLO 与 ByteTrack 的目标检测与多目标跟踪系统&#xff08;系统设计 算法实现 代码详解 扩展调优&#xff09;在计算机视觉应用中&#xff0c;目标检测与多目标跟踪的结合是实现智能视频分析的关键。本文基于 YOLO 检测模…

AI加持下的智能路由监控:Amazon VPC Direct Connect实战指南

> 一次流量突增引发的生产事故,如何催生出融合流日志、机器学习与自动化告警的智能监控体系 深夜2点,电商平台运维负责人李明的手机疯狂报警——北美用户下单量断崖式下跌。他紧急登录系统,发现跨境专线延迟飙升至2000ms。**经过3小时的排查**,罪魁祸首竟是新部署的CDN…

具身智能竞速时刻,百度百舸提供全栈加速方案

2025年&#xff0c;全球具身智能赛道迎来快速发展期&#xff0c;技术方向日益清晰。每一家企业都面临着同样的核心命题&#xff1a;如何将前沿的模型能力&#xff0c;转化为在真实世界各类场景中可规模化应用落地的机器人产品&#xff1f;这背后&#xff0c;是研发团队对模型迭…

JavaScript 压缩与混淆实战:Terser 命令行详解

使用 Terser 压缩 JavaScript 文件&#xff08;基础 现代语法问题解决&#xff09; 在前端开发中&#xff0c;随着业务复杂度增加&#xff0c;JavaScript 文件体积越来越大。 文件大带来的问题&#xff1a; 加载慢&#xff1a;文件越大&#xff0c;浏览器下载和解析时间越长…

【数据结构初阶】--排序(三):冒泡排序、快速排序

&#x1f618;个人主页&#xff1a;Cx330❀ &#x1f440;个人简介&#xff1a;一个正在努力奋斗逆天改命的二本觉悟生 &#x1f4d6;个人专栏&#xff1a;《C语言》《LeetCode刷题集》《数据结构-初阶》 前言&#xff1a;在上篇博客的学习中&#xff0c;我们掌握了直接选择排序…

名词概念:什么是尾部误差?

“尾部误差”就是指误差分布在两端的那一小撮、但数值特别大的误差——也就是离中心&#xff08;均值/中位数&#xff09;很远的“极端样本”的误差。对应统计学里的“分布尾部”&#xff08;tails&#xff09;。通俗点&#xff1a;大多数样本误差都很小&#xff0c;但总会有少…

记对外国某服务器的内网渗透

本专栏是笔者的网络安全学习笔记&#xff0c;一面分享&#xff0c;同时作为笔记 文章目录前文链接前言上线CS上线rdp后渗透信息收集SMB Pth攻击权限维持魔幻上线提权关Windows Defenderend前文链接 WAMP/DVWA/sqli-labs 搭建burpsuite工具抓包及Intruder暴力破解的使用目录扫描…

速卖通平台关键字搜索商品列表列表接口实现指南:从接口分析到代码落地

在跨境电商开发中&#xff0c;速卖通平台的商品数据获取是许多开发者关注的焦点。本文将详细介绍如何实现速卖通关键字搜索商品列表接口&#xff0c;涵盖接口请求参数分析、签名机制、分页处理及完整代码实现&#xff0c;帮助开发者快速对接速卖通开放平台。一、接口基本信息速…

UE UDP通信

1.确保工程为C工程&#xff0c;在项目工程的xx.Build.cs中加入Networking和Sockets模块。PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Networking", "Socke…

JavaScript 逻辑运算符与实战案例:从原理到落地

JavaScript 中的逻辑运算符不仅是条件判断的核心&#xff0c;还能通过“短路特性”简化代码&#xff1b;结合 DOM 操作的实战案例&#xff0c;更能体现其灵活性。本文整理了逻辑运算符的个人理解、优先级规则&#xff0c;以及 4 个高频实战需求的实现方案&#xff0c;附个人思路…

Android RxJava 过滤与条件操作详解

RxJava 是一个基于观察者模式的响应式编程库&#xff0c;在 Android 开发中被广泛使用。其中&#xff0c;过滤和条件操作是 RxJava 中非常重要的一部分&#xff0c;它们允许我们对数据流进行精细控制。本文将详细介绍 RxJava 中常用的过滤与条件操作符及其使用场景。一、过滤操…

云手机都具有哪些特点?

云手机拥有着便捷的远程操作功能&#xff0c;让用户无论身处何地&#xff0c;只要能连接网络&#xff0c;就能通过手机、电脑等终端设备远程操控云手机&#xff0c;无需受限于物理位置&#xff0c;大大提升了工作的灵活性与便捷性。云手机主要是依赖于云计算技术&#xff0c;能…