Faceswap Extract 插件体系解析:检测、对齐、分割与身份嵌入的统一流水线
FaceSwap 的 extract 命令是整套 Deepfake 工作流的起点:它从原始图片/视频中检测人脸、提取 68 点特征、对齐裁剪出标准尺寸的人脸贴片,并可选地生成脸部分割掩码与身份嵌入向量。本文以 docs/full/plugins/extract.rst 这份 API 参考文档为骨架,逐模块拆解 plugins/extract/ 下的基础类、各插件实现以及提取配置项,帮助你在能跑通 python faceswap.py extract 的前提下,真正理解每个插件的输入约定、配置参数与底层调用链。读完后你能独立看懂并配置 extract 流水线中每一个插件的行为,并定位到具体源码文件。
1. Extract 命令与插件包总览
FaceSwap 将"提取人脸"这一步抽象成一条由多类插件组成的流水线。docs/full/plugins/extract.rst 中用 automodapi 指令列出了整套被文档化的模块:
plugins.extract.base— 所有 extract 插件的基类;plugins.extract.align(cv2_dnn、dark_decoder、fan、hrnet)— 特征点/对齐插件;plugins.extract.detect(cv2_dnn、mtcnn、retinaface、s3fd)— 人脸检测插件;plugins.extract.mask(bisenet_fp、custom、unet_dfl、vgg_clear、vgg_obstructed)— 脸部分割掩码插件;plugins.extract.identity(vggface2、t_face)— 身份嵌入插件;plugins.extract.extract_config— 适用于所有提取插件的全局默认配置。
这些插件被加载后由 lib/infer/handler.py 中的 ExtractHandler(第 48 行)和 ExtractHandlerFace(第 274 行)统一调度;数据容器与流水线信号定义在 lib/infer/objects.py 的 ExtractBatchAligned 数据类和 ExtractSignal(FLUSH/SHUTDOWN)中。从源码结构看,整个提取过程是一个以 batch 为基本单位、按 detect → align → (mask/identity) 顺序传递的批处理流水线。
命令行入口与配置在 USAGE.md 中给出:
# 从文件夹提取
python faceswap.py extract -i ~/faceswap/src/trump -o ~/faceswap/faces/trump
# 从视频提取
python faceswap.py extract -i ~/faceswap/src/trump.mp4 -o ~/faceswap/faces/trump
# 查看全部参数
python faceswap.py extract -h
提取完成后,除输出对齐后的人脸图片外,还会在输入目录生成 alignments.json,供后续训练/转换步骤复用。插件自身的可调选项集中写在 config/extract.ini(首次运行 extract 或 GUI 后自动生成,参见 USAGE.md)。
2. 基础类:ExtractPlugin 与 FacePlugin(plugins/extract/base.py)
plugins/extract/base.py 是整个 extract 包的核心,docs/full/plugins/extract.rst 的第一个 automodapi 指令即指向它。它定义了两个抽象基类。
2.1 ExtractPlugin:通用插件接口
ExtractPlugin(第 177 行)是所有插件必须继承的抽象类,其构造函数确立了"插件-框架"之间的数据契约:
class ExtractPlugin(abc.ABC):
def __init__(self,
input_size: int,
batch_size: int = 1,
is_rgb: bool = False,
dtype: str = "float32",
scale: tuple[int, int] = (0, 1),
force_cpu: bool = False) -> None:
各参数含义(直接决定插件喂给模型的图像形态):
| 参数 | 默认 | 说明 |
|---|---|---|
input_size |
必填 | 插件期望的输入边长,输入恒为该尺寸的正方形 |
batch_size |
1 |
process 方法处理数据的批大小(仅 process 保证收到该值或更小) |
is_rgb |
False |
True 表示插件期望 RGB 图像,否则为 BGR |
dtype |
"float32" |
插件期望接收的图像数据类型 |
scale |
(0, 1) |
期望的数值范围,如 uint8 图像用 (0, 255) |
force_cpu |
False |
Torch 模型强制在 CPU 运行 |
插件需要实现/重写的四个阶段方法,构成标准批处理生命周期:
load_model()(抽象):加载模型,返回可赋给self.model的对象;pre_process(batch):对齐插件用它把检测到的 ROI 包围盒调整成从原图切出正方形;其他插件做归一化等预处理;process(batch)(抽象):真正调用模型的地方。返回"可以是任意 numpy 数组",检测类若返回多个结果必须包成 object 数组;post_process(batch):约定各插件的输出形状,例如 detect 返回(N, M, left, top, right, bottom)的 float32 包围盒(N 为批大小,M 为每张图的检出数);align 返回(N, 68, 2)归一化到 0~1 的特征点;mask 返回(N, size, size)0~1 的 float32 掩码;identity 返回(N, M)的 float32 嵌入。
2.2 FacePlugin:处理已对齐人脸的插件
FacePlugin(第 364 行)继承自 ExtractPlugin,额外增加一个 centering 参数(取值 "face"/"head"/"legacy",默认 "face"),并自动按模块名生成一个便于序列化的 storage_name(下划线转连字符):
self.storage_name = self.__module__.rsplit(".", maxsplit=1)[-1].replace("_", "-")
mask 插件常在此基础上再追加 centering 后缀以区分 face/head 两种存储形态(见下文 BiSeNet)。
2.3 _TorchInfer:PyTorch 推理的默认优化
对使用 PyTorch 的插件,ExtractPlugin 内嵌一个 _TorchInfer 助手(第 26 行),并通过 load_torch_model() 与 from_torch() 两个便捷方法对外暴露。它封装了若干默认优化(源码注释明确说"不通过它加载将不会获得这些优化"):
- 设备选择:
_get_device()依次探测 CUDA → MPS → CPU;force_cpu=True时直接落到 CPU; load_torch_model():torch.load权重 →load_state_dict→.to(device, memory_format=torch.channels_last)→model.eval();from_torch()/predict():在torch.inference_mode()下推理,CUDA 可用时启用pin_memory()+non_blocking加速 H2D 传输,并用channels_last内存格式;return_indices:模型若输出多个张量而插件只用其中一部分,可只把指定下标从 GPU 拷回,减少显存搬运;- 首批次自省:
_process_first_batch()用 warmup 批次判断输出是单张量还是列表,从而决定predict返回普通 ndarray 还是 object 数组。
这段代码解释了为什么 FaceSwap 里大量 PyTorch 插件只需"声明 + 调 from_torch"两行,就能拿到 channels_last、pinned memory 等吞吐优化。
3. Align 包:从 ROI 到 68 点特征
docs/full/plugins/extract.rst 的 "align package" 小节文档化了四个模块。对齐插件的输入约定与检测不同:pre_process 收到的是检测 ROI 包围盒 (batch, left, top, right, bottom) 的 INT32,process 收到对齐后的人脸贴片。
| 模块 | 类 | input_size |
is_rgb / scale |
备注 |
|---|---|---|---|---|
align/cv2_dnn.py |
CV2DNNAlign |
128 | RGB / (0,1) | 轻量 CNN 特征点,batch_size=1,基于 OpenCV DNN |
align/fan.py |
FAN |
256 | RGB / (0,1) | 头部对齐网络,可选 DARK 解码器,realign_centering="head",_reference_scale=0.8 |
align/hrnet.py |
HRNet |
256 | RGB / (0,1) | 高分辨率特征点,用 ImageNet 均值/方差归一化(0.485/0.456/0.406, 0.229/0.224/0.225) |
align/dark_decoder.py |
Dark |
— | — | 供热力图类对齐器解码的 DARK 解码器(如 Dark(68, 64)) |
要点:
dark_decoder.py本身不是一个独立"插件",而是热力图对齐(FAN/HRNet 输出的是 68 个热力图)到 68 个(x, y)特征点的解码器。从源码看,FAN.__init__中self._dark = Dark(68, 64) if cfg.dark_decoder() else None,即 FAN 依赖该解码器把每个热力图峰位转成坐标。- FAN 代码头部注明"adapted and modified from 1adrianb/face-alignment",并提到默认 reference scale(
200./195.)会导致特征点不够理想,因此收紧为0.8。 - HRNet 内部实现了
BasicBlock、BasicBlockAttention、Bottleneck等模块,是精度更高的对齐方案;cv2_dnn则是最轻量的 CPU 友好选项。
4. Detect 包:四种人脸检测器
detect 插件的输入是方形、已填充的整帧图像;process 返回 object 数组,post_process 输出 (N, M, left, top, right, bottom) 包围盒。
| 模块 | 类 | input_size |
is_rgb / scale |
后端 / 备注 |
|---|---|---|---|---|
detect/cv2_dnn.py |
CV2DNNDetect |
300 | BGR / (0,255) | OpenCV DNN,均值 (104,117,123),输出 object 数组 |
detect/mtcnn.py |
MTCNN |
640 | RGB / (-1,1) | 级联网络,内部实现 PNet/RNet |
detect/retinaface.py |
— | — | — | 基于 Pytorch_Retinaface 移植,torchvision 骨干 |
detect/s3fd.py |
S3FD |
640 | BGR / (0,255) | 单阶段检测器,GPU 快、CPU 慢,均值 (104.0,117.0,123.0) |
以 plugins/extract/detect/s3fd.py 为例,其构造函数直接体现了基础类的契约:
class S3FD(ExtractPlugin):
def __init__(self) -> None:
super().__init__(input_size=640,
batch_size=cfg.batch_size(),
is_rgb=False,
dtype="float32",
scale=(0, 255))
self._model_path = self._get_weights_path()
self._average_img = np.array([104.0, 117.0, 123.0], dtype="float32")
self._confidence = cfg.confidence() / 100
权重通过 GetModel 在需要时自动下载(_get_weights_path()),并把默认 confidence(百分比)归一化成 0~1 阈值。
每个检测插件都带一个 <plugin>_defaults.py 配置文件,例如 plugins/extract/detect/s3fd_defaults.py 定义了:
HELPTEXT = ("S3FD Detector options.\n"
"Fast on GPU, slow on CPU. Can detect more faces and fewer false positives "
"than other GPU detectors, but is a lot more resource intensive.")
confidence = ConfigItem(datatype=int, default=70, group="settings",
info="The confidence level at which the detector has successfully found a face.",
rounding=5, min_max=(25, 100))
batch_size = ConfigItem(datatype=int, default=4, group="settings",
info="The batch size to use. ...", rounding=1, min_max=(1, 128))
这些 <plugin>_defaults.py 会自动被合并进 config/extract.ini 与 GUI 设置页(该文件头部 docstring 明确说明了此机制),因此 confidence、batch_size 既是源码常量,也是可被用户覆盖的配置项。
5. Mask 包:脸部分割掩码
mask 插件都继承 FacePlugin,输入是已对齐的人脸贴片,post_process 输出 (N, size, size) 的 0~1 float32 掩码。centering 参数决定掩码按 face 还是 head 中心存储。
| 模块 | 类 | input_size |
is_rgb / scale |
centering |
备注 |
|---|---|---|---|---|---|
mask/bisenet_fp.py |
BiSeNetFP |
512 | RGB / (0,1) | head(若含头发)否则 face | 脸部解析(face-parsing)模型,按头发开关切换均值 |
mask/custom.py |
Custom |
256 | BGR / (0,255) uint8 | 用户指定 | 无模型,按设置整体填 1/0 |
mask/unet_dfl.py |
UNetDFL |
256 | BGR / (0,1) | legacy | 基于 TernausNet/UNet |
mask/vgg_clear.py |
VGGClear |
300 | BGR / (0,255) | face | VGG 骨干分割 |
mask/vgg_obstructed.py |
VGGObstructed |
500 | BGR / (0,255) | face | 面向遮挡场景的 VGG 分割 |
BiSeNetFP 的实现最能体现 FacePlugin 的 centering 语义(plugins/extract/mask/bisenet_fp.py):
super().__init__(input_size=512,
batch_size=cfg.batch_size(),
is_rgb=True,
dtype="float32",
scale=(0, 1),
force_cpu=cfg.cpu(),
centering="head" if cfg.include_hair() else "face")
...
self.storage_name = f"{self.storage_name}_{self.centering}"
mean = (0.384, 0.314, 0.279) if self._is_faceswap else (0.485, 0.456, 0.406)
即:是否包含头发会同时影响 1) 喂给模型的 centering,2) 存储掩码的中心方式,3) 归一化均值(faceswap 微调权重与原版 ImageNet 权重不同)。Custom 则是无模型的"手动掩码",load_model() 直接返回、pre_process 返回与输入同形状的全零数组,再由用户设定填充 1/0。
6. Identity 包:身份嵌入向量
identity 插件输出 (N, M) 的 float32 身份嵌入,用于比较人脸相似度(例如筛选同一人、剔除非目标人脸)。
| 模块 | 类 | input_size |
is_rgb / scale |
centering |
备注 |
|---|---|---|---|---|---|
identity/vggface2.py |
VGGFace2 |
224 | BGR / (0,255) | — | VGGFace2-ResNet50,输入须为 BGR |
identity/t_face.py |
TFace |
112 | RGB / (0,1) | legacy | 腾讯 InsightFace 风格 ResNet(ir_50/ir_101) |
TFace 的构造体现了不同身份模型间输入约定的差异(plugins/extract/identity/t_face.py):
super().__init__(input_size=112,
batch_size=cfg.batch_size(),
is_rgb=True,
dtype="float32",
scale=(0, 1),
centering="legacy")
它与 VGGFace2(224、BGR、0~255)在分辨率、通道顺序和数值范围上完全不同——这正是 ExtractPlugin 用 input_size/is_rgb/dtype/scale 四个参数统一描述"插件输入约定"的价值:上层流水线据此自动做 resize、通道转换和缩放,插件内部无需关心原始帧的形态。
7. extract_config:适用于所有提取插件的全局配置
docs/full/plugins/extract.rst 的最后指向 plugins.extract.extract_config(plugins/extract/extract_config.py)。它定义了一组 _Config(FaceswapConfig) 的默认项,并在 set_defaults 中调用 self._defaults_from_plugin(os.path.dirname(__file__)),把本目录下所有插件的 <plugin>_defaults.py 一并聚合进 config/extract.ini。各 ConfigItem 及其取值范围如下(min_max 即 GUI 滑块/输入框上下限):
7.1 align 组
| 配置项 | 默认 | 范围 | 作用 |
|---|---|---|---|
aligner_min_scale |
0.03 |
(0.0, 1.0) | 过滤小于"最小帧边长 × 该值"的人脸,视为误检 |
aligner_max_scale |
4.00 |
(0.0, 10.0) | 过滤大于"最小帧边长 × 该值"的人脸 |
aligner_distance |
40.0 |
(0.0, 45.0) | 特征点距"平均脸"超过该距离则丢弃(>15 较安全,>10 更严) |
aligner_roll |
0.0 |
(0.0, 90.0) | 计算出的 roll 偏离 0 超过该角度(度)则丢弃 |
aligner_features |
True |
bool | 丢弃"眼/眉最低点低于嘴最高点"的错对齐脸 |
7.2 mask / profile 组
| 配置项 | 默认 | 范围 | 作用 |
|---|---|---|---|
mask_storage_size |
128 |
(0, 1028),步长 64 | 掩码存储尺寸;0 表示按模型输出尺寸存储 |
profile_warmup_time |
2 |
(1, 10) | 每个 batch size 下模型预热秒数 |
profile_test_time |
10 |
(8, 30) | 每个 batch size 下 profile 流水线秒数 |
profile_num_faces |
2 |
(1, 10) | 期望每帧检出人脸数,影响下游插件吞吐优化 |
profile_max_vram |
85 |
(25, 95) | 允许 Cuda 预占的最大显存百分比,越接近 100% 越易 OOM |
profile_save_config |
False |
bool | 是否把探测到的最优 batch size 写回 config 供后续使用 |
这些 profile 项配合 lib/infer/profile.py 的自动批大小探测逻辑,是 FaceSwap 在 extract 阶段"先 profile 再正式跑"策略的落地:检测器吞吐按"1 图 = 1 样本"计算,而 align/mask 等下游插件吞吐取决于每帧人脸数,因此 profile_num_faces 设得越准,优化越有效。
extract_config 的加载入口是:
def load_config(config_file: str | None = None) -> _Config:
global _CONFIG
if _CONFIG is None:
_CONFIG = _Config(config_file=config_file)
return _CONFIG
即全局单例,支持传入自定义 .ini 路径。
8. 把插件与流水线串起来:一次 extract 的数据流
结合前文源码,可还原一条典型的 extract 数据流(均为源码可确认的结构,调用链从 lib/infer/ 调度器出发):
- 帧进入:原始帧(图片/视频抽帧)按检测插件
input_size方形化、填充,并按其is_rgb/dtype/scale转换; - detect:
process检出包围盒,post_process产出(N, M, l, t, r, b);aligner_min_scale / max_scale / distance / roll / features在此后阶段过滤误检; - align:把 ROI 调整为正方形切出人脸贴片,
post_process输出(N, 68, 2)归一化特征点; - mask / identity(按 centering 取对齐贴片):mask 输出
(N, size, size)掩码并按mask_storage_size缩放存储;identity 输出(N, M)嵌入; - 落盘:对齐人脸写入输出目录,
alignments.json记录每脸的元数据。
整条链路的批处理载体是 lib/infer/objects.py 的 ExtractBatchAligned(缓存 68 点与归一化特征点),控制信号 ExtractSignal.FLUSH/SHUTDOWN 用于冲刷队列与收尾。每个插件只需实现四个阶段方法,设备选择、通道转换、内存格式与 pinned memory 等由 ExtractPlugin._TorchInfer 统一处理——这正是 docs/full/plugins/extract.rst 用 include-all-objects 文档化 base 模块的原因:它是理解其余所有插件的前提。
9. 小结与延伸阅读
plugins/extract/base.py定义了ExtractPlugin/FacePlugin/_TorchInfer三层,是所有插件的"输入契约 + 推理优化"中枢;- 四类插件包(detect / align / mask / identity)各自以
<plugin>.py+<plugin>_defaults.py成对出现,后者自动汇入config/extract.ini; extract_config.py提供 aligner 过滤、mask 存储尺寸与 profile 探测等全局旋钮,取值范围由min_max约束;- 插件的加载与批调度由
lib/infer/(handler.py、objects.py、profile.py)完成,USAGE.md给出命令行入口。
可进一步深入的路径:plugins/extract/base.py、plugins/extract/extract_config.py、plugins/extract/detect/s3fd_defaults.py、lib/infer/handler.py、lib/infer/objects.py、USAGE.md。
适用前提:以上参数、默认值与取值范围均以当前仓库源码为准;不同插件的权重由
GetModel在首次需要时自动下载。GPU 相关优化(channels_last、pinned memory、CUDA 设备选择)仅在存在可用 CUDA/MPS 后端时生效,CPU 环境会自动降级。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00