official.ghost.logic commited on
Commit
1160ead
·
0 Parent(s):

Initial commit

Browse files
Files changed (3) hide show
  1. README.md +47 -0
  2. app.py +180 -0
  3. requirements.txt +11 -0
README.md ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Character View Generator
3
+ emoji: 🎭
4
+ colorFrom: purple
5
+ colorTo: blue
6
+ sdk: gradio
7
+ sdk_version: 4.44.0
8
+ app_file: app.py
9
+ pinned: false
10
+ license: mit
11
+ ---
12
+
13
+ # Character View Generator
14
+
15
+ Generate consistent character views from a reference face image using IP-Adapter FaceID Plus.
16
+
17
+ ## API Usage
18
+
19
+ ```python
20
+ from gradio_client import Client
21
+
22
+ client = Client("ghost-logic/character-view-generator")
23
+
24
+ result = client.predict(
25
+ face_image="path/to/face.png",
26
+ view_angle="3/4-right",
27
+ prompt="anime character, blue skin, orange eyes",
28
+ negative_prompt="realistic, photo",
29
+ strength=0.8,
30
+ guidance_scale=5.0,
31
+ num_steps=30,
32
+ seed=42,
33
+ api_name="/generate_view"
34
+ )
35
+ ```
36
+
37
+ ## View Angles
38
+
39
+ - `front` - Direct front view
40
+ - `3/4-left` - Three-quarter view facing left
41
+ - `3/4-right` - Three-quarter view facing right
42
+ - `profile-left` - Full side profile facing left
43
+ - `profile-right` - Full side profile facing right
44
+
45
+ ## For Daggr Integration
46
+
47
+ This space is designed to be called from a daggr pipeline for character sheet generation.
app.py ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ from PIL import Image
4
+ from diffusers import StableDiffusionXLPipeline, ControlNetModel, AutoencoderKL
5
+ from transformers import CLIPVisionModelWithProjection
6
+ import spaces
7
+ import os
8
+ import numpy as np
9
+
10
+ # Pre-defined head rotation angles (pitch, yaw in degrees)
11
+ VIEW_ANGLES = {
12
+ "front": (0, 0),
13
+ "3/4-left": (0, -35),
14
+ "3/4-right": (0, 35),
15
+ "profile-left": (0, -90),
16
+ "profile-right": (0, 90),
17
+ }
18
+
19
+ # Global pipeline (loaded once)
20
+ pipe = None
21
+ ip_adapter = None
22
+
23
+ def load_pipeline():
24
+ """Load the IP-Adapter FaceID Plus pipeline"""
25
+ global pipe
26
+
27
+ if pipe is not None:
28
+ return pipe
29
+
30
+ # Load IP-Adapter FaceID Plus with SDXL
31
+ from diffusers import StableDiffusionXLPipeline
32
+ from diffusers.utils import load_image
33
+
34
+ # Base model - using a good anime-capable SDXL model
35
+ model_id = "stabilityai/stable-diffusion-xl-base-1.0"
36
+
37
+ pipe = StableDiffusionXLPipeline.from_pretrained(
38
+ model_id,
39
+ torch_dtype=torch.float16,
40
+ variant="fp16",
41
+ )
42
+
43
+ # Load IP-Adapter FaceID Plus
44
+ pipe.load_ip_adapter(
45
+ "h94/IP-Adapter-FaceID",
46
+ subfolder=None,
47
+ weight_name="ip-adapter-faceid-plusv2_sdxl.bin",
48
+ image_encoder_folder="models/image_encoder",
49
+ )
50
+
51
+ pipe.set_ip_adapter_scale(0.7)
52
+ pipe.enable_model_cpu_offload()
53
+
54
+ return pipe
55
+
56
+
57
+ @spaces.GPU
58
+ def generate_view(
59
+ face_image: Image.Image,
60
+ view_angle: str,
61
+ prompt: str,
62
+ negative_prompt: str = "",
63
+ strength: float = 0.8,
64
+ guidance_scale: float = 5.0,
65
+ num_steps: int = 30,
66
+ seed: int = 42,
67
+ ) -> Image.Image:
68
+ """
69
+ Generate a character view from a reference face.
70
+
71
+ Args:
72
+ face_image: Reference face image (front view ideally)
73
+ view_angle: One of 'front', '3/4-left', '3/4-right', 'profile-left', 'profile-right'
74
+ prompt: Description of the character/style
75
+ negative_prompt: What to avoid
76
+ strength: IP-Adapter strength (0.0-1.0)
77
+ guidance_scale: CFG scale
78
+ num_steps: Number of inference steps
79
+ seed: Random seed for reproducibility
80
+
81
+ Returns:
82
+ Generated image at the specified angle
83
+ """
84
+
85
+ pipe = load_pipeline()
86
+
87
+ # Add view-specific prompt additions
88
+ angle_prompts = {
89
+ "front": "front view, facing camera, symmetrical",
90
+ "3/4-left": "3/4 view, turned slightly left, three quarter view",
91
+ "3/4-right": "3/4 view, turned slightly right, three quarter view",
92
+ "profile-left": "side profile, facing left, profile view",
93
+ "profile-right": "side profile, facing right, profile view",
94
+ }
95
+
96
+ view_prompt = angle_prompts.get(view_angle, "")
97
+ full_prompt = f"{prompt}, {view_prompt}, portrait, character art, consistent character"
98
+
99
+ default_negative = "deformed, ugly, bad anatomy, blurry, low quality, worst quality, text, watermark"
100
+ full_negative = f"{negative_prompt}, {default_negative}" if negative_prompt else default_negative
101
+
102
+ # Set seed for reproducibility
103
+ generator = torch.Generator(device="cpu").manual_seed(seed)
104
+
105
+ # Generate with IP-Adapter face reference
106
+ result = pipe(
107
+ prompt=full_prompt,
108
+ negative_prompt=full_negative,
109
+ ip_adapter_image=face_image,
110
+ num_inference_steps=num_steps,
111
+ guidance_scale=guidance_scale,
112
+ generator=generator,
113
+ width=1024,
114
+ height=1024,
115
+ )
116
+
117
+ return result.images[0]
118
+
119
+
120
+ # Gradio Interface
121
+ with gr.Blocks(title="Character View Generator") as demo:
122
+ gr.Markdown("""
123
+ # Character View Generator
124
+
125
+ Generate consistent character views from a reference face image.
126
+ Designed for character sheet pipelines.
127
+ """)
128
+
129
+ with gr.Row():
130
+ with gr.Column():
131
+ face_input = gr.Image(label="Reference Face", type="pil")
132
+ view_dropdown = gr.Dropdown(
133
+ choices=list(VIEW_ANGLES.keys()),
134
+ value="front",
135
+ label="Target View Angle"
136
+ )
137
+ prompt_input = gr.Textbox(
138
+ label="Prompt",
139
+ placeholder="anime character, blue skin, orange eyes...",
140
+ lines=2
141
+ )
142
+ negative_input = gr.Textbox(
143
+ label="Negative Prompt (optional)",
144
+ placeholder="realistic, photo...",
145
+ lines=2
146
+ )
147
+
148
+ with gr.Row():
149
+ strength_slider = gr.Slider(0.0, 1.0, value=0.8, label="Identity Strength")
150
+ guidance_slider = gr.Slider(1.0, 20.0, value=5.0, label="Guidance Scale")
151
+
152
+ with gr.Row():
153
+ steps_slider = gr.Slider(10, 50, value=30, step=1, label="Steps")
154
+ seed_input = gr.Number(value=42, label="Seed", precision=0)
155
+
156
+ generate_btn = gr.Button("Generate View", variant="primary")
157
+
158
+ with gr.Column():
159
+ output_image = gr.Image(label="Generated View")
160
+
161
+ generate_btn.click(
162
+ fn=generate_view,
163
+ inputs=[
164
+ face_input,
165
+ view_dropdown,
166
+ prompt_input,
167
+ negative_input,
168
+ strength_slider,
169
+ guidance_slider,
170
+ steps_slider,
171
+ seed_input,
172
+ ],
173
+ outputs=output_image,
174
+ api_name="generate_view" # Enables API access
175
+ )
176
+
177
+
178
+ if __name__ == "__main__":
179
+ demo.queue(api_open=True)
180
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ torch
2
+ diffusers>=0.25.0
3
+ transformers
4
+ accelerate
5
+ safetensors
6
+ gradio
7
+ Pillow
8
+ numpy
9
+ spaces
10
+ insightface
11
+ onnxruntime-gpu