comfyui_controlnet_aux
扩展介绍
ComfyUI 的 ControlNet 辅助预处理器
即插即用的 ComfyUI 节点集,用于生成 ControlNet 提示图像
“动漫风格,街头抗议场景,赛博朋克城市,一位粉色头发、金色眼睛的女性(看向观众)举着一块牌子,上面用粗体霓虹粉色写着“ComfyUI ControlNet Aux”文字” 在 Flux.1 Dev 上生成。

代码是从 https://github.com/lllyasviel/ControlNet/tree/main/annotator 中的相应文件夹复制粘贴而来,并连接到 🤗 Hub。
所有功劳和版权归 https://github.com/lllyasviel 所有。
更新
前往 更新页面 以关注更新
安装:
使用 ComfyUI Manager(推荐):
安装 ComfyUI Manager,并按照其中介绍的步骤安装此仓库。
替代方法:
如果你在 Linux 上运行,或使用 Windows 上的非管理员账户,你需要确保 /ComfyUI/custom_nodes 和 comfyui_controlnet_aux 具有写入权限。
现在有一个 install.bat 文件,你可以运行它来安装到便携版(如果检测到)。否则,它将默认安装到系统版,并假设你已遵循 ConfyUI 的手动安装步骤。
如果你无法运行 install.bat(例如你是 Linux 用户),请打开 CMD/Shell 并执行以下操作:
- 导航到你的
/ComfyUI/custom_nodes/文件夹 - 运行
git clone https://github.com/Fannovel16/comfyui_controlnet_aux/ - 导航到你的
comfyui_controlnet_aux文件夹- 便携版/虚拟环境:
- 运行
path/to/ComfUI/python_embeded/python.exe -s -m pip install -r requirements.txt
- 运行
- 使用系统 Python
- 运行
pip install -r requirements.txt
- 运行
- 便携版/虚拟环境:
- 启动 ComfyUI
节点
请注意,此仓库仅支持生成提示图像的预处理器(例如火柴人、Canny 边缘等)。 除 Inpaint 之外的所有预处理器都集成在 AIO Aux Preprocessor 节点中。 该节点允许你快速获取预处理器,但无法设置预处理器自身的阈值参数。 你需要直接使用其对应节点来设置阈值。
节点(各部分是 Comfy 菜单中的分类)
线条提取器
预处理器节点 | sd-webui-controlnet/其他 | ControlNet/T2I-Adapter |
|---|---|---|
二值线条 | binary | control_scribble |
Canny 边缘 | canny | control_v11p_sd15_canny control_canny t2iadapter_canny |
HED 软边缘线条 | hed | control_v11p_sd15_softedge control_hed |
标准线稿 | standard_lineart | control_v11p_sd15_lineart |
写实线稿 | lineart(如果启用了 | control_v11p_sd15_lineart |
动漫线稿 | lineart_anime | control_v11p_sd15s2_lineart_anime |
漫画线稿 | lineart_anime_denoise | control_v11p_sd15s2_lineart_anime |
M-LSD 线条 | mlsd | control_v11p_sd15_mlsd control_mlsd |
PiDiNet 软边缘线条 | pidinet | control_v11p_sd15_softedge control_scribble |
涂鸦线条 | scribble | control_v11p_sd15_scribble control_scribble |
涂鸦 XDoG 线条 | scribble_xdog | control_v11p_sd15_scribble control_scribble |
伪涂鸦线条 | scribble_hed | control_v11p_sd15_scribble control_scribble |
TEED 软边缘线条 | teed | controlnet-sd-xl-1.0-softedge-dexined control_v11p_sd15_softedge(理论上) |
涂鸦 PiDiNet 线条 | scribble_pidinet | control_v11p_sd15_scribble control_scribble |
AnyLine 线稿 | mistoLine_fp16.safetensors mistoLine_rank256 control_v11p_sd15s2_lineart_anime control_v11p_sd15_lineart |
法线与深度估计器
预处理器节点 | sd-webui-controlnet/其他 | ControlNet/T2I-Adapter |
|---|---|---|
MiDaS 深度图 | (normal) depth | control_v11f1p_sd15_depth control_depth t2iadapter_depth |
LeReS 深度图 | depth_leres | control_v11f1p_sd15_depth control_depth t2iadapter_depth |
Zoe 深度图 | depth_zoe | control_v11f1p_sd15_depth control_depth t2iadapter_depth |
MiDaS 法线贴图 | normal_map | control_normal |
BAE 法线贴图 | normal_bae | control_v11p_sd15_normalbae |
MeshGraphormer 手部细化器(HandRefinder) | depth_hand_refiner | |
深度任意 | depth_anything | |
Zoe 深度任意 (基本上是 Zoe,但编码器替换为 DepthAnything) | depth_anything | |
法线 DSINE | control_normal/control_v11p_sd15_normalbae | |
Metric3D 深度 | control_v11f1p_sd15_depth control_depth t2iadapter_depth | |
Metric3D 法线 | control_v11p_sd15_normalbae | |
深度任意 V2 |
人脸和姿态估计器
预处理器节点 | sd-webui-controlnet/其他 | ControlNet/T2I-Adapter |
|---|
DWPose 姿态估计器 | dw_openpose_full | control_v11p_sd15_openpose control_openpose t2iadapter_openpose |
OpenPose 姿态估计器 | openpose (检测身体) openpose_hand (检测身体 + 检测手部) openpose_faceonly (检测面部) openpose_full (检测手部 + 检测身体 + 检测面部) | control_v11p_sd15_openpose control_openpose t2iadapter_openpose |
MediaPipe 面部网格 | mediapipe_face | controlnet_sd21_laion_face_v2 |
动物姿态估计器 | animal_openpose |
光流估计器
预处理器节点 | sd-webui-controlnet/其他 | ControlNet/T2I-Adapter |
|---|---|---|
Unimatch 光流 |
如何获取 OpenPose 格式的 JSON?
用户端
此工作流会将图像保存到 ComfyUI 的输出文件夹(与输出图像相同的位置)。如果尚未找到 Save Pose Keypoints 节点,请更新此扩展 
开发者端
对于 IMAGE 批次中的每一帧,可以通过 UI 上的 app.nodeOutputs 或 /history API 端点,从 DWPose 和 OpenPose 获取一组 OpenPose 格式的 JSON 数据。AnimalPose 的 JSON 输出格式与 OpenPose JSON 类似:
[
{
"version": "ap10k",
"animals": [
[[x1, y1, 1], [x2, y2, 1],..., [x17, y17, 1]],
[[x1, y1, 1], [x2, y2, 1],..., [x17, y17, 1]],
...
],
"canvas_height": 512,
"canvas_width": 768
},
...
]
对于扩展开发者(例如 Openpose 编辑器):
const poseNodes = app.graph._nodes.filter(node => ["OpenposePreprocessor", "DWPreprocessor", "AnimalPosePreprocessor"].includes(node.type))
for (const poseNode of poseNodes) {
const openposeResults = JSON.parse(app.nodeOutputs[poseNode.id].openpose_json[0])
console.log(openposeResults) //An array containing Openpose JSON for each frame
}
对于 API 用户: JavaScript
import fetch from "node-fetch" //Remember to add "type": "module" to "package.json"
async function main() {
const promptId = '792c1905-ecfe-41f4-8114-83e6a4a09a9f' //Too lazy to POST /queue
let history = await fetch(`http://127.0.0.1:8188/history/${promptId}`).then(re => re.json())
history = history[promptId]
const nodeOutputs = Object.values(history.outputs).filter(output => output.openpose_json)
for (const nodeOutput of nodeOutputs) {
const openposeResults = JSON.parse(nodeOutput.openpose_json[0])
console.log(openposeResults) //An array containing Openpose JSON for each frame
}
}
main()
Python
import json, urllib.request
server_address = "127.0.0.1:8188"
prompt_id = '' #Too lazy to POST /queue
def get_history(prompt_id):
with urllib.request.urlopen("http://{}/history/{}".format(server_address, prompt_id)) as response:
return json.loads(response.read())
history = get_history(prompt_id)[prompt_id]
for o in history['outputs']:
for node_id in history['outputs']:
node_output = history['outputs'][node_id]
if 'openpose_json' in node_output:
print(json.loads(node_output['openpose_json'][0])) #An list containing Openpose JSON for each frame
语义分割
预处理器节点 | sd-webui-controlnet/其他 | ControlNet/T2I-Adapter |
|---|---|---|
OneFormer ADE20K 分割器 | oneformer_ade20k | control_v11p_sd15_seg |
OneFormer COCO 分割器 | oneformer_coco | control_v11p_sd15_seg |
UniFormer 分割器 | segmentation | control_sd15_seg control_v11p_sd15_seg |
仅限 T2I-Adapter
预处理器节点 | sd-webui-controlnet/其他 | ControlNet/T2I-Adapter |
|---|---|---|
调色板 | color | t2iadapter_color |
内容洗牌 | shuffle | t2iadapter_style |
重新着色
预处理器节点 | sd-webui-controlnet/其他 | ControlNet/T2I-Adapter |
|---|
图像亮度 | recolor_luminance | |
图像强度 | recolor_intensity | 不知道。也许和上面一样? |
示例
一图胜千言

问答:
为什么我安装了这个仓库后有些节点没有出现?
这个仓库有一个新机制,会跳过任何无法导入的自定义节点。如果你遇到这种情况,请在Issues 标签页创建一个问题,并附上命令行中的日志。
DWPose/AnimalPose 仅使用 CPU,因此速度很慢。如何让它使用 GPU?
有两种方法可以加速 DWPose:使用 TorchScript 检查点(.torchscript.pt)或 ONNXRuntime(.onnx)。TorchScript 方式比 ONNXRuntime 稍慢,但不需要任何额外的库,而且仍然比 CPU 快得多。
TorchScript 的 bbox 检测器与 ONNX 的姿态估计器兼容,反之亦然。
TorchScript
根据此图片设置 bbox_detector 和 pose_estimator。如果输入图像理想,您可以尝试使用 .torchscript.pt 的其他 bbox 检测器结尾,以减少 bbox 检测时间。 
ONNXRuntime
如果 onnxruntime 安装成功,并且检查点使用的结尾为 .onnx,它将替换默认的 cv2 后端以利用 GPU。请注意,如果您使用的是 NVidia 显卡,此方法目前仅适用于 CUDA 11.8(ComfyUI_windows_portable_nvidia_cu118_or_cpu.7z),除非您自行编译 onnxruntime。
- 了解您的 onnxruntime 构建版本:
- NVidia CUDA 11.x 或更低版本/AMD GPU:
onnxruntime-gpu - NVidia CUDA 12.x:
onnxruntime-gpu --extra-index-url https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/onnxruntime-cuda-12/pypi/simple/ - DirectML:
onnxruntime-directml - OpenVINO:
onnxruntime-openvino
- NVidia CUDA 11.x 或更低版本/AMD GPU:
请注意,如果您是第一次使用 ComfyUI,请在进行下一步之前测试它是否能在您的设备上运行。
- 将其添加到
requirements.txt中 - 运行
install.bat或安装部分提到的 pip 命令

预处理器的资源文件
- anime_face_segment(动漫人脸分割): bdsqlsz/qinglong_controlnet-lllite/Annotators/UNet.pth, anime-seg/isnetis.ckpt
- densepose: LayerNorm/DensePose-TorchScript-with-hint-image/densepose_r50_fpn_dl.torchscript
- dwpose:
- bbox_detector(边界框检测器):可选择 yzd-v/DWPose/yolox_l.onnx, hr16/yolox-onnx/yolox_l.torchscript.pt, hr16/yolo-nas-fp16/yolo_nas_l_fp16.onnx, hr16/yolo-nas-fp16/yolo_nas_m_fp16.onnx, hr16/yolo-nas-fp16/yolo_nas_s_fp16.onnx
- pose_estimator(姿态估计器):可选择 hr16/DWPose-TorchScript-BatchSize5/dw-ll_ucoco_384_bs5.torchscript.pt, yzd-v/DWPose/dw-ll_ucoco_384.onnx
- animal_pose(动物姿态,ap10k):
- bbox_detector:可选择 yzd-v/DWPose/yolox_l.onnx、hr16/yolox-onnx/yolox_l.torchscript.pt、hr16/yolo-nas-fp16/yolo_nas_l_fp16.onnx、hr16/yolo-nas-fp16/yolo_nas_m_fp16.onnx、hr16/yolo-nas-fp16/yolo_nas_s_fp16.onnx
- pose_estimator:可选择 hr16/DWPose-TorchScript-BatchSize5/rtmpose-m_ap10k_256_bs5.torchscript.pt、hr16/UnJIT-DWPose/rtmpose-m_ap10k_256.onnx
- hed:lllyasviel/Annotators/ControlNetHED.pth
- leres:lllyasviel/Annotators/res101.pth、lllyasviel/Annotators/latest_net_G.pth
- lineart:lllyasviel/Annotators/sk_model.pth、lllyasviel/Annotators/sk_model2.pth
- lineart_anime:lllyasviel/Annotators/netG.pth
- manga_line:lllyasviel/Annotators/erika.pth
- mesh_graphormer:hr16/ControlNet-HandRefiner-pruned/graphormer_hand_state_dict.bin、hr16/ControlNet-HandRefiner-pruned/hrnetv2_w64_imagenet_pretrained.pth
- midas:lllyasviel/Annotators/dpt_hybrid-midas-501f0c75.pt
- mlsd:lllyasviel/Annotators/mlsd_large_512_fp32.pth
- normalbae:lllyasviel/Annotators/scannet.pt
- oneformer:lllyasviel/Annotators/250_16_swin_l_oneformer_ade20k_160k.pth
- open_pose:lllyasviel/Annotators/body_pose_model.pth、lllyasviel/Annotators/hand_pose_model.pth、lllyasviel/Annotators/facenet.pth
- pidi: lllyasviel/Annotators/table5_pidinet.pth
- sam: dhkim2810/MobileSAM/mobile_sam.pt
- uniformer: lllyasviel/Annotators/upernet_global_small.pth
- zoe: lllyasviel/Annotators/ZoeD_M12_N.pt
- teed: bdsqlsz/qinglong_controlnet-lllite/7_model.pth
- depth_anything: 可以是 LiheYoung/Depth-Anything/checkpoints/depth_anything_vitl14.pth、LiheYoung/Depth-Anything/checkpoints/depth_anything_vitb14.pth 或 LiheYoung/Depth-Anything/checkpoints/depth_anything_vits14.pth
- diffusion_edge: 可以是 hr16/Diffusion-Edge/diffusion_edge_indoor.pt、hr16/Diffusion-Edge/diffusion_edge_urban.pt 或 hr16/Diffusion-Edge/diffusion_edge_natrual.pt
- unimatch:可以是 hr16/Unimatch/gmflow-scale2-regrefine6-mixdata.pth、hr16/Unimatch/gmflow-scale2-mixdata.pth 或 hr16/Unimatch/gmflow-scale1-mixdata.pth
- zoe_depth_anything:可以是 LiheYoung/Depth-Anything/checkpoints_metric_depth/depth_anything_metric_depth_indoor.pt 或 LiheYoung/Depth-Anything/checkpoints_metric_depth/depth_anything_metric_depth_outdoor.pt