Files
Pis7i-COMFYUI-MODELINSTALLER/CONTROLNET_CHARACTER_SWAP_PLAN.md
T
Pishtiwan MoradiandClaude Sonnet 4.5 92e062ff34 Add 15 new models for Wan2.2 video generation workflow
Added models:
- Wan2.2 diffusion models: T2V, Animate 14B, T2V Low Noise
- Wan2.2 LoRAs: Lightning 4-step, Lightx2v, Relight, Distill
- Text encoders: UMT5-XXL (fp8 and bf16 variants)
- CLIP Vision H for Wan workflows
- InsightFace buffalo_l model for face detection
- IP-Adapter Plus SDXL VIT-H
- RealESRGAN x4 upscaler
- Wan 2.1 VAE

Updated file permissions to executable for all Python files and documentation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-09 05:46:56 +02:00

446 lines
16 KiB
Markdown
Executable File

# ControlNet Character Face Swap Node - Implementation Plan
## Concept Overview
Create a ComfyUI node that takes a **reference image** (for pose, clothing, background, scene) and applies a **character's face** from your AI model collection. This lets you place your consistent AI characters into any pose/scene while maintaining their identity.
## Use Case Example
**Input 1:** Reference image of a person sitting at a café (pose + scene)
**Input 2:** Your AI character model/LoRA or reference face image
**Output:** Your character sitting at the café in the same pose
## Technical Approach
### 1. **Multi-ControlNet for Structure Transfer**
Extract structure from reference image:
- **OpenPose** - Body pose and skeleton (PRIMARY - most important)
- **Depth** - Spatial depth and 3D structure
- **Canny Edge** - Sharp outlines and composition
- **Normal Map** - Surface details and lighting direction
- **Softedge** - Softer structural guidance
### 2. **Character Face Application Methods**
#### Option A: LoRA-Based (Best for consistent characters)
- Use character-specific LoRA trained on your AI character
- ControlNets guide pose/scene
- LoRA ensures consistent face/identity
- **Strength:** LoRA weight 0.7-1.0
#### Option B: IP-Adapter FaceID (Best for flexibility)
- Use IP-Adapter with FaceID model
- Input: Reference image structure + Character face reference
- Maintains face identity across different scenes
- **Strength:** IP-Adapter weight 0.8-1.0
#### Option C: Reactor/ReActor Face Swap
- Generate image with ControlNets
- Use face swap to replace generated face with character face
- Most accurate face transfer
- Works with any character reference
### 3. **Recommended Hybrid Approach**
Combine multiple methods for best results:
```
Reference Image (pose/scene)
↓
┌─────────────────────────────────┐
│ ControlNet Preprocessing │
│ - OpenPose skeleton │
│ - Depth map │
│ - Canny edges │
│ - Normal map │
└─────────────────────────────────┘
↓
┌─────────────────────────────────┐
│ Initial Generation │
│ - Base model + Character LoRA │
│ - Guided by ControlNets │
│ - Prompt: character description│
└─────────────────────────────────┘
↓
┌─────────────────────────────────┐
│ Face Identity Reinforcement │
│ Option 1: IP-Adapter FaceID │
│ Option 2: ReActor Face Swap │
│ - Apply character face │
│ - Blend seamlessly │
└─────────────────────────────────┘
↓
Output: Character in reference pose/scene
```
## Node Architecture
### Input Ports
#### Required
1. **reference_image** - Source image for pose/background/scene
2. **model** - Base Stable Diffusion checkpoint
3. **character_face_image** - Your character's face reference
#### Character Method (Choose One)
4. **character_lora** - LoRA file for your character (optional)
5. **lora_strength** - Float (0.0-1.5, default 0.8)
#### ControlNet Settings
6. **pose_strength** - Float (0.0-1.5, default 1.0) - Most important
7. **depth_strength** - Float (0.0-1.5, default 0.7)
8. **canny_strength** - Float (0.0-1.5, default 0.5)
#### Generation Settings
9. **positive_prompt** - Character description + scene details
10. **negative_prompt** - Quality negatives
11. **face_method** - Choice ["IP-Adapter FaceID", "ReActor", "Both"]
12. **face_strength** - Float (0.0-1.0, default 0.85)
13. **seed** - Random seed
#### Optional
14. **preserve_clothes** - Boolean (try to keep reference clothing)
15. **preserve_background** - Boolean (keep original background)
16. **style_prompt** - Override style (anime, realistic, etc.)
### Output Ports
1. **image** - Final generated image
2. **pose_preview** - OpenPose skeleton preview
3. **depth_preview** - Depth map preview
4. **face_mask** - Face region mask (debugging)
## Processing Pipeline
```python
class ControlNetCharacterSwap:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"reference_image": ("IMAGE",),
"character_face": ("IMAGE",),
"model": ("MODEL",),
"positive_prompt": ("STRING", {"multiline": True}),
"pose_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0}),
"face_strength": ("FLOAT", {"default": 0.85, "min": 0.0, "max": 1.0}),
},
"optional": {
"character_lora": ("LORA",),
"lora_strength": ("FLOAT", {"default": 0.8}),
"depth_strength": ("FLOAT", {"default": 0.7}),
"canny_strength": ("FLOAT", {"default": 0.5}),
"face_method": (["IP-Adapter FaceID", "ReActor", "Both"],),
}
}
RETURN_TYPES = ("IMAGE", "IMAGE", "IMAGE", "MASK")
RETURN_NAMES = ("image", "pose_preview", "depth_preview", "face_mask")
FUNCTION = "generate_character"
CATEGORY = "PMA Utils/Character"
def generate_character(self, reference_image, character_face, model,
positive_prompt, pose_strength, face_strength,
character_lora=None, lora_strength=0.8,
depth_strength=0.7, canny_strength=0.5,
face_method="IP-Adapter FaceID"):
# STEP 1: Extract ControlNet Maps
pose_map = openpose_detector(reference_image)
depth_map = depth_estimator(reference_image)
canny_map = canny_detector(reference_image)
# STEP 2: Prepare Model
working_model = model
if character_lora:
working_model = apply_lora(model, character_lora, lora_strength)
# STEP 3: Apply ControlNets
# OpenPose is primary - controls body structure
latent = apply_controlnet(
model=working_model,
controlnet=openpose_controlnet,
image=pose_map,
strength=pose_strength
)
# Depth adds spatial awareness
latent = apply_controlnet(
latent=latent,
controlnet=depth_controlnet,
image=depth_map,
strength=depth_strength
)
# Canny for fine details (lower strength to allow character features)
latent = apply_controlnet(
latent=latent,
controlnet=canny_controlnet,
image=canny_map,
strength=canny_strength
)
# STEP 4: Generate Base Image
generated_image = generate(
latent=latent,
positive=positive_prompt,
negative=negative_prompt,
model=working_model
)
# STEP 5: Apply Character Face
if face_method == "IP-Adapter FaceID":
final_image = apply_ipadapter_faceid(
image=generated_image,
face_reference=character_face,
strength=face_strength
)
elif face_method == "ReActor":
final_image = reactor_face_swap(
target_image=generated_image,
source_face=character_face,
strength=face_strength
)
elif face_method == "Both":
# First IP-Adapter, then ReActor for maximum accuracy
temp_image = apply_ipadapter_faceid(
image=generated_image,
face_reference=character_face,
strength=face_strength * 0.7
)
final_image = reactor_face_swap(
target_image=temp_image,
source_face=character_face,
strength=face_strength
)
# STEP 6: Generate Previews
face_mask = detect_face_mask(final_image)
return (final_image, pose_map, depth_map, face_mask)
```
## Workflow Example
### Basic Workflow
```
┌─────────────────┐
│ Reference Image │ (person at café)
└────────┬────────┘
│
┌────▼─────────────────────┐
│ ControlNet Preprocessors │
│ - OpenPose │
│ - Depth │
│ - Canny │
└────┬─────────────────────┘
│
┌────▼────────────┐ ┌──────────────────┐
│ SD Generation │◄─────┤ Character LoRA │
│ + ControlNets │ └──────────────────┘
└────┬────────────┘
│
┌────▼────────────┐ ┌──────────────────┐
│ IP-Adapter │◄─────┤ Character Face │
│ FaceID │ │ Reference │
└────┬────────────┘ └──────────────────┘
│
┌────▼────────────┐
│ Final Output │ (Your character at café)
└─────────────────┘
```
## Prompt Strategy
### Positive Prompt Template
```
[CHARACTER NAME/DESCRIPTION], [CHARACTER FEATURES],
[REFERENCE SCENE DESCRIPTION], [POSE DESCRIPTION],
[STYLE KEYWORDS], high quality, detailed face, 8k
```
**Example:**
```
Emma, young woman with long brown hair, blue eyes, fair skin,
sitting at outdoor café table, holding coffee cup, relaxed pose,
photorealistic, natural lighting, bokeh background, professional photo
```
### Negative Prompt
```
bad face, deformed, ugly, blurry, low quality, bad anatomy,
extra limbs, wrong proportions, watermark
```
## Required Models & Dependencies
### ControlNet Models (SD 1.5 or SDXL)
- **control_sd15_openpose.pth** - ESSENTIAL
- **control_sd15_depth.pth** - ESSENTIAL
- **control_sd15_canny.pth** - Recommended
- **control_sd15_normal.pth** - Optional
### Face Models
- **IP-Adapter FaceID Plus v2** - For face identity transfer
- Model: `ip-adapter-faceid-plusv2_sdxl.bin`
- CLIP: `clip_vision_SDXL_vit-h.safetensors`
- **ReActor** - For face swapping
- InsightFace models (buffalo_l)
### ComfyUI Custom Nodes
1. **ComfyUI-ControlNet-Aux** - Preprocessors
2. **ComfyUI-IPAdapter-Plus** - IP-Adapter support
3. **ReActor Node** - Face swapping
4. **ComfyUI-Impact-Pack** - Face detection utilities
### Your Character Assets
- **Character LoRAs** - Trained on your AI characters
- **Character Face References** - Clean face shots of each character
## Character Library Management
### Suggested Structure
```
/models/loras/characters/
emma_character.safetensors
john_character.safetensors
sarah_character.safetensors
/inputs/character_faces/
emma_face.png
john_face.png
sarah_face.png
```
### Node Enhancement: Character Selector
Add dropdown to select from saved characters:
```python
"character_preset": (self.get_character_list(),)
def get_character_list(self):
# Scan character directory
return ["Emma", "John", "Sarah", "Custom..."]
```
## Advanced Features
### 1. **Outfit Preservation Mode**
- Extract clothing from reference with segmentation
- Apply clothing ControlNet or inpainting
- Keep character face + reference outfit
### 2. **Background Swapping**
- Segment background from reference
- Replace with custom background
- Keep character + pose
### 3. **Multi-Character Scenes**
- Detect multiple people in reference
- Apply different character faces to each
- Maintain relative positions
### 4. **Expression Transfer**
- Detect facial expression from reference
- Apply expression to character face
- Use expression ControlNet if available
### 5. **Batch Processing**
- Process multiple references with same character
- Generate character pose library
- Automatic prompt generation from reference
## Testing Scenarios
| Scenario | Reference | Character | Expected Result |
|----------|-----------|-----------|-----------------|
| Portrait | Professional headshot | Emma | Emma in professional setting |
| Action | Person jumping | John | John jumping, same pose |
| Group | 3 people at party | Sarah (1 person) | Sarah in same scene/pose |
| Historical | Vintage photo | Emma | Emma in vintage style/setting |
| Fashion | Model on runway | John | John as fashion model |
## Optimization Tips
### For Best Quality
1. **OpenPose Strength:** 0.9-1.2 (maintain pose)
2. **Character LoRA:** 0.7-1.0 (strong character features)
3. **Face Method:** "Both" (IP-Adapter + ReActor)
4. **Resolution:** Match reference or use 1024x1024 for SDXL
### For Speed
1. **Reduce ControlNets:** Use only OpenPose + Depth
2. **Lower Steps:** 20-25 steps sufficient
3. **Skip ReActor:** Use only IP-Adapter FaceID
4. **Batch Process:** Queue multiple generations
### For Consistency Across Images
1. **Use Same LoRA + Weight** for all generations
2. **Use Same Face Reference** image
3. **Lock Seed** for similar variations
4. **Save Workflow** as template
## Common Issues & Solutions
| Problem | Cause | Solution |
|---------|-------|----------|
| Wrong face | Weak face strength | Increase face_strength to 0.9-1.0 |
| Wrong pose | Weak pose ControlNet | Increase pose_strength to 1.2 |
| Blurry face | ControlNet conflict | Lower canny/depth, keep pose high |
| Wrong clothing | Strong clothing from ref | Lower depth_strength, use outfit prompt |
| Background wrong | ControlNets too strong | Lower all except pose, focus prompt on BG |
| Face doesn't match character | LoRA not strong enough | Increase lora_strength or use "Both" face method |
## Implementation Phases
### Phase 1: Core Functionality
- [x] Plan architecture
- [ ] Implement OpenPose ControlNet integration
- [ ] Implement Depth ControlNet integration
- [ ] Basic generation pipeline
### Phase 2: Face Integration
- [ ] IP-Adapter FaceID integration
- [ ] ReActor face swap integration
- [ ] Face blending quality improvements
### Phase 3: LoRA Support
- [ ] Character LoRA loading
- [ ] LoRA strength controls
- [ ] Character library management
### Phase 4: UI/UX
- [ ] Character preset selector
- [ ] Preview outputs for each stage
- [ ] Workflow templates
### Phase 5: Advanced Features
- [ ] Outfit preservation mode
- [ ] Expression transfer
- [ ] Batch processing
## Expected Results
**Quality Metrics:**
- **Face Similarity:** 90%+ match to character reference
- **Pose Accuracy:** 95%+ match to reference pose
- **Scene Coherence:** Natural integration of character into scene
- **Processing Time:** 15-30 seconds per image (RTX 3090)
## Conclusion
This node solves the problem of placing consistent AI characters into arbitrary poses and scenes. By combining ControlNet for structure transfer with face identity models (IP-Adapter/ReActor), you can maintain character consistency while achieving any pose or setting.
**Perfect for:**
- Building character portfolio/lookbooks
- Storytelling with consistent characters
- Virtual fashion/product modeling
- Character-based content creation
- AI influencer content
**Estimated Development Time:** 1-2 weeks
**Complexity:** Medium-High
**Value:** Extremely high for character-based workflows