首页
/ Faceswap Extract 插件体系解析:检测、对齐、分割与身份嵌入的统一流水线

Faceswap Extract 插件体系解析:检测、对齐、分割与身份嵌入的统一流水线

2026-09-06 21:36:06作者:齐冠琰

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.aligncv2_dnndark_decoderfanhrnet)— 特征点/对齐插件;
  • plugins.extract.detectcv2_dnnmtcnnretinafaces3fd)— 人脸检测插件;
  • plugins.extract.maskbisenet_fpcustomunet_dflvgg_clearvgg_obstructed)— 脸部分割掩码插件;
  • plugins.extract.identityvggface2t_face)— 身份嵌入插件;
  • plugins.extract.extract_config — 适用于所有提取插件的全局默认配置。

这些插件被加载后由 lib/infer/handler.py 中的 ExtractHandler(第 48 行)和 ExtractHandlerFace(第 274 行)统一调度;数据容器与流水线信号定义在 lib/infer/objects.pyExtractBatchAligned 数据类和 ExtractSignalFLUSH/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. 基础类:ExtractPluginFacePlugin(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 内部实现了 BasicBlockBasicBlockAttentionBottleneck 等模块,是精度更高的对齐方案;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 明确说明了此机制),因此 confidencebatch_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)在分辨率、通道顺序和数值范围上完全不同——这正是 ExtractPlugininput_size/is_rgb/dtype/scale 四个参数统一描述"插件输入约定"的价值:上层流水线据此自动做 resize、通道转换和缩放,插件内部无需关心原始帧的形态。


7. extract_config:适用于所有提取插件的全局配置

docs/full/plugins/extract.rst 的最后指向 plugins.extract.extract_configplugins/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/ 调度器出发):

  1. 帧进入:原始帧(图片/视频抽帧)按检测插件 input_size 方形化、填充,并按其 is_rgb/dtype/scale 转换;
  2. detectprocess 检出包围盒,post_process 产出 (N, M, l, t, r, b)aligner_min_scale / max_scale / distance / roll / features 在此后阶段过滤误检;
  3. align:把 ROI 调整为正方形切出人脸贴片,post_process 输出 (N, 68, 2) 归一化特征点;
  4. mask / identity(按 centering 取对齐贴片):mask 输出 (N, size, size) 掩码并按 mask_storage_size 缩放存储;identity 输出 (N, M) 嵌入;
  5. 落盘:对齐人脸写入输出目录,alignments.json 记录每脸的元数据。

整条链路的批处理载体是 lib/infer/objects.pyExtractBatchAligned(缓存 68 点与归一化特征点),控制信号 ExtractSignal.FLUSH/SHUTDOWN 用于冲刷队列与收尾。每个插件只需实现四个阶段方法,设备选择、通道转换、内存格式与 pinned memory 等由 ExtractPlugin._TorchInfer 统一处理——这正是 docs/full/plugins/extract.rstinclude-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.pyobjects.pyprofile.py)完成,USAGE.md 给出命令行入口。

可进一步深入的路径:plugins/extract/base.pyplugins/extract/extract_config.pyplugins/extract/detect/s3fd_defaults.pylib/infer/handler.pylib/infer/objects.pyUSAGE.md

适用前提:以上参数、默认值与取值范围均以当前仓库源码为准;不同插件的权重由 GetModel 在首次需要时自动下载。GPU 相关优化(channels_last、pinned memory、CUDA 设备选择)仅在存在可用 CUDA/MPS 后端时生效,CPU 环境会自动降级。

登录后查看全文
热门项目推荐
相关项目推荐