news 2026/10/10 22:02:48

onnxruntime部署LivePortrait人像动画:C++与Python双栈实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
onnxruntime部署LivePortrait人像动画:C++与Python双栈实战

简介:本资源面向希望在人像动画生成方向落地的开发者,提供使用onnxruntime部署LivePortrait的完整程序,同时给出C++与Python两套实现路径,适合具备一定深度学习推理基础、想在本地或工程环境中集成人像驱动能力的读者参考。压缩包共14个文件,约459KB,包含4个cpp与3个h源文件构成C++推理主流程,2个py脚本负责Python侧调用与裁剪处理,另有txt、md说明文档及mp4、jpg、png等示例素材,便于对照理解输入输出。目前已有204人学习下载。资源涵盖人脸检测、裁剪对齐、动画生成等模块的代码组织,读者可据此掌握onnxruntime加载模型、前后处理与跨语言调用的排错思路,并借助示例素材快速验证效果,适合作为人像动画工程化部署的起步模板。

1. 拿到 liveportrait-onnxrun-main 之后:这套 C++/Python 双栈人像动画程序到底能跑出什么

上周有个做短视频工具的朋友甩给我一个压缩包,名字很长——使用onnxruntime部署LivePortrait人像动画生成(C++和Python)程序.zip。他问得很直接:这东西能不能脱离 PyTorch 那套重依赖,在普通 Windows 机器上把一张静态人像照片驱动成一段说话视频?我解压跑了一遍,答案是能,而且它把推理后端换成了 onnxruntime,Python 和 C++ 两条路都给了。

LivePortrait 本身是快手开源的肖像动画框架,核心思路是从源图像里提取外观特征和关键点运动信息,再结合驱动视频的表情、姿态、视线变化,逐帧渲染出目标人像的动画。原版依赖 PyTorch 和一堆 CUDA 算子,部署门槛不低。这个包做的事,是把模型转成 ONNX 格式后用 onnxruntime 加载推理,同时提供了 Python 脚本和一套完整的 C++ 工程(含 CMakeLists.txt、liveportrait.h/cpp、faceanalysis.h/cpp、utils_crop.h/cpp、main.cpp),等于把「快速验证」和「集成进现有 C++ 项目」两条路都铺好了。

适合谁用?如果你手头有 C++ 的桌面端或服务端工程,想把人像动画能力嵌进去,又不想拖一个 PyTorch 运行时,这套东西值得拆开看。如果你只是想先跑通效果,Python 那条线几分钟就能出第一段视频。下面按我实际操作的顺序,把两条路都走一遍。

2. 环境准备与模型文件落位:onnxruntime 动态库、Python 依赖和目录结构

2.1 先看清包里的目录骨架

解压后根目录是liveportrait-onnxrun-main,里面大致分三块:Python 侧有main.py、utils_crop.py,以及0.jpg、mask_template.png、d0.mp4这几个示例素材;C++ 侧在cpp目录下,包含CMakeLists.txt、liveportrait.h、liveportrait.cpp、faceanalysis.h、faceanalysis.cpp、utils_crop.h、utils_crop.cpp、main.cpp;根目录还有一份README.md。

模型文件(.onnx)通常需要单独下载后放到指定目录,包里不会塞几百兆的权重。常见做法是在根目录建一个models或onnx文件夹,把外观提取、运动提取、生成器、关键点检测这几类 ONNX 文件按 README 里的命名放进去。这一步别偷懒,路径和文件名对不上,后面报错会很难定位。

2.2 Python 侧依赖安装

Python 这条线依赖比较轻,核心就是 onnxruntime、opencv、numpy、pillow 这几个。我一般用虚拟环境隔离,避免和系统里的 PyTorch 打架:

# 建虚拟环境,Python 3.8 及以上都行 python -m venv venv_lp # Windows 激活 venv_lp\Scripts\activate # Linux/macOS 激活 source venv_lp/bin/activate # 装核心依赖,CPU 版 onnxruntime pip install onnxruntime opencv-python numpy pillow # 如果有 NVIDIA 显卡且想用 GPU 推理,换成 GPU 版 # pip install onnxruntime-gpu

