SuperMakeUpTransfer PM
Borrowing someone's makeup look in one node — SuperMakeUpTransfer PM
- main_image
- makeup_image
- avatar_box
- IMAGE
Some workflows make you earn a look. Want a reference photo's makeup on your face? The old way was a five-node chain: detect the face, crop both images, run the makeup-transfer GAN, resize the result back, and paste it in. SuperMakeUpTransfer PM collapses all of that into a single node - give it your photo and a photo with makeup you like, and out comes your face wearing that makeup. It's the "super" nodes' whole selling point: v1.2.0 added SuperMakeUpTransfer and its sibling SuperColorTransfer precisely so you don't have to wire the EasyPhoto chain by hand.
How it works
Underneath it's PSGAN, a GAN trained for makeup transfer - it doesn't just copy color, it learns to re-apply the reference's makeup structure (lipstick, eye shadow, foundation) onto your facial layout. The node feeds both images into the model's transfer() and then handles all the geometry for you.
The pipeline in the source:
- Crop
main_imageandmakeup_imageto the face region usingavatar_box. - Resize both crops to 256×256 (PSGAN's working resolution).
- Run the transfer.
- Resize the result back to the box's width and height.
- Paste it into a copy of the original image.
It needs three things loaded under the hood: RetinaFace for face detection, the face-skin extractor, and a face-landmarks model - plus the makeup_transfer weights, all of which the pack downloads on first launch into its own models/ folder.
Inputs
main_image(IMAGE) - the face that receives the makeup.makeup_image(IMAGE) - the reference look you're borrowing.avatar_box(BOX, looks optional) - the face region, in(x1, y1, x2, y2). Grab it from PM_RetinaFace'scrop_boxoutput.
Here's the trap that will actually bite you: the schema marks avatar_box as optional, but the shipped code reads its width and height before checking whether it's None. Leave it unconnected and the node dies with a TypeError the moment it runs. Treat it as required and wire in a box from PM_RetinaFace - don't let "optional" fool you.
What to expect
Output is a single IMAGE: the original frame with the transferred makeup pasted over the face region. The rest of the image is untouched, and the transfer only lands where the box points, so both faces should be roughly aligned in size and orientation for believable results. The 256×256 bottleneck means it's not going to add detail - it re-styles what's already there, so start from a clean, decent-resolution face crop.
Installing
ComfyUI Manager (search "ComfyUI-Portrait-Maker") or:
cd ComfyUI/custom_nodes
git clone https://github.com/THtianhao/ComfyUI-Portrait-Maker.git
then restart. This is the heavyweight end of the pack: first launch downloads the entire EasyPhoto model set (controlnet pths, VAE, LoRA, face_skin.pth, inswapper, face_landmarks.pth, makeup_transfer.pth) with no hash verification - don't interrupt it. requirements.txt pulls in modelscope, tensorflow, onnxruntime, insightface, scikit-image and diffusers pinned to 0.18.2.
Common issues
Beyond the fake-optional box, the big one is CUDA. The model holder constructs PSGAN with "cuda" hardcoded as the device - no CUDA, no makeup transfer, so this node effectively requires an NVIDIA setup. Alignment matters too: if the reference's face is a different scale than yours, crop both tighter with the box. And because the face-skin and landmark models load from ModelScope on first run, the first execution can sit on a download for a while - that's normal, not a hang.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| main_image | IMAGE | — | |
| makeup_image | IMAGE | — | |
| avatar_boxopt | BOX | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |