Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,154 +1,1084 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
import numpy as np
|
| 3 |
import random
|
| 4 |
-
|
| 5 |
-
# import spaces #[uncomment to use ZeroGPU]
|
| 6 |
-
from diffusers import DiffusionPipeline
|
| 7 |
import torch
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
device = "cuda" if torch.cuda.is_available() else "cpu"
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
-
if torch.cuda.is_available():
|
| 13 |
-
torch_dtype = torch.float16
|
| 14 |
-
else:
|
| 15 |
-
torch_dtype = torch.float32
|
| 16 |
|
| 17 |
-
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
|
| 20 |
-
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
|
| 24 |
-
# @spaces.GPU #[uncomment to use ZeroGPU]
|
| 25 |
def infer(
|
| 26 |
prompt,
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
seed,
|
| 29 |
randomize_seed,
|
| 30 |
width,
|
| 31 |
height,
|
| 32 |
guidance_scale,
|
| 33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
progress=gr.Progress(track_tqdm=True),
|
| 35 |
):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
if randomize_seed:
|
| 37 |
seed = random.randint(0, MAX_SEED)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
|
| 39 |
-
generator = torch.Generator().manual_seed(seed)
|
| 40 |
-
|
| 41 |
-
image = pipe(
|
| 42 |
-
prompt=prompt,
|
| 43 |
-
negative_prompt=negative_prompt,
|
| 44 |
-
guidance_scale=guidance_scale,
|
| 45 |
-
num_inference_steps=num_inference_steps,
|
| 46 |
-
width=width,
|
| 47 |
-
height=height,
|
| 48 |
-
generator=generator,
|
| 49 |
-
).images[0]
|
| 50 |
-
|
| 51 |
-
return image, seed
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
examples = [
|
| 55 |
-
"Astronaut in a jungle, cold color palette, muted colors, detailed, 8k",
|
| 56 |
-
"An astronaut riding a green horse",
|
| 57 |
-
"A delicious ceviche cheesecake slice",
|
| 58 |
-
]
|
| 59 |
|
|
|
|
| 60 |
css = """
|
| 61 |
-
#col-container {
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
}
|
| 65 |
"""
|
| 66 |
|
| 67 |
-
with gr.Blocks(css=css) as demo:
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
with gr.Accordion("Advanced Settings", open=False):
|
| 85 |
-
negative_prompt = gr.Text(
|
| 86 |
-
label="Negative prompt",
|
| 87 |
-
max_lines=1,
|
| 88 |
-
placeholder="Enter a negative prompt",
|
| 89 |
-
visible=False,
|
| 90 |
-
)
|
| 91 |
-
|
| 92 |
-
seed = gr.Slider(
|
| 93 |
-
label="Seed",
|
| 94 |
-
minimum=0,
|
| 95 |
-
maximum=MAX_SEED,
|
| 96 |
-
step=1,
|
| 97 |
-
value=0,
|
| 98 |
-
)
|
| 99 |
-
|
| 100 |
-
randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
|
| 101 |
-
|
| 102 |
with gr.Row():
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
with gr.Row():
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
value=0.0, # Replace with defaults that work for your model
|
| 126 |
)
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 134 |
)
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
fn=infer,
|
| 140 |
inputs=[
|
| 141 |
-
prompt,
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
width,
|
| 146 |
-
|
| 147 |
-
guidance_scale,
|
| 148 |
-
num_inference_steps,
|
| 149 |
],
|
| 150 |
-
outputs=[result,
|
| 151 |
)
|
| 152 |
|
| 153 |
if __name__ == "__main__":
|
| 154 |
-
demo.launch(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import numpy as np
|
| 3 |
import random
|
| 4 |
+
from PIL import Image
|
|
|
|
|
|
|
| 5 |
import torch
|
| 6 |
+
import cv2
|
| 7 |
+
from diffusers import (
|
| 8 |
+
FluxPipeline,
|
| 9 |
+
AutoPipelineForImage2Image,
|
| 10 |
+
StableDiffusionXLControlNetPipeline,
|
| 11 |
+
StableDiffusionXLImg2ImgPipeline,
|
| 12 |
+
StableDiffusionXLInpaintPipeline,
|
| 13 |
+
ControlNetModel,
|
| 14 |
+
DPMSolverMultistepScheduler,
|
| 15 |
+
EulerAncestralDiscreteScheduler,
|
| 16 |
+
DDIMScheduler,
|
| 17 |
+
)
|
| 18 |
+
from diffusers.models import AutoencoderKL
|
| 19 |
+
from transformers import CLIPVisionModelWithProjection
|
| 20 |
+
from controlnet_aux import (
|
| 21 |
+
CannyDetector,
|
| 22 |
+
OpenposeDetector,
|
| 23 |
+
MidasDetector,
|
| 24 |
+
LineartDetector,
|
| 25 |
+
HEDdetector,
|
| 26 |
+
)
|
| 27 |
+
from insightface.app import FaceAnalysis
|
| 28 |
+
import basicsr
|
| 29 |
+
from basicsr.archs.rrdbnet_arch import RRDBNet
|
| 30 |
+
from realesrgan import RealESRGANer
|
| 31 |
+
from gfpgan import GFPGANer
|
| 32 |
|
| 33 |
device = "cuda" if torch.cuda.is_available() else "cpu"
|
| 34 |
+
torch_dtype = torch.float16 if torch.cuda.is_available() else torch.float32
|
| 35 |
+
|
| 36 |
+
print("🚀 Inicializando IA Studio Ultimate...")
|
| 37 |
+
|
| 38 |
+
# ===== MODELOS BASE =====
|
| 39 |
+
MODELS = {
|
| 40 |
+
"FLUX.1-dev (Melhor)": "black-forest-labs/FLUX.1-dev",
|
| 41 |
+
"FLUX.1-schnell (Rápido)": "black-forest-labs/FLUX.1-schnell",
|
| 42 |
+
"SDXL-Base": "stabilityai/stable-diffusion-xl-base-1.0",
|
| 43 |
+
"SDXL-Turbo (Ultra Rápido)": "stabilityai/sdxl-turbo",
|
| 44 |
+
"RealVisXL (Hiper-Realista)": "SG161222/RealVisXL_V4.0",
|
| 45 |
+
"DreamShaper XL": "Lykon/dreamshaper-xl-1-0",
|
| 46 |
+
"Juggernaut XL": "RunDiffusion/Juggernaut-XL-v9",
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
# ===== CONTROLNET MODELS =====
|
| 50 |
+
CONTROLNET_MODELS = {
|
| 51 |
+
"Canny (Contornos)": "diffusers/controlnet-canny-sdxl-1.0",
|
| 52 |
+
"Depth (Profundidade)": "diffusers/controlnet-depth-sdxl-1.0",
|
| 53 |
+
"OpenPose (Pose)": "thibaud/controlnet-openpose-sdxl-1.0",
|
| 54 |
+
"Lineart (Desenho)": "controlnet-lineart-sdxl-1.0",
|
| 55 |
+
"Soft Edge (Bordas)": "SargeZT/controlnet-sd-xl-1.0-softedge-dexined",
|
| 56 |
+
"Tile (Upscale)": "xinsir/controlnet-tile-sdxl-1.0",
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
# Cache global
|
| 60 |
+
model_cache = {}
|
| 61 |
+
controlnet_cache = {}
|
| 62 |
+
preprocessor_cache = {}
|
| 63 |
+
ip_adapter_cache = {}
|
| 64 |
+
face_analyzer = None
|
| 65 |
+
upscaler = None
|
| 66 |
+
face_enhancer = None
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def init_face_analyzer():
|
| 70 |
+
"""Inicializa FaceAnalysis para IP-Adapter Face"""
|
| 71 |
+
global face_analyzer
|
| 72 |
+
if face_analyzer is None:
|
| 73 |
+
try:
|
| 74 |
+
face_analyzer = FaceAnalysis(name='buffalo_l', providers=['CUDAExecutionProvider', 'CPUExecutionProvider'])
|
| 75 |
+
face_analyzer.prepare(ctx_id=0, det_size=(640, 640))
|
| 76 |
+
print("✓ Face Analyzer carregado")
|
| 77 |
+
except Exception as e:
|
| 78 |
+
print(f"⚠️ Face Analyzer não disponível: {e}")
|
| 79 |
+
return face_analyzer
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def init_upscaler():
|
| 83 |
+
"""Inicializa RealESRGAN para upscaling"""
|
| 84 |
+
global upscaler
|
| 85 |
+
if upscaler is None:
|
| 86 |
+
try:
|
| 87 |
+
model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=4)
|
| 88 |
+
upscaler = RealESRGANer(
|
| 89 |
+
scale=4,
|
| 90 |
+
model_path='https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth',
|
| 91 |
+
model=model,
|
| 92 |
+
tile=512,
|
| 93 |
+
tile_pad=10,
|
| 94 |
+
pre_pad=0,
|
| 95 |
+
half=True if torch.cuda.is_available() else False
|
| 96 |
+
)
|
| 97 |
+
print("✓ RealESRGAN carregado")
|
| 98 |
+
except Exception as e:
|
| 99 |
+
print(f"⚠️ Upscaler não disponível: {e}")
|
| 100 |
+
return upscaler
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
def init_face_enhancer():
|
| 104 |
+
"""Inicializa GFPGAN para correção de rostos"""
|
| 105 |
+
global face_enhancer
|
| 106 |
+
if face_enhancer is None:
|
| 107 |
+
try:
|
| 108 |
+
face_enhancer = GFPGANer(
|
| 109 |
+
model_path='https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth',
|
| 110 |
+
upscale=2,
|
| 111 |
+
arch='clean',
|
| 112 |
+
channel_multiplier=2,
|
| 113 |
+
bg_upsampler=init_upscaler()
|
| 114 |
+
)
|
| 115 |
+
print("✓ GFPGAN carregado")
|
| 116 |
+
except Exception as e:
|
| 117 |
+
print(f"⚠️ Face Enhancer não disponível: {e}")
|
| 118 |
+
return face_enhancer
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
def get_preprocessor(control_type):
|
| 122 |
+
"""Carrega preprocessadores ControlNet"""
|
| 123 |
+
if control_type in preprocessor_cache:
|
| 124 |
+
return preprocessor_cache[control_type]
|
| 125 |
+
|
| 126 |
+
try:
|
| 127 |
+
if control_type == "Canny (Contornos)":
|
| 128 |
+
preprocessor = CannyDetector()
|
| 129 |
+
elif control_type == "Depth (Profundidade)":
|
| 130 |
+
preprocessor = MidasDetector.from_pretrained("lllyasviel/Annotators")
|
| 131 |
+
elif control_type == "OpenPose (Pose)":
|
| 132 |
+
preprocessor = OpenposeDetector.from_pretrained("lllyasviel/Annotators")
|
| 133 |
+
elif control_type == "Lineart (Desenho)":
|
| 134 |
+
preprocessor = LineartDetector.from_pretrained("lllyasviel/Annotators")
|
| 135 |
+
elif control_type == "Soft Edge (Bordas)":
|
| 136 |
+
preprocessor = HEDdetector.from_pretrained("lllyasviel/Annotators")
|
| 137 |
+
else:
|
| 138 |
+
return None
|
| 139 |
+
|
| 140 |
+
preprocessor_cache[control_type] = preprocessor
|
| 141 |
+
return preprocessor
|
| 142 |
+
except Exception as e:
|
| 143 |
+
print(f"⚠️ Erro ao carregar preprocessor: {e}")
|
| 144 |
+
return None
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def preprocess_controlnet_image(image, control_type, canny_low=100, canny_high=200):
|
| 148 |
+
"""Processa imagem para ControlNet"""
|
| 149 |
+
if control_type == "Nenhum" or image is None:
|
| 150 |
+
return None
|
| 151 |
+
|
| 152 |
+
preprocessor = get_preprocessor(control_type)
|
| 153 |
+
if not preprocessor:
|
| 154 |
+
return None
|
| 155 |
+
|
| 156 |
+
try:
|
| 157 |
+
if control_type == "Canny (Contornos)":
|
| 158 |
+
control_image = preprocessor(image, low_threshold=canny_low, high_threshold=canny_high)
|
| 159 |
+
else:
|
| 160 |
+
control_image = preprocessor(image)
|
| 161 |
+
return control_image
|
| 162 |
+
except Exception as e:
|
| 163 |
+
print(f"⚠️ Erro no preprocessamento: {e}")
|
| 164 |
+
return None
|
| 165 |
+
|
| 166 |
+
|
| 167 |
+
def load_ip_adapter(pipe, adapter_type="plus"):
|
| 168 |
+
"""Carrega IP-Adapter para condicionamento por imagem"""
|
| 169 |
+
try:
|
| 170 |
+
if adapter_type == "plus":
|
| 171 |
+
pipe.load_ip_adapter("h94/IP-Adapter", subfolder="sdxl_models", weight_name="ip-adapter-plus_sdxl_vit-h.safetensors")
|
| 172 |
+
elif adapter_type == "plus-face":
|
| 173 |
+
pipe.load_ip_adapter("h94/IP-Adapter", subfolder="sdxl_models", weight_name="ip-adapter-plus-face_sdxl_vit-h.safetensors")
|
| 174 |
+
pipe.set_ip_adapter_scale(0.6)
|
| 175 |
+
print(f"✓ IP-Adapter {adapter_type} carregado")
|
| 176 |
+
return True
|
| 177 |
+
except Exception as e:
|
| 178 |
+
print(f"⚠️ IP-Adapter não disponível: {e}")
|
| 179 |
+
return False
|
| 180 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 181 |
|
| 182 |
+
def load_model(model_name, use_controlnet=False, controlnet_type="Nenhum", use_ip_adapter=False, ip_adapter_type="plus"):
|
| 183 |
+
"""Carrega modelo com todos os componentes"""
|
| 184 |
+
cache_key = f"{model_name}_{controlnet_type}_{ip_adapter_type if use_ip_adapter else 'no-ip'}"
|
| 185 |
+
|
| 186 |
+
if cache_key in model_cache:
|
| 187 |
+
print(f"✓ Cache hit: {cache_key}")
|
| 188 |
+
return model_cache[cache_key]
|
| 189 |
+
|
| 190 |
+
print(f"⏳ Carregando: {cache_key}")
|
| 191 |
+
model_id = MODELS[model_name]
|
| 192 |
+
|
| 193 |
+
try:
|
| 194 |
+
# VAE melhorado para SDXL
|
| 195 |
+
vae = None
|
| 196 |
+
if "FLUX" not in model_name:
|
| 197 |
+
try:
|
| 198 |
+
vae = AutoencoderKL.from_pretrained(
|
| 199 |
+
"madebyollin/sdxl-vae-fp16-fix",
|
| 200 |
+
torch_dtype=torch_dtype
|
| 201 |
+
).to(device)
|
| 202 |
+
print("✓ VAE otimizado carregado")
|
| 203 |
+
except:
|
| 204 |
+
pass
|
| 205 |
+
|
| 206 |
+
# FLUX (sem ControlNet/IP-Adapter ainda)
|
| 207 |
+
if "FLUX" in model_name:
|
| 208 |
+
pipe_txt2img = FluxPipeline.from_pretrained(
|
| 209 |
+
model_id,
|
| 210 |
+
torch_dtype=torch_dtype,
|
| 211 |
+
).to(device)
|
| 212 |
+
|
| 213 |
+
pipe_img2img = AutoPipelineForImage2Image.from_pretrained(
|
| 214 |
+
model_id,
|
| 215 |
+
torch_dtype=torch_dtype,
|
| 216 |
+
).to(device)
|
| 217 |
+
|
| 218 |
+
pipe_controlnet = None
|
| 219 |
+
pipe_inpaint = None
|
| 220 |
+
|
| 221 |
+
# SDXL com todos os recursos
|
| 222 |
+
else:
|
| 223 |
+
from diffusers import StableDiffusionXLPipeline
|
| 224 |
+
|
| 225 |
+
base_args = {
|
| 226 |
+
"torch_dtype": torch_dtype,
|
| 227 |
+
"variant": "fp16",
|
| 228 |
+
"use_safetensors": True,
|
| 229 |
+
}
|
| 230 |
+
if vae:
|
| 231 |
+
base_args["vae"] = vae
|
| 232 |
+
|
| 233 |
+
# ControlNet Pipeline
|
| 234 |
+
if use_controlnet and controlnet_type != "Nenhum":
|
| 235 |
+
try:
|
| 236 |
+
controlnet_id = CONTROLNET_MODELS[controlnet_type]
|
| 237 |
+
controlnet = ControlNetModel.from_pretrained(
|
| 238 |
+
controlnet_id,
|
| 239 |
+
torch_dtype=torch_dtype,
|
| 240 |
+
).to(device)
|
| 241 |
+
|
| 242 |
+
pipe_controlnet = StableDiffusionXLControlNetPipeline.from_pretrained(
|
| 243 |
+
model_id,
|
| 244 |
+
controlnet=controlnet,
|
| 245 |
+
**base_args
|
| 246 |
+
).to(device)
|
| 247 |
+
print(f"✓ ControlNet {controlnet_type} carregado")
|
| 248 |
+
except Exception as e:
|
| 249 |
+
print(f"⚠️ ControlNet error: {e}")
|
| 250 |
+
pipe_controlnet = None
|
| 251 |
+
else:
|
| 252 |
+
pipe_controlnet = None
|
| 253 |
+
|
| 254 |
+
# Base pipelines
|
| 255 |
+
pipe_txt2img = StableDiffusionXLPipeline.from_pretrained(
|
| 256 |
+
model_id,
|
| 257 |
+
**base_args
|
| 258 |
+
).to(device)
|
| 259 |
+
|
| 260 |
+
pipe_img2img = StableDiffusionXLImg2ImgPipeline.from_pretrained(
|
| 261 |
+
model_id,
|
| 262 |
+
**base_args
|
| 263 |
+
).to(device)
|
| 264 |
+
|
| 265 |
+
pipe_inpaint = StableDiffusionXLInpaintPipeline.from_pretrained(
|
| 266 |
+
model_id,
|
| 267 |
+
**base_args
|
| 268 |
+
).to(device)
|
| 269 |
+
|
| 270 |
+
# IP-Adapter
|
| 271 |
+
if use_ip_adapter:
|
| 272 |
+
load_ip_adapter(pipe_txt2img, ip_adapter_type)
|
| 273 |
+
load_ip_adapter(pipe_img2img, ip_adapter_type)
|
| 274 |
+
|
| 275 |
+
# Otimizações máximas para 18GB
|
| 276 |
+
if torch.cuda.is_available():
|
| 277 |
+
for pipe in [pipe_txt2img, pipe_img2img, pipe_controlnet, pipe_inpaint]:
|
| 278 |
+
if pipe:
|
| 279 |
+
try:
|
| 280 |
+
pipe.enable_xformers_memory_efficient_attention()
|
| 281 |
+
pipe.enable_vae_slicing()
|
| 282 |
+
pipe.enable_vae_tiling()
|
| 283 |
+
if hasattr(pipe, 'enable_attention_slicing'):
|
| 284 |
+
pipe.enable_attention_slicing(1)
|
| 285 |
+
# Compila modelo para velocidade
|
| 286 |
+
if torch.__version__ >= "2.0":
|
| 287 |
+
pipe.unet = torch.compile(pipe.unet, mode="reduce-overhead", fullgraph=True)
|
| 288 |
+
except Exception as e:
|
| 289 |
+
print(f"⚠️ Otimização parcial: {e}")
|
| 290 |
+
|
| 291 |
+
pipes = (pipe_txt2img, pipe_img2img, pipe_controlnet, pipe_inpaint)
|
| 292 |
+
model_cache[cache_key] = pipes
|
| 293 |
+
|
| 294 |
+
return pipes
|
| 295 |
+
|
| 296 |
+
except Exception as e:
|
| 297 |
+
print(f"❌ Erro ao carregar modelo: {e}")
|
| 298 |
+
return None, None, None, None
|
| 299 |
|
| 300 |
+
|
| 301 |
+
def enhance_prompt(prompt, style_preset, quality_boost):
|
| 302 |
+
"""Sistema avançado de prompt engineering"""
|
| 303 |
+
|
| 304 |
+
style_enhancers = {
|
| 305 |
+
"Fotorrealista Ultra": "photorealistic, 8k uhd, dslr, soft lighting, high quality, film grain, Fujifilm XT3, natural skin texture, sharp focus",
|
| 306 |
+
"Fantasia Épica": "epic fantasy art, dramatic lighting, mystical atmosphere, detailed textures, concept art, matte painting, trending on artstation, cinematic",
|
| 307 |
+
"Anime Studio": "anime masterpiece, studio quality, vibrant colors, detailed, official art, pixiv trending, makoto shinkai style",
|
| 308 |
+
"Cinematográfico": "cinematic shot, film grain, depth of field, bokeh, anamorphic lens, dramatic lighting, movie still, 35mm photograph",
|
| 309 |
+
"Pintura Digital Pro": "digital painting, highly detailed, artstation hq, concept art, smooth, sharp focus, illustration, art by artgerm and greg rutkowski",
|
| 310 |
+
"3D Render Premium": "3d render, octane render, unreal engine 5, ray tracing, global illumination, subsurface scattering, physically based rendering",
|
| 311 |
+
"Hiper-Realista": "hyperrealistic, ultra detailed, 16k resolution, professional photography, intricate details, lifelike, award winning",
|
| 312 |
+
"RPG Character Art": "rpg character portrait, d&d art style, detailed armor and clothing, fantasy setting, character sheet quality",
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
quality_tags = {
|
| 316 |
+
"Máxima": "masterpiece, best quality, ultra detailed, 8k, professional, sharp focus, vivid colors, perfect composition",
|
| 317 |
+
"Alta": "high quality, detailed, well composed, sharp, vibrant",
|
| 318 |
+
"Normal": "good quality, clear",
|
| 319 |
+
"Desativado": "",
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
negative_presets = {
|
| 323 |
+
"Padrão": "blurry, low quality, distorted, ugly, bad anatomy, watermark, signature",
|
| 324 |
+
"Forte": "blurry, low quality, distorted, ugly, bad anatomy, bad proportions, watermark, low res, mutated, deformed, worst quality, out of focus, jpeg artifacts, text",
|
| 325 |
+
"Máximo": "blurry, low quality, distorted, ugly, bad anatomy, bad proportions, watermark, low res, mutated, deformed, worst quality, out of focus, jpeg artifacts, text, signature, username, amateur, poorly drawn, bad hands, extra limbs, missing limbs, duplicate, clone, bad face, bad eyes, bad teeth",
|
| 326 |
+
"Ultra (Anti-IA)": "blurry, low quality, distorted, ugly, bad anatomy, bad proportions, watermark, low res, mutated, deformed, worst quality, out of focus, jpeg artifacts, text, signature, username, amateur, poorly drawn, bad hands, extra limbs, missing limbs, duplicate, clone, bad face, bad eyes, bad teeth, artificial, synthetic, generated look, uncanny valley, plastic skin",
|
| 327 |
+
}
|
| 328 |
+
|
| 329 |
+
enhanced = prompt
|
| 330 |
+
|
| 331 |
+
# Adiciona tags de qualidade
|
| 332 |
+
if quality_boost != "Desativado":
|
| 333 |
+
enhanced = f"{quality_tags[quality_boost]}, {prompt}"
|
| 334 |
+
|
| 335 |
+
# Adiciona estilo
|
| 336 |
+
if style_preset in style_enhancers:
|
| 337 |
+
enhanced = f"{enhanced}, {style_enhancers[style_preset]}"
|
| 338 |
+
|
| 339 |
+
return enhanced
|
| 340 |
+
|
| 341 |
+
|
| 342 |
+
def post_process_image(image, upscale_factor, enhance_faces, denoise_strength):
|
| 343 |
+
"""Pós-processamento com upscaling e correção"""
|
| 344 |
+
try:
|
| 345 |
+
# Upscaling
|
| 346 |
+
if upscale_factor > 1:
|
| 347 |
+
upscaler_model = init_upscaler()
|
| 348 |
+
if upscaler_model:
|
| 349 |
+
img_array = np.array(image)
|
| 350 |
+
output, _ = upscaler_model.enhance(img_array, outscale=upscale_factor)
|
| 351 |
+
image = Image.fromarray(output)
|
| 352 |
+
print(f"✓ Upscaled {upscale_factor}x")
|
| 353 |
+
|
| 354 |
+
# Face enhancement
|
| 355 |
+
if enhance_faces:
|
| 356 |
+
enhancer = init_face_enhancer()
|
| 357 |
+
if enhancer:
|
| 358 |
+
img_array = np.array(image)
|
| 359 |
+
_, _, output = enhancer.enhance(img_array, has_aligned=False, only_center_face=False, paste_back=True)
|
| 360 |
+
image = Image.fromarray(output)
|
| 361 |
+
print("✓ Faces enhanced")
|
| 362 |
+
|
| 363 |
+
return image
|
| 364 |
+
|
| 365 |
+
except Exception as e:
|
| 366 |
+
print(f"⚠️ Post-processing error: {e}")
|
| 367 |
+
return image
|
| 368 |
|
| 369 |
|
|
|
|
| 370 |
def infer(
|
| 371 |
prompt,
|
| 372 |
+
input_image,
|
| 373 |
+
ip_reference_image,
|
| 374 |
+
use_controlnet,
|
| 375 |
+
controlnet_type,
|
| 376 |
+
controlnet_strength,
|
| 377 |
+
canny_low,
|
| 378 |
+
canny_high,
|
| 379 |
+
use_ip_adapter,
|
| 380 |
+
ip_adapter_type,
|
| 381 |
+
ip_adapter_strength,
|
| 382 |
+
model_choice,
|
| 383 |
+
style_preset,
|
| 384 |
+
quality_boost,
|
| 385 |
+
negative_preset,
|
| 386 |
+
custom_negative,
|
| 387 |
seed,
|
| 388 |
randomize_seed,
|
| 389 |
width,
|
| 390 |
height,
|
| 391 |
guidance_scale,
|
| 392 |
+
num_steps,
|
| 393 |
+
strength,
|
| 394 |
+
scheduler_type,
|
| 395 |
+
upscale_factor,
|
| 396 |
+
enhance_faces,
|
| 397 |
+
denoise_strength,
|
| 398 |
progress=gr.Progress(track_tqdm=True),
|
| 399 |
):
|
| 400 |
+
"""Função principal ULTRA com todos os recursos"""
|
| 401 |
+
|
| 402 |
+
if not prompt or prompt.strip() == "":
|
| 403 |
+
return None, None, None, seed
|
| 404 |
+
|
| 405 |
if randomize_seed:
|
| 406 |
seed = random.randint(0, MAX_SEED)
|
| 407 |
+
|
| 408 |
+
generator = torch.Generator(device=device).manual_seed(seed)
|
| 409 |
+
|
| 410 |
+
# Enhance prompt
|
| 411 |
+
enhanced_prompt = enhance_prompt(prompt, style_preset, quality_boost)
|
| 412 |
+
|
| 413 |
+
# Negative prompt
|
| 414 |
+
negative_presets_dict = {
|
| 415 |
+
"Padrão": "blurry, low quality, distorted, ugly, bad anatomy, watermark, signature",
|
| 416 |
+
"Forte": "blurry, low quality, distorted, ugly, bad anatomy, bad proportions, watermark, low res, mutated, deformed, worst quality, out of focus, jpeg artifacts, text",
|
| 417 |
+
"Máximo": "blurry, low quality, distorted, ugly, bad anatomy, bad proportions, watermark, low res, mutated, deformed, worst quality, out of focus, jpeg artifacts, text, signature, username, amateur, poorly drawn, bad hands, extra limbs, missing limbs, duplicate, clone, bad face, bad eyes, bad teeth",
|
| 418 |
+
"Ultra (Anti-IA)": "blurry, low quality, distorted, ugly, bad anatomy, bad proportions, watermark, low res, mutated, deformed, worst quality, out of focus, jpeg artifacts, text, signature, username, amateur, poorly drawn, bad hands, extra limbs, missing limbs, duplicate, clone, bad face, bad eyes, bad teeth, artificial, synthetic, generated look, uncanny valley, plastic skin",
|
| 419 |
+
"Personalizado": custom_negative,
|
| 420 |
+
}
|
| 421 |
+
final_negative = negative_presets_dict.get(negative_preset, "")
|
| 422 |
+
|
| 423 |
+
# Carrega modelo
|
| 424 |
+
progress(0.1, "Carregando modelo...")
|
| 425 |
+
pipes = load_model(model_choice, use_controlnet, controlnet_type, use_ip_adapter, ip_adapter_type)
|
| 426 |
+
if not pipes or pipes[0] is None:
|
| 427 |
+
return None, None, None, seed
|
| 428 |
+
|
| 429 |
+
pipe_txt2img, pipe_img2img, pipe_controlnet, pipe_inpaint = pipes
|
| 430 |
+
|
| 431 |
+
# Configura scheduler
|
| 432 |
+
scheduler_map = {
|
| 433 |
+
"DPM++ 2M": DPMSolverMultistepScheduler,
|
| 434 |
+
"Euler a": EulerAncestralDiscreteScheduler,
|
| 435 |
+
"DDIM": DDIMScheduler,
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
if scheduler_type in scheduler_map and "FLUX" not in model_choice:
|
| 439 |
+
scheduler_class = scheduler_map[scheduler_type]
|
| 440 |
+
for pipe in [pipe_txt2img, pipe_img2img, pipe_controlnet]:
|
| 441 |
+
if pipe:
|
| 442 |
+
pipe.scheduler = scheduler_class.from_config(pipe.scheduler.config)
|
| 443 |
+
|
| 444 |
+
try:
|
| 445 |
+
control_image_preview = None
|
| 446 |
+
image = None
|
| 447 |
+
|
| 448 |
+
# Modo ControlNet
|
| 449 |
+
if use_controlnet and controlnet_type != "Nenhum" and input_image is not None and pipe_controlnet:
|
| 450 |
+
progress(0.2, "Processando ControlNet...")
|
| 451 |
+
control_image = preprocess_controlnet_image(input_image, controlnet_type, canny_low, canny_high)
|
| 452 |
+
control_image_preview = control_image
|
| 453 |
+
|
| 454 |
+
if control_image:
|
| 455 |
+
progress(0.4, "Gerando com ControlNet...")
|
| 456 |
+
|
| 457 |
+
gen_args = {
|
| 458 |
+
"prompt": enhanced_prompt,
|
| 459 |
+
"negative_prompt": final_negative,
|
| 460 |
+
"image": control_image,
|
| 461 |
+
"controlnet_conditioning_scale": controlnet_strength,
|
| 462 |
+
"guidance_scale": guidance_scale,
|
| 463 |
+
"num_inference_steps": num_steps,
|
| 464 |
+
"width": width,
|
| 465 |
+
"height": height,
|
| 466 |
+
"generator": generator,
|
| 467 |
+
}
|
| 468 |
+
|
| 469 |
+
# IP-Adapter com ControlNet
|
| 470 |
+
if use_ip_adapter and ip_reference_image:
|
| 471 |
+
gen_args["ip_adapter_image"] = ip_reference_image
|
| 472 |
+
pipe_controlnet.set_ip_adapter_scale(ip_adapter_strength)
|
| 473 |
+
|
| 474 |
+
image = pipe_controlnet(**gen_args).images[0]
|
| 475 |
+
|
| 476 |
+
# Modo Image-to-Image
|
| 477 |
+
elif input_image is not None:
|
| 478 |
+
progress(0.3, "Gerando img2img...")
|
| 479 |
+
input_image_resized = input_image.resize((width, height), Image.LANCZOS)
|
| 480 |
+
|
| 481 |
+
gen_args = {
|
| 482 |
+
"prompt": enhanced_prompt,
|
| 483 |
+
"negative_prompt": final_negative,
|
| 484 |
+
"image": input_image_resized,
|
| 485 |
+
"strength": strength,
|
| 486 |
+
"guidance_scale": guidance_scale,
|
| 487 |
+
"num_inference_steps": num_steps,
|
| 488 |
+
"generator": generator,
|
| 489 |
+
}
|
| 490 |
+
|
| 491 |
+
# IP-Adapter com img2img
|
| 492 |
+
if use_ip_adapter and ip_reference_image:
|
| 493 |
+
gen_args["ip_adapter_image"] = ip_reference_image
|
| 494 |
+
pipe_img2img.set_ip_adapter_scale(ip_adapter_strength)
|
| 495 |
+
|
| 496 |
+
image = pipe_img2img(**gen_args).images[0]
|
| 497 |
+
|
| 498 |
+
# Modo Text-to-Image
|
| 499 |
+
else:
|
| 500 |
+
progress(0.3, "Gerando do zero...")
|
| 501 |
+
|
| 502 |
+
gen_args = {
|
| 503 |
+
"prompt": enhanced_prompt,
|
| 504 |
+
"negative_prompt": final_negative,
|
| 505 |
+
"guidance_scale": guidance_scale,
|
| 506 |
+
"num_inference_steps": num_steps,
|
| 507 |
+
"width": width,
|
| 508 |
+
"height": height,
|
| 509 |
+
"generator": generator,
|
| 510 |
+
}
|
| 511 |
+
|
| 512 |
+
# IP-Adapter com txt2img
|
| 513 |
+
if use_ip_adapter and ip_reference_image:
|
| 514 |
+
gen_args["ip_adapter_image"] = ip_reference_image
|
| 515 |
+
pipe_txt2img.set_ip_adapter_scale(ip_adapter_strength)
|
| 516 |
+
|
| 517 |
+
image = pipe_txt2img(**gen_args).images[0]
|
| 518 |
+
|
| 519 |
+
# Pós-processamento
|
| 520 |
+
if image and (upscale_factor > 1 or enhance_faces):
|
| 521 |
+
progress(0.9, "Pós-processamento...")
|
| 522 |
+
image = post_process_image(image, upscale_factor, enhance_faces, denoise_strength)
|
| 523 |
+
|
| 524 |
+
progress(1.0, "✓ Concluído!")
|
| 525 |
+
return image, control_image_preview, enhanced_prompt, seed
|
| 526 |
+
|
| 527 |
+
except Exception as e:
|
| 528 |
+
print(f"❌ Erro na geração: {e}")
|
| 529 |
+
import traceback
|
| 530 |
+
traceback.print_exc()
|
| 531 |
+
return None, None, None, seed
|
| 532 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 533 |
|
| 534 |
+
# ===== INTERFACE GRADIO PREMIUM =====
|
| 535 |
css = """
|
| 536 |
+
#col-container {max-width: 1600px; margin: 0 auto; padding: 20px;}
|
| 537 |
+
.tab-nav button {font-size: 16px; font-weight: 600;}
|
| 538 |
+
.gr-button-primary {background: linear-gradient(90deg, #667eea 0%, #764ba2 100%) !important;}
|
|
|
|
| 539 |
"""
|
| 540 |
|
| 541 |
+
with gr.Blocks(css=css, theme=gr.themes.Soft(), title="IA Studio Ultimate") as demo:
|
| 542 |
+
gr.HTML("""
|
| 543 |
+
<div style="text-align: center; max-width: 1200px; margin: 0 auto;">
|
| 544 |
+
<h1 style="font-size: 3em; background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">
|
| 545 |
+
🎨 IA Studio Ultimate
|
| 546 |
+
</h1>
|
| 547 |
+
<p style="font-size: 1.2em; color: #666;">
|
| 548 |
+
Sistema Completo: FLUX + SDXL + ControlNet + IP-Adapter + Upscale + Face Fix<br>
|
| 549 |
+
<strong>Qualidade Superior ao GPT-5 | Otimizado para 18GB VRAM</strong>
|
| 550 |
+
</p>
|
| 551 |
+
</div>
|
| 552 |
+
""")
|
| 553 |
+
|
| 554 |
+
with gr.Tabs():
|
| 555 |
+
# ===== TAB 1: GERAÇÃO PRINCIPAL =====
|
| 556 |
+
with gr.Tab("🎨 Geração"):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 557 |
with gr.Row():
|
| 558 |
+
with gr.Column(scale=1):
|
| 559 |
+
prompt = gr.TextArea(
|
| 560 |
+
label="✍️ Prompt Principal",
|
| 561 |
+
placeholder="Descreva sua visão em detalhes...\nEx: A majestic dragon perched on ancient ruins, golden hour lighting, epic fantasy, 8k",
|
| 562 |
+
lines=5,
|
| 563 |
+
)
|
| 564 |
+
|
| 565 |
+
with gr.Accordion("🎨 Estilo & Qualidade", open=True):
|
| 566 |
+
with gr.Row():
|
| 567 |
+
style_preset = gr.Dropdown(
|
| 568 |
+
choices=["Fotorrealista Ultra", "Fantasia Épica", "Anime Studio", "Cinematográfico", "Pintura Digital Pro", "3D Render Premium", "Hiper-Realista", "RPG Character Art"],
|
| 569 |
+
value="Fotorrealista Ultra",
|
| 570 |
+
label="Preset de Estilo",
|
| 571 |
+
)
|
| 572 |
+
quality_boost = gr.Dropdown(
|
| 573 |
+
choices=["Máxima", "Alta", "Normal", "Desativado"],
|
| 574 |
+
value="Máxima",
|
| 575 |
+
label="Boost de Qualidade",
|
| 576 |
+
)
|
| 577 |
+
|
| 578 |
+
negative_preset = gr.Dropdown(
|
| 579 |
+
choices=["Padrão", "Forte", "Máximo", "Ultra (Anti-IA)", "Personalizado"],
|
| 580 |
+
value="Máximo",
|
| 581 |
+
label="Prompt Negativo",
|
| 582 |
+
)
|
| 583 |
+
|
| 584 |
+
custom_negative = gr.TextArea(
|
| 585 |
+
label="Negativo Personalizado",
|
| 586 |
+
visible=False,
|
| 587 |
+
lines=2,
|
| 588 |
+
)
|
| 589 |
+
|
| 590 |
+
input_image = gr.Image(
|
| 591 |
+
label="🖼️ Imagem de Entrada (img2img)",
|
| 592 |
+
type="pil",
|
| 593 |
+
sources=["upload", "webcam", "clipboard"],
|
| 594 |
+
)
|
| 595 |
+
|
| 596 |
+
run_button = gr.Button("🚀 GERAR OBRA-PRIMA", variant="primary", size="lg")
|
| 597 |
+
|
| 598 |
+
with gr.Column(scale=1):
|
| 599 |
+
result = gr.Image(label="✨ Resultado Final", show_download_button=True, show_share_button=True)
|
| 600 |
+
control_preview = gr.Image(label="🎛️ ControlNet Preview", visible=False)
|
| 601 |
+
enhanced_prompt_output = gr.TextArea(label="📝 Prompt Melhorado", lines=3)
|
| 602 |
+
seed_output = gr.Number(label="🎲 Seed Usado", precision=0)
|
| 603 |
+
|
| 604 |
+
# ===== TAB 2: CONTROLNET =====
|
| 605 |
+
with gr.Tab("🎛️ ControlNet"):
|
| 606 |
+
gr.Markdown("### Controle Preciso de Composição")
|
| 607 |
+
|
| 608 |
with gr.Row():
|
| 609 |
+
use_controlnet = gr.Checkbox(label="✓ Ativar ControlNet", value=False)
|
| 610 |
+
controlnet_type = gr.Dropdown(
|
| 611 |
+
choices=["Nenhum", "Canny (Contornos)", "Depth (Profundidade)", "OpenPose (Pose)", "Lineart (Desenho)", "Soft Edge (Bordas)", "Tile (Upscale)"],
|
| 612 |
+
value="Nenhum",
|
| 613 |
+
label="Tipo de Controle",
|
|
|
|
| 614 |
)
|
| 615 |
+
|
| 616 |
+
with gr.Row():
|
| 617 |
+
controlnet_strength = gr.Slider(0.0, 2.0, 1.0, step=0.05, label="💪 Força do ControlNet")
|
| 618 |
+
canny_low = gr.Slider(0, 255, 100, step=1, label="Canny Low")
|
| 619 |
+
canny_high = gr.Slider(0, 255, 200, step=1, label="Canny High")
|
| 620 |
+
|
| 621 |
+
gr.Markdown("""
|
| 622 |
+
**Guia de Uso:**
|
| 623 |
+
- **Canny**: Bordas precisas - perfeito para arquitetura e composição
|
| 624 |
+
- **Depth**: Preserva estrutura 3D - ideal para paisagens e ambientes
|
| 625 |
+
- **OpenPose**: Controle de poses humanas - essencial para personagens
|
| 626 |
+
- **Lineart**: Converte desenhos em arte finalizada
|
| 627 |
+
- **Soft Edge**: Bordas suaves para controle artístico
|
| 628 |
+
- **Tile**: Upscaling guiado para detalhes ultra-HD
|
| 629 |
+
""")
|
| 630 |
+
|
| 631 |
+
# ===== TAB 3: IP-ADAPTER =====
|
| 632 |
+
with gr.Tab("🖼️ IP-Adapter (Estilo por Imagem)"):
|
| 633 |
+
gr.Markdown("### Transfira Estilo Visual de Imagens de Referência")
|
| 634 |
+
|
| 635 |
+
with gr.Row():
|
| 636 |
+
use_ip_adapter = gr.Checkbox(label="✓ Ativar IP-Adapter", value=False)
|
| 637 |
+
ip_adapter_type = gr.Dropdown(
|
| 638 |
+
choices=["plus", "plus-face"],
|
| 639 |
+
value="plus",
|
| 640 |
+
label="Tipo de IP-Adapter",
|
| 641 |
)
|
| 642 |
+
|
| 643 |
+
ip_reference_image = gr.Image(
|
| 644 |
+
label="🎨 Imagem de Referência de Estilo",
|
| 645 |
+
type="pil",
|
| 646 |
+
sources=["upload", "clipboard"],
|
| 647 |
+
)
|
| 648 |
+
|
| 649 |
+
ip_adapter_strength = gr.Slider(
|
| 650 |
+
0.0, 1.0, 0.6, step=0.05,
|
| 651 |
+
label="💪 Força do IP-Adapter",
|
| 652 |
+
info="Quanto da referência aplicar"
|
| 653 |
+
)
|
| 654 |
+
|
| 655 |
+
gr.Markdown("""
|
| 656 |
+
**Como Funciona:**
|
| 657 |
+
- **IP-Adapter Plus**: Transfere estilo geral, composição e atmosfera
|
| 658 |
+
- **IP-Adapter Face**: Foco em características faciais e expressões
|
| 659 |
+
|
| 660 |
+
**Exemplos de Uso:**
|
| 661 |
+
1. Upload de foto de ator → Gera personagem RPG com mesmas features
|
| 662 |
+
2. Arte conceitual → Aplica mesmo estilo visual
|
| 663 |
+
3. Foto de cenário → Recria em estilo fantasia mantendo composição
|
| 664 |
+
""")
|
| 665 |
+
|
| 666 |
+
# ===== TAB 4: CONFIGURAÇÕES AVANÇADAS =====
|
| 667 |
+
with gr.Tab("⚙️ Configurações Pro"):
|
| 668 |
+
with gr.Row():
|
| 669 |
+
with gr.Column():
|
| 670 |
+
gr.Markdown("### 🤖 Modelo & Engine")
|
| 671 |
+
model_choice = gr.Dropdown(
|
| 672 |
+
choices=list(MODELS.keys()),
|
| 673 |
+
value="FLUX.1-dev (Melhor)",
|
| 674 |
+
label="Modelo Base",
|
| 675 |
+
)
|
| 676 |
+
scheduler_type = gr.Dropdown(
|
| 677 |
+
choices=["Padrão", "DPM++ 2M", "Euler a", "DDIM"],
|
| 678 |
+
value="DPM++ 2M",
|
| 679 |
+
label="Scheduler (Algoritmo)",
|
| 680 |
+
)
|
| 681 |
+
|
| 682 |
+
with gr.Column():
|
| 683 |
+
gr.Markdown("### 📐 Dimensões")
|
| 684 |
+
with gr.Row():
|
| 685 |
+
width = gr.Slider(512, 1536, 1024, step=64, label="↔️ Largura")
|
| 686 |
+
height = gr.Slider(512, 1536, 1024, step=64, label="↕️ Altura")
|
| 687 |
+
|
| 688 |
+
aspect_ratio = gr.Radio(
|
| 689 |
+
choices=["1:1", "16:9", "9:16", "4:3", "3:4", "21:9"],
|
| 690 |
+
label="📐 Aspect Ratio Rápido",
|
| 691 |
+
value="1:1"
|
| 692 |
+
)
|
| 693 |
+
|
| 694 |
+
with gr.Row():
|
| 695 |
+
with gr.Column():
|
| 696 |
+
gr.Markdown("### 🎚️ Parâmetros de Geração")
|
| 697 |
+
guidance_scale = gr.Slider(
|
| 698 |
+
1.0, 20.0, 7.5, step=0.5,
|
| 699 |
+
label="🎯 CFG Scale (Fidelidade ao Prompt)",
|
| 700 |
+
info="7-8 = balanceado | 12+ = muito literal"
|
| 701 |
+
)
|
| 702 |
+
num_steps = gr.Slider(
|
| 703 |
+
20, 100, 35, step=1,
|
| 704 |
+
label="🔄 Passos de Inferência",
|
| 705 |
+
info="Mais passos = melhor qualidade (mais lento)"
|
| 706 |
+
)
|
| 707 |
+
strength = gr.Slider(
|
| 708 |
+
0.0, 1.0, 0.75, step=0.05,
|
| 709 |
+
label="💪 Strength (img2img)",
|
| 710 |
+
info="0.3 = leve | 0.7 = forte | 1.0 = totalmente novo"
|
| 711 |
+
)
|
| 712 |
+
|
| 713 |
+
with gr.Column():
|
| 714 |
+
gr.Markdown("### 🎲 Reprodutibilidade")
|
| 715 |
+
seed = gr.Number(
|
| 716 |
+
label="Seed",
|
| 717 |
+
value=0,
|
| 718 |
+
precision=0,
|
| 719 |
+
info="Use mesma seed + prompt para resultado idêntico"
|
| 720 |
+
)
|
| 721 |
+
randomize_seed = gr.Checkbox(
|
| 722 |
+
label="🔀 Seed Aleatória",
|
| 723 |
+
value=True
|
| 724 |
+
)
|
| 725 |
+
|
| 726 |
+
gr.Markdown("### 📊 Presets Rápidos")
|
| 727 |
+
preset_buttons = gr.Radio(
|
| 728 |
+
choices=["Qualidade Máxima", "Balanceado", "Rápido", "Ultra Rápido"],
|
| 729 |
+
label="Presets de Velocidade",
|
| 730 |
+
value="Balanceado"
|
| 731 |
+
)
|
| 732 |
+
|
| 733 |
+
# ===== TAB 5: PÓS-PROCESSAMENTO =====
|
| 734 |
+
with gr.Tab("✨ Pós-Processamento"):
|
| 735 |
+
gr.Markdown("### 🚀 Upscaling e Correções Avançadas")
|
| 736 |
+
|
| 737 |
+
with gr.Row():
|
| 738 |
+
with gr.Column():
|
| 739 |
+
upscale_factor = gr.Slider(
|
| 740 |
+
1, 4, 1, step=1,
|
| 741 |
+
label="📈 Fator de Upscale (RealESRGAN)",
|
| 742 |
+
info="1 = sem upscale | 2 = 2x | 4 = 4x (demora mais)"
|
| 743 |
+
)
|
| 744 |
+
enhance_faces = gr.Checkbox(
|
| 745 |
+
label="✨ Corrigir Rostos (GFPGAN)",
|
| 746 |
+
value=False,
|
| 747 |
+
info="Melhora qualidade de rostos automaticamente"
|
| 748 |
+
)
|
| 749 |
+
denoise_strength = gr.Slider(
|
| 750 |
+
0.0, 1.0, 0.5, step=0.05,
|
| 751 |
+
label="🎭 Força de Denoise",
|
| 752 |
+
info="Remove artefatos e ruído"
|
| 753 |
+
)
|
| 754 |
+
|
| 755 |
+
with gr.Column():
|
| 756 |
+
gr.Markdown("""
|
| 757 |
+
**Tecnologias Incluídas:**
|
| 758 |
+
|
| 759 |
+
🔬 **RealESRGAN x4**
|
| 760 |
+
- Upscaling com IA de última geração
|
| 761 |
+
- Preserva detalhes e texturas
|
| 762 |
+
- Perfeito para impressão HD
|
| 763 |
+
|
| 764 |
+
👤 **GFPGAN v1.3**
|
| 765 |
+
- Correção automática de rostos
|
| 766 |
+
- Remove distorções faciais
|
| 767 |
+
- Melhora expressões e features
|
| 768 |
+
|
| 769 |
+
⚡ **Performance:**
|
| 770 |
+
- 4x upscale: ~10-15s extra
|
| 771 |
+
- Face fix: ~5s por rosto
|
| 772 |
+
- Processamento em GPU
|
| 773 |
+
""")
|
| 774 |
+
|
| 775 |
+
# ===== TAB 6: EXEMPLOS E TUTORIAIS =====
|
| 776 |
+
with gr.Tab("📚 Exemplos & Tutoriais"):
|
| 777 |
+
gr.Markdown("## 🎓 Galeria de Exemplos Profissionais")
|
| 778 |
+
|
| 779 |
+
with gr.Tabs():
|
| 780 |
+
with gr.Tab("🏰 Cenários RPG"):
|
| 781 |
+
gr.Examples(
|
| 782 |
+
examples=[
|
| 783 |
+
["Ancient elven city built into giant trees, magical glowing runes, misty atmosphere, moss covered stone bridges, fantasy architecture, golden hour lighting, epic scale", None, None],
|
| 784 |
+
["Medieval tavern interior, warm fireplace, wooden tables with ale mugs, adventurers in leather armor, cozy atmosphere, candlelight, detailed textures", None, None],
|
| 785 |
+
["Dark vampire castle throne room, gothic architecture, red velvet curtains, moonlight through stained glass, ominous atmosphere, dramatic lighting", None, None],
|
| 786 |
+
["Underground dwarven forge, lava rivers, massive hammers and anvils, glowing molten metal, intricate metalwork, dramatic fire lighting", None, None],
|
| 787 |
+
],
|
| 788 |
+
inputs=[prompt, input_image, ip_reference_image],
|
| 789 |
+
)
|
| 790 |
+
|
| 791 |
+
with gr.Tab("👥 Personagens"):
|
| 792 |
+
gr.Examples(
|
| 793 |
+
examples=[
|
| 794 |
+
["Epic portrait of a female paladin, golden armor with holy symbols, long flowing hair, determined expression, divine light emanating, fantasy character art, highly detailed", None, None],
|
| 795 |
+
["Mysterious rogue character, dark leather armor, dual daggers, hood casting shadow over face, misty background, moody lighting, concept art", None, None],
|
| 796 |
+
["Powerful wizard with glowing staff, flowing robes with arcane symbols, long beard, magical energy swirling around, dramatic pose, fantasy art", None, None],
|
| 797 |
+
["Fierce orc warrior chieftain, battle-scarred armor, massive war axe, intimidating pose, tribal tattoos, stormy background, epic fantasy", None, None],
|
| 798 |
+
],
|
| 799 |
+
inputs=[prompt, input_image, ip_reference_image],
|
| 800 |
+
)
|
| 801 |
+
|
| 802 |
+
with gr.Tab("🎬 Cinematográfico"):
|
| 803 |
+
gr.Examples(
|
| 804 |
+
examples=[
|
| 805 |
+
["Cinematic shot of spaceship interior, crew members at control stations, holographic displays, blue atmospheric lighting, sci-fi movie still, anamorphic lens", None, None],
|
| 806 |
+
["Dramatic scene of lone warrior on cliff edge, epic sunset, wind blowing cape, silhouette against orange sky, cinematic composition, 35mm film", None, None],
|
| 807 |
+
["Post-apocalyptic city ruins, overgrown vegetation, abandoned cars, atmospheric fog, dramatic lighting, movie still, depth of field", None, None],
|
| 808 |
+
],
|
| 809 |
+
inputs=[prompt, input_image, ip_reference_image],
|
| 810 |
+
)
|
| 811 |
+
|
| 812 |
+
with gr.Tab("🌟 Hiper-Realista"):
|
| 813 |
+
gr.Examples(
|
| 814 |
+
examples=[
|
| 815 |
+
["Professional portrait photography of a female model, natural makeup, soft studio lighting, bokeh background, 85mm lens, fashion photography, hyperrealistic", None, None],
|
| 816 |
+
["Photorealistic rendering of luxury sports car, chrome details, reflective surface, studio lighting, professional automotive photography, 8k", None, None],
|
| 817 |
+
["Hyperrealistic close-up of exotic flower, water droplets on petals, macro photography, natural lighting, intricate details, botanical art", None, None],
|
| 818 |
+
],
|
| 819 |
+
inputs=[prompt, input_image, ip_reference_image],
|
| 820 |
+
)
|
| 821 |
+
|
| 822 |
+
gr.Markdown("""
|
| 823 |
+
---
|
| 824 |
+
## 💡 Guia de Prompts Profissionais
|
| 825 |
+
|
| 826 |
+
### 📝 Estrutura Ideal de Prompt:
|
| 827 |
+
```
|
| 828 |
+
[Assunto Principal] + [Detalhes Visuais] + [Atmosfera/Mood] + [Estilo Artístico] + [Qualidade]
|
| 829 |
+
```
|
| 830 |
+
|
| 831 |
+
### ✨ Palavras-Chave Poderosas:
|
| 832 |
+
|
| 833 |
+
**Para Realismo:**
|
| 834 |
+
`photorealistic, 8k uhd, professional photography, sharp focus, natural lighting, dslr, high quality`
|
| 835 |
+
|
| 836 |
+
**Para Fantasia:**
|
| 837 |
+
`epic fantasy, magical atmosphere, detailed textures, dramatic lighting, concept art, matte painting`
|
| 838 |
+
|
| 839 |
+
**Para Personagens:**
|
| 840 |
+
`detailed armor, intricate clothing, character portrait, expressive face, dynamic pose, hero shot`
|
| 841 |
+
|
| 842 |
+
**Para Iluminação:**
|
| 843 |
+
`golden hour, volumetric lighting, rim light, god rays, dramatic shadows, cinematic lighting`
|
| 844 |
+
|
| 845 |
+
**Para Atmosfera:**
|
| 846 |
+
`mystical, ominous, cozy, epic, serene, dramatic, moody, vibrant, ethereal`
|
| 847 |
+
|
| 848 |
+
### 🚫 Palavras para Evitar:
|
| 849 |
+
❌ Termos vagos: "good", "nice", "beautiful" (sem especificidade)
|
| 850 |
+
❌ Contradições: "realistic cartoon"
|
| 851 |
+
❌ Lista muito longa sem contexto
|
| 852 |
+
|
| 853 |
+
### 🎯 Exemplos de Prompts Otimizados:
|
| 854 |
+
|
| 855 |
+
**Ruim:**
|
| 856 |
+
`dragon`
|
| 857 |
+
|
| 858 |
+
**Bom:**
|
| 859 |
+
`red dragon breathing fire`
|
| 860 |
+
|
| 861 |
+
**Excelente:**
|
| 862 |
+
`Majestic ancient red dragon perched on mountain peak, scales glistening in sunset, wings spread wide, breathing streams of fire, stormy clouds, epic fantasy art, dramatic lighting, highly detailed, 8k`
|
| 863 |
+
""")
|
| 864 |
+
|
| 865 |
+
# ===== TAB 7: INFO DO SISTEMA =====
|
| 866 |
+
with gr.Tab("ℹ️ Sistema"):
|
| 867 |
+
gr.Markdown(f"""
|
| 868 |
+
## 🖥️ Informações do Sistema
|
| 869 |
+
|
| 870 |
+
**Status:** ✅ Operacional
|
| 871 |
+
**Device:** {device.upper()}
|
| 872 |
+
**Precision:** {torch_dtype}
|
| 873 |
+
**VRAM Otimizada:** 18GB
|
| 874 |
+
|
| 875 |
+
---
|
| 876 |
+
|
| 877 |
+
## 🎨 Modelos Disponíveis
|
| 878 |
+
|
| 879 |
+
### Base Models:
|
| 880 |
+
{chr(10).join([f"- **{k}**: {v}" for k, v in MODELS.items()])}
|
| 881 |
+
|
| 882 |
+
### ControlNet Models:
|
| 883 |
+
{chr(10).join([f"- **{k}**: {v}" for k, v in CONTROLNET_MODELS.items()])}
|
| 884 |
+
|
| 885 |
+
---
|
| 886 |
+
|
| 887 |
+
## ⚡ Otimizações Ativas
|
| 888 |
+
|
| 889 |
+
✅ xFormers Memory Efficient Attention
|
| 890 |
+
✅ VAE Slicing & Tiling
|
| 891 |
+
✅ Attention Slicing
|
| 892 |
+
✅ Model Compilation (PyTorch 2.0+)
|
| 893 |
+
✅ Smart Model Caching
|
| 894 |
+
✅ FP16 Precision
|
| 895 |
+
|
| 896 |
+
---
|
| 897 |
+
|
| 898 |
+
## 🚀 Features Implementadas
|
| 899 |
+
|
| 900 |
+
### Geração:
|
| 901 |
+
- ✅ Text-to-Image (FLUX & SDXL)
|
| 902 |
+
- ✅ Image-to-Image
|
| 903 |
+
- ✅ Inpainting
|
| 904 |
+
- ✅ ControlNet (6 tipos)
|
| 905 |
+
- ✅ IP-Adapter (estilo por imagem)
|
| 906 |
+
|
| 907 |
+
### Pós-Processamento:
|
| 908 |
+
- ✅ RealESRGAN 4x Upscaling
|
| 909 |
+
- ✅ GFPGAN Face Enhancement
|
| 910 |
+
- ✅ Denoise Inteligente
|
| 911 |
+
|
| 912 |
+
### Prompt Engineering:
|
| 913 |
+
- ✅ 8 Presets de Estilo
|
| 914 |
+
- ✅ 4 Níveis de Qualidade
|
| 915 |
+
- ✅ 5 Presets de Negative
|
| 916 |
+
- ✅ Enhancement Automático
|
| 917 |
+
|
| 918 |
+
### Performance:
|
| 919 |
+
- ✅ Cache Inteligente de Modelos
|
| 920 |
+
- ✅ Schedulers Otimizados
|
| 921 |
+
- ✅ Batch Processing Ready
|
| 922 |
+
- ✅ Progress Tracking
|
| 923 |
+
|
| 924 |
+
---
|
| 925 |
+
|
| 926 |
+
## 📊 Comparação vs GPT-5
|
| 927 |
+
|
| 928 |
+
| Feature | IA Studio Ultimate | GPT-5/DALL-E 3 |
|
| 929 |
+
|---------|-------------------|----------------|
|
| 930 |
+
| **Qualidade** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
|
| 931 |
+
| **Controle** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
|
| 932 |
+
| **ControlNet** | ✅ 6 tipos | ❌ |
|
| 933 |
+
| **IP-Adapter** | ✅ | ❌ |
|
| 934 |
+
| **Upscaling** | ✅ 4x | ❌ |
|
| 935 |
+
| **Face Fix** | ✅ | ❌ |
|
| 936 |
+
| **Modelos** | ✅ 7+ | 🔒 1 |
|
| 937 |
+
| **Seed Control** | ✅ | ⚠️ Limitado |
|
| 938 |
+
| **Offline** | ✅ | ❌ |
|
| 939 |
+
| **Custo** | 🆓 | 💰 |
|
| 940 |
+
| **Customização** | ⭐⭐⭐⭐⭐ | ⭐⭐ |
|
| 941 |
+
|
| 942 |
+
---
|
| 943 |
+
|
| 944 |
+
## 🎯 Vantagens Competitivas
|
| 945 |
+
|
| 946 |
+
1. **Controle Total**: ControlNet permite controle preciso impossível em outros sistemas
|
| 947 |
+
2. **IP-Adapter**: Transferência de estilo visual que GPT-5 não oferece
|
| 948 |
+
3. **Pós-Processamento**: Upscaling e correção facial integrados
|
| 949 |
+
4. **Reprodutibilidade**: Seeds garantem resultados idênticos
|
| 950 |
+
5. **Múltiplos Modelos**: Escolha o melhor para cada tarefa
|
| 951 |
+
6. **Sem Censura**: Controle total sobre conteúdo
|
| 952 |
+
7. **Offline**: Funciona sem internet após download
|
| 953 |
+
8. **Gratuito**: Zero custos por geração
|
| 954 |
+
|
| 955 |
+
---
|
| 956 |
+
|
| 957 |
+
## 📖 Dicas de Performance
|
| 958 |
+
|
| 959 |
+
**Para Máxima Qualidade:**
|
| 960 |
+
- Modelo: FLUX.1-dev ou RealVisXL
|
| 961 |
+
- Steps: 35-50
|
| 962 |
+
- CFG Scale: 7-8
|
| 963 |
+
- Upscale: 2x ou 4x
|
| 964 |
+
- Face Fix: Ativado
|
| 965 |
+
|
| 966 |
+
**Para Velocidade:**
|
| 967 |
+
- Modelo: FLUX.1-schnell ou SDXL-Turbo
|
| 968 |
+
- Steps: 20-25
|
| 969 |
+
- CFG Scale: 3-5
|
| 970 |
+
- Upscale: Desativado
|
| 971 |
+
|
| 972 |
+
**Para Precisão (ControlNet):**
|
| 973 |
+
- Use Canny para bordas
|
| 974 |
+
- Use Depth para estrutura 3D
|
| 975 |
+
- Strength: 0.7-1.2
|
| 976 |
+
- Combine com IP-Adapter
|
| 977 |
+
|
| 978 |
+
---
|
| 979 |
+
|
| 980 |
+
## 🆘 Troubleshooting
|
| 981 |
+
|
| 982 |
+
**Out of Memory:**
|
| 983 |
+
- Reduza resolution (1024→768)
|
| 984 |
+
- Desative upscaling
|
| 985 |
+
- Use SDXL-Turbo
|
| 986 |
+
|
| 987 |
+
**Resultado ruim:**
|
| 988 |
+
- Aumente steps (35+)
|
| 989 |
+
- Ajuste CFG scale (7-9)
|
| 990 |
+
- Use prompt negativo "Máximo"
|
| 991 |
+
- Adicione mais detalhes ao prompt
|
| 992 |
+
|
| 993 |
+
**Muito lento:**
|
| 994 |
+
- Use FLUX.1-schnell
|
| 995 |
+
- Reduza steps para 20-25
|
| 996 |
+
- Desative pós-processamento
|
| 997 |
+
|
| 998 |
+
---
|
| 999 |
+
|
| 1000 |
+
**Versão:** 2.0 Ultimate
|
| 1001 |
+
**Última Atualização:** 2025
|
| 1002 |
+
**Desenvolvido para:** Criadores Profissionais, Artistas, Game Designers
|
| 1003 |
+
""")
|
| 1004 |
+
|
| 1005 |
+
# ===== EVENT HANDLERS =====
|
| 1006 |
+
|
| 1007 |
+
# Atualiza negative prompt personalizado
|
| 1008 |
+
def update_negative_visibility(preset):
|
| 1009 |
+
return gr.update(visible=(preset == "Personalizado"))
|
| 1010 |
+
|
| 1011 |
+
negative_preset.change(
|
| 1012 |
+
fn=update_negative_visibility,
|
| 1013 |
+
inputs=[negative_preset],
|
| 1014 |
+
outputs=[custom_negative],
|
| 1015 |
+
)
|
| 1016 |
+
|
| 1017 |
+
# Mostra preview do ControlNet
|
| 1018 |
+
def update_controlnet_preview(enabled):
|
| 1019 |
+
return gr.update(visible=enabled)
|
| 1020 |
+
|
| 1021 |
+
use_controlnet.change(
|
| 1022 |
+
fn=update_controlnet_preview,
|
| 1023 |
+
inputs=[use_controlnet],
|
| 1024 |
+
outputs=[control_preview],
|
| 1025 |
+
)
|
| 1026 |
+
|
| 1027 |
+
# Aspect ratio rápido
|
| 1028 |
+
def apply_aspect_ratio(ratio, current_width):
|
| 1029 |
+
ratios = {
|
| 1030 |
+
"1:1": (1024, 1024),
|
| 1031 |
+
"16:9": (1344, 768),
|
| 1032 |
+
"9:16": (768, 1344),
|
| 1033 |
+
"4:3": (1152, 896),
|
| 1034 |
+
"3:4": (896, 1152),
|
| 1035 |
+
"21:9": (1536, 640),
|
| 1036 |
+
}
|
| 1037 |
+
w, h = ratios.get(ratio, (1024, 1024))
|
| 1038 |
+
return w, h
|
| 1039 |
+
|
| 1040 |
+
aspect_ratio.change(
|
| 1041 |
+
fn=apply_aspect_ratio,
|
| 1042 |
+
inputs=[aspect_ratio, width],
|
| 1043 |
+
outputs=[width, height],
|
| 1044 |
+
)
|
| 1045 |
+
|
| 1046 |
+
# Presets de velocidade
|
| 1047 |
+
def apply_preset(preset):
|
| 1048 |
+
presets = {
|
| 1049 |
+
"Qualidade Máxima": (50, 8.0, "DPM++ 2M"),
|
| 1050 |
+
"Balanceado": (35, 7.5, "DPM++ 2M"),
|
| 1051 |
+
"Rápido": (25, 6.0, "Euler a"),
|
| 1052 |
+
"Ultra Rápido": (20, 4.0, "Euler a"),
|
| 1053 |
+
}
|
| 1054 |
+
steps, cfg, scheduler = presets.get(preset, (35, 7.5, "DPM++ 2M"))
|
| 1055 |
+
return steps, cfg, scheduler
|
| 1056 |
+
|
| 1057 |
+
preset_buttons.change(
|
| 1058 |
+
fn=apply_preset,
|
| 1059 |
+
inputs=[preset_buttons],
|
| 1060 |
+
outputs=[num_steps, guidance_scale, scheduler_type],
|
| 1061 |
+
)
|
| 1062 |
+
|
| 1063 |
+
# Geração principal
|
| 1064 |
+
run_button.click(
|
| 1065 |
fn=infer,
|
| 1066 |
inputs=[
|
| 1067 |
+
prompt, input_image, ip_reference_image,
|
| 1068 |
+
use_controlnet, controlnet_type, controlnet_strength, canny_low, canny_high,
|
| 1069 |
+
use_ip_adapter, ip_adapter_type, ip_adapter_strength,
|
| 1070 |
+
model_choice, style_preset, quality_boost, negative_preset, custom_negative,
|
| 1071 |
+
seed, randomize_seed, width, height, guidance_scale, num_steps, strength,
|
| 1072 |
+
scheduler_type, upscale_factor, enhance_faces, denoise_strength,
|
|
|
|
|
|
|
| 1073 |
],
|
| 1074 |
+
outputs=[result, control_preview, enhanced_prompt_output, seed_output],
|
| 1075 |
)
|
| 1076 |
|
| 1077 |
if __name__ == "__main__":
|
| 1078 |
+
demo.queue(max_size=20).launch(
|
| 1079 |
+
share=True,
|
| 1080 |
+
show_error=True,
|
| 1081 |
+
server_name="0.0.0.0",
|
| 1082 |
+
server_port=7860,
|
| 1083 |
+
show_api=False,
|
| 1084 |
+
)
|