这里有个参数选择:onnxruntime和onnxruntime-gpu只能装一个,装混了会出现 provider 找不到的情况。CPU 版默认用CPUExecutionProvider,GPU 版需要 CUDA 和 cuDNN 版本匹配,具体版本对照去 onnxruntime 官方文档查,别凭感觉装。

2.3 C++ 侧依赖与 onnxruntime 动态库

C++ 这条线要准备三样东西:onnxruntime 的 C++ 库(头文件 + 动态库)、OpenCV、CMake。onnxruntime 官方提供预编译包,下载对应平台的压缩包后,把include和lib目录路径记下来,等会儿在 CMakeLists.txt 里指过去。

Windows 上还需要注意运行库:Microsoft Visual C++ 2015-2022 Redistributable (x64)建议先装上,否则 onnxruntime 的动态库加载可能直接失败,报找不到vcruntime140_1.dll之类的错。这个坑我踩过不止一次,装完重启一下最稳。

提示:onnxruntime 动态库的版本要和头文件版本一致,混用不同版本的 dll 和 lib 会出现符号找不到的链接错误。

3. Python 跑通第一段动画:main.py 的参数、裁剪脚本与推理链路

3.1 先跑 utils_crop.py 做素材预处理

LivePortrait 对输入图像有裁剪和对齐要求,直接丢一张原图进去,人脸区域比例不对,出来的动画会歪或者抖动。包里给了utils_crop.py,作用是把源图像裁剪到合适的人脸区域并生成对齐后的图。

# 对示例图 0.jpg 做裁剪,输出对齐后的人脸图 python utils_crop.py 0.jpg

这个脚本内部一般会调用人脸检测,拿到关键点后做仿射变换,把脸摆正并缩放到模型期望的输入尺寸。执行完会生成一张裁剪后的图,记下输出文件名,下一步要作为参数传进去。如果脚本报检测不到人脸,先检查图片是不是太暗、人脸太小或者侧脸角度过大——检测模型对这三类情况比较敏感。

3.2 main.py 的核心参数逐个说清

跑主推理脚本时,参数顺序和含义必须搞对,否则要么读错文件要么输出空视频。典型调用长这样:

# 源图像 + 驱动视频 + 输出路径 python main.py --source 0_crop.jpg --driving d0.mp4 --output result.mp4

如果包里的 main.py 用的是位置参数而非命名参数,就按 README 里的顺序传。几个关键点:

  • source:裁剪对齐后的源人像图,不是原图。传原图可能也能跑,但效果打折。
  • driving:驱动视频,示例给了d0.mp4。驱动视频里的人脸要清晰,帧率稳定,否则运动信号提取会抖。
  • output:输出视频路径,编码格式一般跟随 OpenCV 的 VideoWriter 设置,常见是 mp4v 或 avc1。

推理链路大致是:源图过外观提取网络拿到特征和关键点 → 驱动视频逐帧过运动提取网络拿到表情和姿态 → 生成器把两者融合渲染 → 写回视频帧。整个过程在 onnxruntime 里就是一次次session.run(),没有 PyTorch 的动态图开销。

3.3 输出视频的编码与帧率对齐

跑完第一遍,最容易翻车的不是模型,是视频编码。OpenCV 写视频时如果编码器选得不对,输出文件要么打不开,要么只有几帧。我一般会显式指定:

# 在 main.py 里找到 VideoWriter 那段,确认编码和帧率 fourcc = cv2.VideoWriter_fourcc(*'mp4v') out = cv2.VideoWriter(output_path, fourcc, fps, (w, h))

fps要和驱动视频一致,宽高要和生成帧一致。如果输出视频播放速度不对,八成是 fps 传错了。另外mask_template.png是配合遮罩用的,某些后处理步骤会拿它做区域融合,别删。

4. C++ 工程编译与集成:CMakeLists 配置、faceanalysis 与 liveportrait 模块拆解

4.1 CMakeLists.txt 里必须改的三处路径

