ivanoctaviogaitansantos commited on
Commit
12258ce
·
verified ·
1 Parent(s): 9a81634

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +358 -0
app.py ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import time
3
+ import random
4
+ from diffusers import StableDiffusionPipeline
5
+ import torch
6
+ from PIL import Image, ImageFilter, ImageStat
7
+ import numpy as np
8
+
9
+ # ========== AGENTES DEFINIDOS DIRECTAMENTE EN EL ARCHIVO ==========
10
+
11
+ class LightingAgent:
12
+ def __init__(self):
13
+ print("✅ LightingAgent inicializado")
14
+ self.lighting_styles = {
15
+ "cinematic": "dramatic lighting, cinematic style, film noir, high contrast, volumetric light",
16
+ "natural": "natural sunlight, soft light, golden hour, ambient light, realistic lighting",
17
+ "studio": "studio lighting, professional photo, softbox, beauty dish, even lighting",
18
+ "moody": "moody lighting, low key, chiaroscuro, atmospheric, dramatic shadows"
19
+ }
20
+
21
+ def optimize_lighting(self, base_prompt, lighting_style):
22
+ lighting_terms = self.lighting_styles.get(lighting_style, self.lighting_styles["natural"])
23
+ optimized_prompt = f"{base_prompt}, {lighting_terms}"
24
+ return optimized_prompt, lighting_style
25
+
26
+ class TextureAgent:
27
+ def __init__(self):
28
+ print("✅ TextureAgent inicializado")
29
+ self.texture_library = {
30
+ "skin": [
31
+ "detailed skin texture", "natural skin pores", "skin microdetails",
32
+ "subsurface scattering", "realistic skin", "skin imperfections"
33
+ ],
34
+ "hair": [
35
+ "individual hair strands", "hair texture", "realistic hair flow",
36
+ "hair details", "natural hair"
37
+ ]
38
+ }
39
+
40
+ def enhance_textures(self, prompt):
41
+ enhanced_prompt = prompt
42
+ skin_terms = random.sample(self.texture_library["skin"], 2)
43
+ enhanced_prompt += f", {', '.join(skin_terms)}"
44
+
45
+ if "8k" not in enhanced_prompt.lower():
46
+ enhanced_prompt += ", detailed texture, high quality details"
47
+
48
+ return enhanced_prompt
49
+
50
+ class CompositionAgent:
51
+ def __init__(self):
52
+ print("✅ CompositionAgent inicializado")
53
+ self.composition_rules = {
54
+ "portrait": [
55
+ "head and shoulders composition", "rule of thirds", "vertical portrait",
56
+ "close-up shot", "professional portrait composition"
57
+ ],
58
+ "full_body": [
59
+ "full body portrait", "vertical composition", "environmental portrait",
60
+ "full figure", "standing pose vertical"
61
+ ]
62
+ }
63
+
64
+ def optimize_composition(self, prompt, composition_type="portrait"):
65
+ composition_terms = self.composition_rules.get(composition_type, self.composition_rules["portrait"])
66
+ selected_terms = composition_terms[:2]
67
+ optimized_prompt = f"{prompt}, {', '.join(selected_terms)}, vertical format 9:16"
68
+ return optimized_prompt, composition_type
69
+
70
+ class StyleTransferAgent:
71
+ def __init__(self):
72
+ print("✅ StyleTransferAgent inicializado")
73
+ self.hyperreal_styles = {
74
+ "photorealistic": {
75
+ "terms": "photorealistic, 8k resolution, professional photography, highly detailed",
76
+ "description": "Máximo realismo fotográfico"
77
+ },
78
+ "cinematic": {
79
+ "terms": "cinematic, movie still, film photography, dramatic, cinematic style",
80
+ "description": "Estilo de película o cine"
81
+ }
82
+ }
83
+
84
+ def apply_style(self, prompt, style_name="photorealistic"):
85
+ style_data = self.hyperreal_styles.get(style_name, self.hyperreal_styles["photorealistic"])
86
+ styled_prompt = f"{prompt}, {style_data['terms']}"
87
+ return styled_prompt, style_name, style_data["description"]
88
+
89
+ class QualityControlAgent:
90
+ def __init__(self):
91
+ print("✅ QualityControlAgent inicializado")
92
+
93
+ def analyze_image_quality(self, image):
94
+ if not isinstance(image, Image.Image):
95
+ return {"score": 0.5, "feedback": ["No se pudo analizar la imagen"]}
96
+
97
+ try:
98
+ metrics = {
99
+ "contrast": self._analyze_contrast(image),
100
+ "sharpness": self._analyze_sharpness(image),
101
+ "brightness": self._analyze_brightness(image)
102
+ }
103
+
104
+ overall_score = np.mean(list(metrics.values()))
105
+
106
+ return {
107
+ "score": round(overall_score, 2),
108
+ "metrics": metrics,
109
+ "feedback": self._generate_feedback(metrics)
110
+ }
111
+ except Exception as e:
112
+ return {"score": 0.5, "feedback": ["Error en análisis"]}
113
+
114
+ def _analyze_contrast(self, image):
115
+ stat = ImageStat.Stat(image)
116
+ if len(stat.stddev) == 3:
117
+ return np.mean(stat.stddev) / 255.0
118
+ return 0.5
119
+
120
+ def _analyze_sharpness(self, image):
121
+ small_img = image.resize((100, 100))
122
+ edges = small_img.filter(ImageFilter.FIND_EDGES)
123
+ stat = ImageStat.Stat(edges)
124
+ return min(np.mean(stat.stddev) / 255.0, 1.0)
125
+
126
+ def _analyze_brightness(self, image):
127
+ stat = ImageStat.Stat(image)
128
+ if len(stat.mean) == 3:
129
+ brightness = np.mean(stat.mean) / 255.0
130
+ return 1.0 - abs(brightness - 0.5) * 2
131
+ return 0.5
132
+
133
+ def _generate_feedback(self, metrics):
134
+ feedback = []
135
+ if metrics.get("contrast", 0) < 0.3:
136
+ feedback.append("Puedes mejorar el contraste")
137
+ if metrics.get("sharpness", 0) < 0.4:
138
+ feedback.append("La imagen está algo borrosa")
139
+ return feedback if feedback else ["¡Buena calidad de imagen!"]
140
+
141
+ class EmotionAgent:
142
+ def __init__(self):
143
+ self.emotion_profiles = {
144
+ "subtle_smile": "hint of smile, gentle eye crinkles, relaxed forehead, natural expression",
145
+ "contemplative": "distant gaze, soft frown, pensive expression, thoughtful look",
146
+ "joyful_laugh": "crow's feet, teeth slightly visible, raised cheeks, genuine smile",
147
+ "serious": "neutral expression, focused gaze, composed demeanor, professional"
148
+ }
149
+ print("✅ EmotionAgent inicializado")
150
+
151
+ def add_emotion_cues(self, base_prompt, emotion):
152
+ emotion_cues = self.emotion_profiles.get(emotion, "natural expression")
153
+ return f"{base_prompt}, {emotion_cues}"
154
+
155
+ def get_available_emotions(self):
156
+ return list(self.emotion_profiles.keys())
157
+
158
+ class ImageGenerator:
159
+ def __init__(self):
160
+ print("🔄 Cargando generador de imágenes...")
161
+ self.device = "cpu"
162
+ self.pipeline = None
163
+ self.model_id = "runwayml/stable-diffusion-v1-5"
164
+ self.load_model()
165
+
166
+ def load_model(self):
167
+ try:
168
+ print("📥 Descargando modelo Stable Diffusion...")
169
+
170
+ self.pipeline = StableDiffusionPipeline.from_pretrained(
171
+ self.model_id,
172
+ torch_dtype=torch.float32,
173
+ use_safetensors=True,
174
+ safety_checker=None,
175
+ requires_safety_checker=False,
176
+ )
177
+
178
+ self.pipeline = self.pipeline.to(self.device)
179
+ self.pipeline.enable_attention_slicing()
180
+
181
+ print("✅ Generador de imágenes cargado")
182
+ except Exception as e:
183
+ print(f"❌ Error cargando el generador: {e}")
184
+ raise e
185
+
186
+ def generate_image(self, prompt, negative_prompt="", width=512, height=768):
187
+ print(f"🎨 Generando: {prompt[:80]}...")
188
+ start_time = time.time()
189
+
190
+ try:
191
+ with torch.no_grad():
192
+ result = self.pipeline(
193
+ prompt=prompt,
194
+ negative_prompt=negative_prompt,
195
+ width=width,
196
+ height=height,
197
+ num_inference_steps=20,
198
+ guidance_scale=7.5,
199
+ generator=torch.manual_seed(42)
200
+ )
201
+
202
+ image = result.images[0]
203
+ generation_time = time.time() - start_time
204
+ print(f"✅ Imagen generada en {generation_time:.1f}s")
205
+ return image
206
+
207
+ except Exception as e:
208
+ print(f"❌ Error generando imagen: {e}")
209
+ return Image.new('RGB', (width, height), color='gray')
210
+
211
+ # ========== APLICACIÓN PRINCIPAL ==========
212
+
213
+ class HyperRealStudio916:
214
+ def __init__(self):
215
+ print("🚀 Iniciando HyperReal Studio 916...")
216
+
217
+ # Inicializar todos los agentes
218
+ self.lighting_agent = LightingAgent()
219
+ self.texture_agent = TextureAgent()
220
+ self.composition_agent = CompositionAgent()
221
+ self.style_agent = StyleTransferAgent()
222
+ self.quality_agent = QualityControlAgent()
223
+ self.emotion_agent = EmotionAgent()
224
+ self.image_generator = ImageGenerator()
225
+
226
+ print("✅ ¡Aplicación lista!")
227
+
228
+ def generate_portrait(self, description, lighting_style, emotion, composition_type, enhance_texture, style_preset):
229
+ print(f"🎨 Iniciando generación...")
230
+ start_time = time.time()
231
+
232
+ # Negative prompt
233
+ negative_prompt = "cartoon, 3d, render, anime, fake, plastic, doll, deformed, blurry"
234
+
235
+ # Aplicar agentes
236
+ current_prompt = description
237
+
238
+ # Agente de emociones
239
+ current_prompt = self.emotion_agent.add_emotion_cues(current_prompt, emotion)
240
+
241
+ # Agente de iluminación
242
+ current_prompt, _ = self.lighting_agent.optimize_lighting(current_prompt, lighting_style)
243
+
244
+ # Agente de composición
245
+ current_prompt, _ = self.composition_agent.optimize_composition(current_prompt, composition_type)
246
+
247
+ # Agente de estilo
248
+ current_prompt, _, _ = self.style_agent.apply_style(current_prompt, style_preset)
249
+
250
+ # Agente de texturas
251
+ if enhance_texture:
252
+ current_prompt = self.texture_agent.enhance_textures(current_prompt)
253
+
254
+ # Generar imagen
255
+ image = self.image_generator.generate_image(
256
+ prompt=current_prompt,
257
+ negative_prompt=negative_prompt,
258
+ width=512,
259
+ height=768
260
+ )
261
+
262
+ # Analizar calidad
263
+ quality_analysis = self.quality_agent.analyze_image_quality(image)
264
+
265
+ total_time = time.time() - start_time
266
+ print(f"✅ Proceso completado en {total_time:.1f}s")
267
+
268
+ return image, quality_analysis['score'], current_prompt, quality_analysis
269
+
270
+ def create_interface():
271
+ studio = HyperRealStudio916()
272
+
273
+ with gr.Blocks(theme=gr.themes.Soft(), title="HyperReal Studio 916") as demo:
274
+ gr.Markdown("""
275
+ # 🎨 HyperReal Studio 916
276
+ ### Generador de Retratos Hiperrealistas
277
+ """)
278
+
279
+ with gr.Row():
280
+ with gr.Column(scale=1):
281
+ description = gr.Textbox(
282
+ label="📝 Descripción",
283
+ placeholder="Ej: mujer joven con cabello castaño, sonriendo...",
284
+ lines=3
285
+ )
286
+
287
+ lighting_style = gr.Dropdown(
288
+ choices=["cinematic", "natural", "studio", "moody"],
289
+ label="💡 Iluminación",
290
+ value="natural"
291
+ )
292
+
293
+ emotion = gr.Dropdown(
294
+ choices=studio.emotion_agent.get_available_emotions(),
295
+ label="😊 Emoción",
296
+ value="subtle_smile"
297
+ )
298
+
299
+ composition_type = gr.Dropdown(
300
+ choices=["portrait", "full_body"],
301
+ label="📐 Composición",
302
+ value="portrait"
303
+ )
304
+
305
+ style_preset = gr.Dropdown(
306
+ choices=["photorealistic", "cinematic"],
307
+ label="🎨 Estilo",
308
+ value="photorealistic"
309
+ )
310
+
311
+ enhance_texture = gr.Checkbox(
312
+ label="🔍 Mejorar Texturas",
313
+ value=True
314
+ )
315
+
316
+ generate_btn = gr.Button("🎨 Generar Retrato", variant="primary")
317
+
318
+ with gr.Column(scale=2):
319
+ output_image = gr.Image(
320
+ label="🖼️ Retrato Generado",
321
+ format="png",
322
+ height=400
323
+ )
324
+
325
+ realism_score = gr.Number(
326
+ label="📊 Calidad",
327
+ precision=2
328
+ )
329
+
330
+ used_prompt = gr.Textbox(
331
+ label="📝 Prompt Utilizado",
332
+ lines=2
333
+ )
334
+
335
+ with gr.Accordion("📈 Análisis", open=False):
336
+ quality_analysis = gr.JSON(
337
+ label="Métricas"
338
+ )
339
+
340
+ gr.Examples(
341
+ examples=[
342
+ ["mujer joven con cabello largo, sonriendo", "natural", "subtle_smile", "portrait", "photorealistic"],
343
+ ["hombre maduro con barba, serio", "cinematic", "serious", "portrait", "cinematic"]
344
+ ],
345
+ inputs=[description, lighting_style, emotion, composition_type, style_preset],
346
+ )
347
+
348
+ generate_btn.click(
349
+ fn=studio.generate_portrait,
350
+ inputs=[description, lighting_style, emotion, composition_type, enhance_texture, style_preset],
351
+ outputs=[output_image, realism_score, used_prompt, quality_analysis]
352
+ )
353
+
354
+ return demo
355
+
356
+ if __name__ == "__main__":
357
+ demo = create_interface()
358
+ demo.launch(server_name="0.0.0.0", server_port=7860)