C++ 工程能不能编过,九成看 CMakeLists.txt 里的路径对不对。打开后重点找这三类:

# 1. onnxruntime 头文件和库路径 set(ONNXRUNTIME_ROOT "你的路径/onnxruntime") include_directories(${ONNXRUNTIME_ROOT}/include) link_directories(${ONNXRUNTIME_ROOT}/lib) # 2. OpenCV find_package(OpenCV REQUIRED) include_directories(${OpenCV_INCLUDE_DIRS}) # 3. 链接目标 target_link_libraries(your_target ${OpenCV_LIBS} onnxruntime)

Windows 下链接的库名通常是onnxruntime.lib,Linux 下是libonnxruntime.so。如果编译时报LNK2019未解析外部符号,先确认库路径和库名没写错,再确认 32/64 位一致。

4.2 faceanalysis 模块在做什么

faceanalysis.h/cpp负责人脸检测和关键点提取,是整条链路的前置。它一般封装了一个轻量检测模型(比如 SCRFD 或类似结构)的 onnxruntime 推理,输入一张图,输出人脸框和五点/多点关键点。这些关键点后面要用来做对齐和运动参考。

看这个模块时重点关注输入输出的张量形状和归一化方式。检测模型的输入通常是1x3xHxW,像素值归一化到 0~1 或减均值除方差,具体看模型导出时的设定。归一化搞错,检测框会飘。

4.3 liveportrait 模块的推理封装

liveportrait.h/cpp是核心,把外观提取、运动提取、生成器几个 onnxruntime session 串起来。典型结构是类里持有多个Ort::Session对象,提供init()加载模型、run()执行推理的接口。

// 伪代码示意,实际以包内实现为准 class LivePortrait { public: bool init(const std::string& model_dir); cv::Mat animate(const cv::Mat& source, const cv::Mat& driving_frame); private: Ort::Session appearance_session_; Ort::Session motion_session_; Ort::Session generator_session_; };

main.cpp则是把读视频、逐帧调用、写视频串起来的主流程。编译前确认main.cpp里的模型路径、输入视频路径都改成你本地的实际路径。

4.4 编译命令与常见链接错误

cd cpp mkdir build && cd build cmake .. cmake --build . --config Release

Release 模式很重要,Debug 下 onnxruntime 推理会慢好几倍。如果 cmake 阶段报找不到 onnxruntime,检查ONNXRUNTIME_ROOT是否指向了正确的解压目录;如果链接阶段报错,检查库文件名和平台后缀。Linux 下还可能需要把 onnxruntime 的 lib 目录加进LD_LIBRARY_PATH,否则运行时报找不到共享库。

5. 避坑与排查:模型路径、显存、关键点抖动这些翻车点

5.1 报错找不到 onnx 模型文件

现象:程序启动即退出,日志显示Failed to load model或No such file。 原因:模型文件没下载,或者路径拼接时多了/少了一层目录,Windows 下反斜杠和正斜杠混用也可能出问题。 解决:打印出程序实际拼接的完整路径,和文件系统里的真实路径逐字符比对。统一用正斜杠或std::filesystem::path拼接。

5.2 GPU 推理时显存不足

现象:跑几帧后崩溃,报CUDA out of memory或 onnxruntime 的 allocation 失败。 原因:驱动视频分辨率太高,或者同时加载了多个 session 没释放中间张量。 解决:先把驱动视频缩到 512 或 256 宽度试跑,确认能通再逐步放大。onnxruntime 的 GPU 内存池可以通过 session options 限制,别让它无限涨。

5.3 输出视频人脸区域抖动或跳变

现象:生成的动画在某些帧突然歪一下或者闪。 原因:驱动视频里人脸检测在某几帧失败,关键点跳到了背景上,运动信号就脏了。 解决:对驱动视频先做一遍人脸检测过滤,检测置信度低的帧做插值或者跳过。也可以在运动信号上加一点时序平滑,常见做法是滑动平均。

5.4 C++ 编译过但运行时报 DLL 缺失

现象:exe 双击没反应,或者命令行报找不到onnxruntime.dll。 原因:动态库没放到 exe 同目录,或者系统 PATH 里没有。 解决:把 onnxruntime 的 dll 复制到 exe 旁边,最省事。Windows 下也可以用dumpbin /dependents看依赖了哪些 dll,逐个补齐。

5.5 Python 和 C++ 结果不一致

现象:同一张源图同一个驱动视频,两条路输出效果有差异。 原因:预处理(裁剪、归一化、颜色通道顺序)实现不一致,或者模型版本不同。 解决:先确认两边用的是同一批 onnx 文件,再逐行比对预处理代码。OpenCV 默认 BGR,很多模型要 RGB,这个转换漏了颜色就会偏。

6. 进阶技巧:用 C++ 接口做批量处理和实时预览的取舍

跑通单条之后,真正要落地通常会碰到两个需求:批量处理一堆源图,或者做实时预览。这两件事在 C++ 里的做法不太一样。

批量处理的关键是把模型加载和推理分开。init()只调一次,把几个 session 常驻内存,然后循环读图、推理、写文件。我一般会写一个简单的任务队列:

// 初始化一次,复用 session LivePortrait lp; lp.init(model_dir); for (const auto& img_path : image_list) { cv::Mat src = cv::imread(img_path); cv::Mat driving = cv::imread(driving_frame_path); cv::Mat out = lp.animate(src, driving); cv::imwrite("out_" + img_path, out); }

这样比每次重新 init 快一个数量级,因为省掉了模型加载和显存分配的开销。

实时预览则是另一回事。onnxruntime 在 CPU 上跑一帧 LivePortrait 通常要几百毫秒,做不到 30fps。想实时,要么上 GPU 并把分辨率压到 256 以内,要么做帧间缓存——只对关键帧跑完整推理,中间帧用光流或者简单形变过渡。这个取舍没有标准答案,看你的场景能接受多少延迟。

验证结果是否正常,我有个笨办法但很管用:拿同一张源图,分别用原始驱动视频和一段静止画面去驱动。静止画面驱动出来的结果应该几乎不动,如果还在大幅晃,说明运动信号提取或者时序处理有问题。这个对照测试能快速区分是模型问题还是输入问题。

从那以后我每次拿到这类 onnxruntime 部署包,都先跑一遍静止驱动对照,再跑正常驱动,两步都过了才往工程里集成。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 22:00:41

cua极简效率实践:用短脆快思路优化重复操作

1. 从“cua”这个音节说起:它到底是什么第一次看到“cua”这三个字母,很多人会愣一下。它不像一个完整的英文单词,也不像某个技术术语的缩写,更像是一个拟声词或者拼音组合。我在不同场合见过这个词被反复提起:有人把它…

作者头像 李华
网站建设 2026/10/10 21:50:31

Lua表调试与dump函数实战:告别print地址,高效排查配置数据

print 一个 table,看到的却是table: 0x7f9f8a0c1e60这种地址,几乎是每个 Lua 开发者的日常。Lua 里所有复杂数据都往 table 里塞,数组、字典、对象、配置,表面上都是同一种结构,可标准库的 print 对 table 只做一件事&…

作者头像 李华
网站建设 2026/10/10 21:49:03

Matlab实现粒子群算法无功优化:IEEE14节点实战全解析

直接讲几句大实话:电力系统无功优化这个方向,论文里写了无数遍,但真正动手在Matlab里把一段能跑的代码调通、把粒子群算法和无功潮流耦合起来,中间的门槛远比看公式要高。我自己第一次做这个题目时,光是搞清楚控制变量…

作者头像 李华
网站建设 2026/10/10 21:46:50

二维SSH模型Matlab复现:紧束缚能带、投影能带与高阶拓扑角态

动手做二维SSH模型之前,我把一维SSH的论文来回翻了好几遍。一维的情况很清爽:胞内hopping一个参数,胞间一个参数,边界态、Zak phase、末端极化,全都讲得明明白白。可是到了二维,论文里的图变成了一张张原子…

作者头像 李华