Malaji71 commited on
Commit
1128cf2
·
verified ·
1 Parent(s): 325e056

Update analyzer.py

Browse files
Files changed (1) hide show
  1. analyzer.py +288 -344
analyzer.py CHANGED
@@ -1,373 +1,317 @@
1
  """
2
- Ultra Supreme Analyzer for image analysis and prompt building
3
- VERSIÓN MEJORADA - Potencia CLIP en lugar de limitarlo
4
  """
5
 
6
- import re
7
- from typing import Dict, List, Any, Tuple
 
8
  import logging
 
 
 
 
 
 
 
 
 
9
 
10
  logger = logging.getLogger(__name__)
11
 
12
 
13
- class UltraSupremeAnalyzer:
14
- """
15
- ULTRA SUPREME ANALYSIS ENGINE - POTENCIA CLIP, NO LO LIMITA
16
- """
17
 
18
  def __init__(self):
19
- # Palabras a limpiar de las descripciones de CLIP
20
- self.cleanup_patterns = [
21
- r'arafed\s*',
22
- r'there is\s*',
23
- r'a photo of\s*',
24
- r'an image of\s*',
25
- r'a picture of\s*',
26
- r'inspired by [^,]+,?\s*',
27
- r'by [A-Z][^,]+,?\s*',
28
- r'trending on [^,]+,?\s*',
29
- r'featured on [^,]+,?\s*',
30
- r'\d+k\s*',
31
- r'::\s*::\s*',
32
- r'contest winner,?\s*',
33
- r'award winning,?\s*',
34
- ]
35
-
36
- # Indicadores de calidad técnica
37
- self.technical_indicators = {
38
- 'portrait': ['portrait', 'headshot', 'face', 'person', 'man', 'woman', 'child'],
39
- 'landscape': ['mountain', 'landscape', 'nature', 'outdoor', 'field', 'forest'],
40
- 'dramatic': ['dramatic', 'light shining', 'silhouette', 'backlit', 'atmospheric'],
41
- 'professional': ['professional', 'studio', 'formal', 'business'],
42
- 'artistic': ['artistic', 'creative', 'abstract', 'conceptual'],
43
- 'documentary': ['documentary', 'candid', 'street', 'journalism', 'authentic']
44
- }
45
-
46
- # Mejoras de iluminación basadas en contexto
47
- self.lighting_enhancements = {
48
- 'outdoor': 'natural lighting with golden hour warmth',
49
- 'mountain': 'dramatic alpine lighting with atmospheric haze',
50
- 'portrait': 'professional portrait lighting with subtle rim light',
51
- 'silhouette': 'dramatic backlighting creating ethereal silhouettes',
52
- 'indoor': 'soft diffused window lighting with gentle shadows',
53
- 'night': 'cinematic low-key lighting with strategic highlights',
54
- 'default': 'masterful lighting that enhances depth and dimension'
55
- }
56
-
57
- # Configuraciones de cámara según el tipo de foto
58
- self.camera_configs = {
59
- 'portrait': 'Shot on Hasselblad X2D 100C, 90mm f/2.5 lens at f/2.8',
60
- 'landscape': 'Shot on Phase One XT, 40mm f/4 lens at f/8',
61
- 'dramatic': 'Shot on Canon R5, 85mm f/1.2 lens at f/2',
62
- 'street': 'Shot on Leica M11, 35mm f/1.4 lens at f/2.8',
63
- 'default': 'Shot on Phase One XF IQ4, 80mm f/2.8 lens at f/4'
64
- }
65
 
66
- def clean_clip_description(self, description: str) -> str:
67
- """Limpia la descripción de CLIP eliminando ruido pero preservando contenido valioso"""
68
- cleaned = description.lower()
69
-
70
- # Eliminar patrones de ruido
71
- for pattern in self.cleanup_patterns:
72
- cleaned = re.sub(pattern, '', cleaned, flags=re.IGNORECASE)
73
-
74
- # Limpiar espacios múltiples y comas redundantes
75
- cleaned = re.sub(r'\s+', ' ', cleaned)
76
- cleaned = re.sub(r',\s*,+', ',', cleaned)
77
- cleaned = re.sub(r'^\s*,\s*', '', cleaned)
78
- cleaned = re.sub(r'\s*,\s*$', '', cleaned)
79
-
80
- return cleaned.strip()
81
-
82
- def extract_key_elements(self, clip_fast: str, clip_classic: str, clip_best: str) -> Dict[str, Any]:
83
- """Extrae elementos clave de las tres descripciones de CLIP"""
84
-
85
- # Limpiar todas las descripciones
86
- fast_clean = self.clean_clip_description(clip_fast)
87
- classic_clean = self.clean_clip_description(clip_classic)
88
- best_clean = self.clean_clip_description(clip_best)
89
-
90
- # Combinar información única de las tres fuentes
91
- all_descriptions = f"{fast_clean} {classic_clean} {best_clean}"
92
-
93
- # Extraer elementos principales
94
- elements = {
95
- 'main_subject': self._extract_main_subject(all_descriptions),
96
- 'action': self._extract_action(all_descriptions),
97
- 'location': self._extract_location(all_descriptions),
98
- 'mood': self._extract_mood(all_descriptions),
99
- 'special_features': self._extract_special_features(all_descriptions),
100
- 'technical_style': self._determine_technical_style(all_descriptions),
101
- 'original_essence': self._preserve_unique_elements(fast_clean, classic_clean, best_clean)
102
- }
103
-
104
- return elements
105
-
106
- def _extract_main_subject(self, description: str) -> str:
107
- """Extrae el sujeto principal de la descripción"""
108
- # Buscar patrones comunes de sujetos
109
- subject_patterns = [
110
- r'(a |an )?([\w\s]+ )?(man|woman|person|child|boy|girl|people|group)',
111
- r'(a |an )?([\w\s]+ )?(portrait|face|figure)',
112
- r'(a |an )?([\w\s]+ )?(landscape|mountain|building|structure)',
113
- r'(a |an )?([\w\s]+ )?(animal|dog|cat|bird)',
114
- ]
115
-
116
- for pattern in subject_patterns:
117
- match = re.search(pattern, description)
118
- if match:
119
- return match.group(0).strip()
120
-
121
- # Si no encuentra un patrón específico, tomar las primeras palabras significativas
122
- words = description.split()
123
- if len(words) > 2:
124
- return ' '.join(words[:3])
125
-
126
- return "figure"
127
-
128
- def _extract_action(self, description: str) -> str:
129
- """Extrae la acción o pose del sujeto"""
130
- action_keywords = ['standing', 'sitting', 'walking', 'running', 'looking',
131
- 'holding', 'wearing', 'posing', 'working', 'playing']
132
-
133
- for keyword in action_keywords:
134
- if keyword in description:
135
- # Extraer contexto alrededor de la palabra clave
136
- pattern = rf'\b\w*\s*{keyword}\s*\w*\s*\w*'
137
- match = re.search(pattern, description)
138
- if match:
139
- return match.group(0).strip()
140
-
141
- return ""
142
-
143
- def _extract_location(self, description: str) -> str:
144
- """Extrae información de ubicación o ambiente"""
145
- location_keywords = ['mountain', 'beach', 'forest', 'city', 'street', 'indoor',
146
- 'outdoor', 'studio', 'nature', 'urban', 'field', 'desert',
147
- 'ocean', 'lake', 'building', 'home', 'office']
148
-
149
- found_locations = []
150
- for keyword in location_keywords:
151
- if keyword in description:
152
- found_locations.append(keyword)
153
-
154
- if found_locations:
155
- return ' '.join(found_locations[:2]) # Máximo 2 ubicaciones
156
-
157
- return ""
158
-
159
- def _extract_mood(self, description: str) -> str:
160
- """Extrae el mood o atmósfera de la imagen"""
161
- mood_keywords = ['dramatic', 'peaceful', 'serene', 'intense', 'mysterious',
162
- 'joyful', 'melancholic', 'powerful', 'ethereal', 'moody',
163
- 'bright', 'dark', 'atmospheric', 'dreamy', 'dynamic']
164
-
165
- for keyword in mood_keywords:
166
- if keyword in description:
167
- return keyword
168
-
169
- return ""
170
-
171
- def _extract_special_features(self, description: str) -> List[str]:
172
- """Extrae características especiales únicas de la descripción"""
173
- special_patterns = [
174
- 'light shining on [\w\s]+',
175
- 'wearing [\w\s]+',
176
- 'with [\w\s]+ in the background',
177
- 'surrounded by [\w\s]+',
178
- '[\w\s]+ lighting',
179
- '[\w\s]+ atmosphere'
180
- ]
181
-
182
- features = []
183
- for pattern in special_patterns:
184
- matches = re.findall(pattern, description)
185
- features.extend(matches)
186
-
187
- return features[:3] # Limitar a 3 características especiales
188
-
189
- def _determine_technical_style(self, description: str) -> str:
190
- """Determina el estilo técnico más apropiado basado en el contenido"""
191
- style_scores = {}
192
-
193
- for style, keywords in self.technical_indicators.items():
194
- score = sum(1 for keyword in keywords if keyword in description)
195
- if score > 0:
196
- style_scores[style] = score
197
-
198
- if style_scores:
199
- return max(style_scores, key=style_scores.get)
200
-
201
- return 'default'
202
-
203
- def _preserve_unique_elements(self, fast: str, classic: str, best: str) -> str:
204
- """Preserva elementos únicos e interesantes de las descripciones"""
205
- # Encontrar frases únicas que aparecen en alguna descripción
206
- all_words = set(fast.split() + classic.split() + best.split())
207
- common_words = set(['a', 'an', 'the', 'is', 'are', 'was', 'were', 'with', 'of', 'in', 'on', 'at'])
208
-
209
- unique_words = all_words - common_words
210
-
211
- # Buscar frases interesantes que contengan estas palabras únicas
212
- unique_phrases = []
213
- for desc in [fast, classic, best]:
214
- if 'light shining' in desc or 'adventure gear' in desc or 'anthropological' in desc:
215
- # Estas son frases únicas valiosas
216
- unique_phrases.append(desc)
217
- break
218
-
219
- return ' '.join(unique_phrases[:1]) if unique_phrases else ""
220
-
221
- def build_ultra_supreme_prompt(self, elements: Dict[str, Any], original_descriptions: List[str]) -> str:
222
- """Construye un prompt que POTENCIA la visión de CLIP"""
223
-
224
- components = []
225
-
226
- # 1. Sujeto principal con artículo apropiado
227
- subject = elements['main_subject']
228
- if subject:
229
- # Determinar artículo
230
- if subject[0].lower() in 'aeiou':
231
- components.append(f"An {subject}")
232
- else:
233
- components.append(f"A {subject}")
234
  else:
235
- components.append("A figure")
236
-
237
- # 2. Acción si existe
238
- if elements['action']:
239
- components.append(elements['action'])
240
-
241
- # 3. Características especiales (esto es lo que hace única la imagen)
242
- if elements['special_features']:
243
- for feature in elements['special_features'][:2]:
244
- components.append(feature)
245
-
246
- # 4. Ubicación/Ambiente
247
- if elements['location']:
248
- if 'mountain' in elements['location']:
249
- components.append("on a majestic mountain peak")
250
- elif 'outdoor' in elements['location'] or 'nature' in elements['location']:
251
- components.append("in a breathtaking natural setting")
 
 
 
 
 
252
  else:
253
- components.append(f"in {elements['location']}")
254
-
255
- # 5. Mood/Atmósfera si existe
256
- if elements['mood']:
257
- components.append(f"capturing a {elements['mood']} atmosphere")
258
-
259
- # 6. Iluminación basada en contexto
260
- lighting_context = elements['location'] or elements['technical_style']
261
- lighting = self.lighting_enhancements.get(lighting_context, self.lighting_enhancements['default'])
262
- components.append(f"illuminated with {lighting}")
263
-
264
- # 7. Configuración técnica de cámara
265
- camera_setup = self.camera_configs.get(elements['technical_style'], self.camera_configs['default'])
266
- components.append(camera_setup)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
 
268
- # 8. Estilo fotográfico final
269
- if elements['technical_style'] == 'portrait':
270
- components.append("masterful portrait photography")
271
- elif elements['technical_style'] == 'landscape':
272
- components.append("epic landscape photography")
273
- elif elements['technical_style'] == 'dramatic':
274
- components.append("cinematic photography with powerful visual impact")
275
- elif elements['technical_style'] == 'documentary':
276
- components.append("authentic documentary photography")
 
 
 
277
  else:
278
- components.append("professional photography with exceptional detail")
279
-
280
- # 9. Añadir esencia única preservada si existe
281
- if elements['original_essence'] and len(elements['original_essence']) > 10:
282
- # Incluir elementos únicos que CLIP detectó
283
- logger.info(f"Preservando esencia única: {elements['original_essence']}")
284
-
285
- # Construir prompt final
286
- prompt = ", ".join(components)
287
-
288
- # Limpieza final
289
- prompt = re.sub(r'\s+', ' ', prompt)
290
- prompt = re.sub(r',\s*,+', ',', prompt)
291
- prompt = re.sub(r'\s*,\s*', ', ', prompt)
292
-
293
- # Capitalizar primera letra
294
- if prompt:
295
- prompt = prompt[0].upper() + prompt[1:]
296
-
297
- logger.info(f"Prompt generado: {prompt}")
298
 
299
- return prompt
300
-
301
- def ultra_supreme_analysis(self, clip_fast: str, clip_classic: str, clip_best: str) -> Dict[str, Any]:
302
- """Análisis que POTENCIA la información de CLIP en lugar de limitarla"""
303
 
304
- logger.info("Iniciando análisis MEJORADO que potencia CLIP")
 
305
 
306
- # Extraer elementos clave de las descripciones
307
- elements = self.extract_key_elements(clip_fast, clip_classic, clip_best)
 
308
 
309
- # Construir resultado del análisis
310
- result = {
311
- "elements": elements,
312
- "technical_style": elements['technical_style'],
313
- "unique_features": elements['special_features'],
314
- "preserved_essence": elements['original_essence'],
315
- "mood": elements['mood'],
316
- "location": elements['location']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
  }
318
 
319
- return result
320
-
321
- def build_ultra_supreme_prompt(self, ultra_analysis: Dict[str, Any], clip_results: List[str]) -> str:
322
- """Versión pública del método para compatibilidad"""
323
- return self.build_ultra_supreme_prompt(ultra_analysis['elements'], clip_results)
324
-
325
- def calculate_ultra_supreme_score(self, prompt: str, ultra_analysis: Dict[str, Any]) -> Tuple[int, Dict[str, int]]:
326
- """Calcula score basado en la riqueza del prompt generado"""
327
 
 
 
 
 
 
 
 
 
 
 
 
 
328
  score = 0
329
- breakdown = {}
330
 
331
- # Estructura (20 puntos)
332
- structure_score = 0
333
- if prompt.startswith(("A ", "An ")):
334
- structure_score += 10
335
- if prompt.count(",") >= 5:
336
- structure_score += 10
337
- score += structure_score
338
- breakdown["structure"] = structure_score
339
 
340
- # Elementos únicos preservados (30 puntos)
341
- unique_score = 0
342
- if ultra_analysis.get('unique_features'):
343
- unique_score += len(ultra_analysis['unique_features']) * 10
344
- unique_score = min(unique_score, 30)
345
- score += unique_score
346
- breakdown["unique"] = unique_score
347
 
348
- # Contexto técnico (20 puntos)
349
- tech_score = 0
350
- if "Shot on" in prompt:
351
- tech_score += 10
352
- if any(term in prompt for term in ["f/", "mm"]):
353
- tech_score += 10
354
- score += tech_score
355
- breakdown["technical"] = tech_score
356
 
357
- # Mood y atmósfera (15 puntos)
358
- mood_score = 0
359
- if ultra_analysis.get('mood'):
360
- mood_score += 15
361
- score += mood_score
362
- breakdown["mood"] = mood_score
363
 
364
- # Calidad descriptiva (15 puntos)
365
- desc_score = 0
366
- if len(prompt) > 100:
367
- desc_score += 10
368
- if any(term in prompt for term in ["masterful", "epic", "cinematic", "exceptional"]):
369
- desc_score += 5
370
- score += desc_score
371
- breakdown["descriptive"] = desc_score
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
 
373
- return min(score, 100), breakdown
 
1
  """
2
+ Ultra Supreme Optimizer - Main optimization engine for image analysis
3
+ VERSIÓN MEJORADA - Usa el prompt completo de CLIP Interrogator
4
  """
5
 
6
+ # IMPORTANT: spaces must be imported BEFORE torch or any CUDA-using library
7
+ import spaces
8
+ import gc
9
  import logging
10
+ from datetime import datetime
11
+ from typing import Tuple, Dict, Any, Optional
12
+
13
+ import torch
14
+ import numpy as np
15
+ from PIL import Image
16
+ from clip_interrogator import Config, Interrogator
17
+
18
+ from analyzer import UltraSupremeAnalyzer
19
 
20
  logger = logging.getLogger(__name__)
21
 
22
 
23
+ class UltraSupremeOptimizer:
24
+ """Main optimizer class for ultra supreme image analysis"""
 
 
25
 
26
  def __init__(self):
27
+ self.interrogator: Optional[Interrogator] = None
28
+ self.analyzer = UltraSupremeAnalyzer()
29
+ self.usage_count = 0
30
+ self.device = self._get_device()
31
+ self.is_initialized = False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
+ @staticmethod
34
+ def _get_device() -> str:
35
+ """Determine the best available device for computation"""
36
+ if torch.cuda.is_available():
37
+ return "cuda"
38
+ elif torch.backends.mps.is_available():
39
+ return "mps"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  else:
41
+ return "cpu"
42
+
43
+ def initialize_model(self) -> bool:
44
+ """Initialize the CLIP interrogator model"""
45
+ if self.is_initialized:
46
+ return True
47
+
48
+ try:
49
+ config = Config(
50
+ clip_model_name="ViT-L-14/openai",
51
+ download_cache=True,
52
+ chunk_size=2048,
53
+ quiet=True,
54
+ device=self.device
55
+ )
56
+
57
+ self.interrogator = Interrogator(config)
58
+ self.is_initialized = True
59
+
60
+ # Clean up memory after initialization
61
+ if self.device == "cpu":
62
+ gc.collect()
63
  else:
64
+ torch.cuda.empty_cache()
65
+
66
+ return True
67
+
68
+ except Exception as e:
69
+ logger.error(f"Initialization error: {e}")
70
+ return False
71
+
72
+ def optimize_image(self, image: Any) -> Optional[Image.Image]:
73
+ """Optimize image for processing"""
74
+ if image is None:
75
+ return None
76
+
77
+ try:
78
+ # Convert to PIL Image if necessary
79
+ if isinstance(image, np.ndarray):
80
+ image = Image.fromarray(image)
81
+ elif not isinstance(image, Image.Image):
82
+ image = Image.open(image)
83
+
84
+ # Convert to RGB if necessary
85
+ if image.mode != 'RGB':
86
+ image = image.convert('RGB')
87
+
88
+ # Resize if too large
89
+ max_size = 768 if self.device != "cpu" else 512
90
+ if image.size[0] > max_size or image.size[1] > max_size:
91
+ image.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)
92
+
93
+ return image
94
+
95
+ except Exception as e:
96
+ logger.error(f"Image optimization error: {e}")
97
+ return None
98
+
99
+ def apply_flux_rules(self, base_prompt: str) -> str:
100
+ """Aplica las reglas de Flux a un prompt base de CLIP Interrogator"""
101
+
102
+ # Limpiar el prompt de elementos no deseados
103
+ cleanup_patterns = [
104
+ r',\s*trending on artstation',
105
+ r',\s*trending on [^,]+',
106
+ r',\s*\d+k\s*',
107
+ r',\s*\d+k resolution',
108
+ r',\s*artstation',
109
+ r',\s*concept art',
110
+ r',\s*digital art',
111
+ r',\s*by greg rutkowski', # Remover artistas genéricos overused
112
+ ]
113
 
114
+ cleaned_prompt = base_prompt
115
+ for pattern in cleanup_patterns:
116
+ cleaned_prompt = re.sub(pattern, '', cleaned_prompt, flags=re.IGNORECASE)
117
+
118
+ # Detectar el tipo de imagen para añadir configuración de cámara apropiada
119
+ camera_config = ""
120
+ if any(word in base_prompt.lower() for word in ['portrait', 'person', 'man', 'woman', 'face']):
121
+ camera_config = ", Shot on Hasselblad X2D 100C, 90mm f/2.5 lens at f/2.8, professional portrait photography"
122
+ elif any(word in base_prompt.lower() for word in ['landscape', 'mountain', 'nature', 'outdoor']):
123
+ camera_config = ", Shot on Phase One XT, 40mm f/4 lens at f/8, epic landscape photography"
124
+ elif any(word in base_prompt.lower() for word in ['street', 'urban', 'city']):
125
+ camera_config = ", Shot on Leica M11, 35mm f/1.4 lens at f/2.8, documentary street photography"
126
  else:
127
+ camera_config = ", Shot on Phase One XF IQ4, 80mm f/2.8 lens at f/4, professional photography"
128
+
129
+ # Añadir mejoras de iluminación si no están presentes
130
+ if 'lighting' not in cleaned_prompt.lower():
131
+ if 'dramatic' in cleaned_prompt.lower():
132
+ cleaned_prompt += ", dramatic cinematic lighting"
133
+ elif 'portrait' in cleaned_prompt.lower():
134
+ cleaned_prompt += ", professional studio lighting with subtle rim light"
135
+ else:
136
+ cleaned_prompt += ", masterful natural lighting"
 
 
 
 
 
 
 
 
 
 
137
 
138
+ # Construir el prompt final
139
+ final_prompt = cleaned_prompt + camera_config
 
 
140
 
141
+ # Asegurar que empiece con mayúscula
142
+ final_prompt = final_prompt[0].upper() + final_prompt[1:] if final_prompt else final_prompt
143
 
144
+ # Limpiar espacios y comas duplicadas
145
+ final_prompt = re.sub(r'\s+', ' ', final_prompt)
146
+ final_prompt = re.sub(r',\s*,+', ',', final_prompt)
147
 
148
+ return final_prompt
149
+
150
+ @spaces.GPU
151
+ def generate_ultra_supreme_prompt(self, image: Any) -> Tuple[str, str, int, Dict[str, int]]:
152
+ """
153
+ Generate ultra supreme prompt from image usando el pipeline completo
154
+
155
+ Returns:
156
+ Tuple of (prompt, analysis_info, score, breakdown)
157
+ """
158
+ try:
159
+ # Initialize model if needed
160
+ if not self.is_initialized:
161
+ if not self.initialize_model():
162
+ return "❌ Model initialization failed.", "Please refresh and try again.", 0, {}
163
+
164
+ # Validate input
165
+ if image is None:
166
+ return "❌ Please upload an image.", "No image provided.", 0, {}
167
+
168
+ self.usage_count += 1
169
+
170
+ # Optimize image
171
+ image = self.optimize_image(image)
172
+ if image is None:
173
+ return "❌ Image processing failed.", "Invalid image format.", 0, {}
174
+
175
+ start_time = datetime.now()
176
+
177
+ # NUEVO PIPELINE: Usar CLIP Interrogator completo
178
+ logger.info("ULTRA SUPREME ANALYSIS - Usando pipeline completo de CLIP Interrogator")
179
+
180
+ # 1. Obtener el prompt COMPLETO de CLIP Interrogator (no solo análisis)
181
+ # Este incluye descripción + artistas + estilos + mediums
182
+ full_prompt = self.interrogator.interrogate(image)
183
+ logger.info(f"Prompt completo de CLIP Interrogator: {full_prompt}")
184
+
185
+ # 2. También obtener los análisis individuales para el reporte
186
+ clip_fast = self.interrogator.interrogate_fast(image)
187
+ clip_classic = self.interrogator.interrogate_classic(image)
188
+
189
+ logger.info(f"Análisis Fast: {clip_fast}")
190
+ logger.info(f"Análisis Classic: {clip_classic}")
191
+
192
+ # 3. Aplicar reglas de Flux al prompt completo
193
+ import re
194
+ optimized_prompt = self.apply_flux_rules(full_prompt)
195
+
196
+ # 4. Crear análisis para el reporte (simplificado)
197
+ analysis_summary = {
198
+ "base_prompt": full_prompt,
199
+ "clip_fast": clip_fast,
200
+ "clip_classic": clip_classic,
201
+ "optimized": optimized_prompt,
202
+ "detected_style": self._detect_style(full_prompt),
203
+ "detected_subject": self._detect_subject(full_prompt)
204
+ }
205
+
206
+ # 5. Calcular score basado en la riqueza del prompt
207
+ score = self._calculate_score(optimized_prompt, full_prompt)
208
+ breakdown = {
209
+ "base_quality": min(len(full_prompt) // 10, 25),
210
+ "technical_enhancement": 25 if "Shot on" in optimized_prompt else 0,
211
+ "lighting_quality": 25 if "lighting" in optimized_prompt.lower() else 0,
212
+ "composition": 25 if any(word in optimized_prompt.lower() for word in ["professional", "masterful", "epic"]) else 0
213
+ }
214
+ score = sum(breakdown.values())
215
+
216
+ end_time = datetime.now()
217
+ duration = (end_time - start_time).total_seconds()
218
+
219
+ # Memory cleanup
220
+ if self.device == "cpu":
221
+ gc.collect()
222
+ else:
223
+ torch.cuda.empty_cache()
224
+
225
+ # Generate analysis report
226
+ analysis_info = self._generate_analysis_report(
227
+ analysis_summary, score, breakdown, duration
228
+ )
229
+
230
+ return optimized_prompt, analysis_info, score, breakdown
231
+
232
+ except Exception as e:
233
+ logger.error(f"Ultra supreme generation error: {e}")
234
+ return f"❌ Error: {str(e)}", "Please try with a different image.", 0, {}
235
+
236
+ def _detect_style(self, prompt: str) -> str:
237
+ """Detecta el estilo principal del prompt"""
238
+ styles = {
239
+ "portrait": ["portrait", "person", "face", "headshot"],
240
+ "landscape": ["landscape", "mountain", "nature", "scenery"],
241
+ "street": ["street", "urban", "city"],
242
+ "artistic": ["artistic", "abstract", "conceptual"],
243
+ "dramatic": ["dramatic", "cinematic", "moody"]
244
  }
245
 
246
+ for style_name, keywords in styles.items():
247
+ if any(keyword in prompt.lower() for keyword in keywords):
248
+ return style_name
 
 
 
 
 
249
 
250
+ return "general"
251
+
252
+ def _detect_subject(self, prompt: str) -> str:
253
+ """Detecta el sujeto principal del prompt"""
254
+ # Tomar las primeras palabras significativas
255
+ words = prompt.split(',')[0].split()
256
+ if len(words) > 3:
257
+ return ' '.join(words[:4])
258
+ return prompt.split(',')[0]
259
+
260
+ def _calculate_score(self, optimized_prompt: str, base_prompt: str) -> int:
261
+ """Calcula el score basado en la calidad del prompt"""
262
  score = 0
 
263
 
264
+ # Base score por longitud y riqueza
265
+ score += min(len(base_prompt) // 10, 25)
 
 
 
 
 
 
266
 
267
+ # Technical enhancement
268
+ if "Shot on" in optimized_prompt:
269
+ score += 25
 
 
 
 
270
 
271
+ # Lighting quality
272
+ if "lighting" in optimized_prompt.lower():
273
+ score += 25
 
 
 
 
 
274
 
275
+ # Professional quality
276
+ if any(word in optimized_prompt.lower() for word in ["professional", "masterful", "epic", "cinematic"]):
277
+ score += 25
 
 
 
278
 
279
+ return min(score, 100)
280
+
281
+ def _generate_analysis_report(self, analysis: Dict[str, Any],
282
+ score: int, breakdown: Dict[str, int],
283
+ duration: float) -> str:
284
+ """Generate detailed analysis report"""
285
+
286
+ gpu_status = "⚡ ZeroGPU" if torch.cuda.is_available() else "💻 CPU"
287
+
288
+ # Extraer información clave
289
+ detected_style = analysis.get("detected_style", "general").title()
290
+ detected_subject = analysis.get("detected_subject", "Unknown")
291
+ base_prompt_preview = analysis.get("base_prompt", "")[:100] + "..." if len(analysis.get("base_prompt", "")) > 100 else analysis.get("base_prompt", "")
292
+
293
+ analysis_info = f"""**🚀 ULTRA SUPREME ANALYSIS COMPLETE**
294
+ **Processing:** {gpu_status} • {duration:.1f}s • Full CLIP Interrogator Pipeline
295
+ **Ultra Score:** {score}/100 • Breakdown: Base({breakdown.get('base_quality',0)}) Technical({breakdown.get('technical_enhancement',0)}) Lighting({breakdown.get('lighting_quality',0)}) Composition({breakdown.get('composition',0)})
296
+ **Generation:** #{self.usage_count}
297
+
298
+ **🧠 INTELLIGENT DETECTION:**
299
+ - **Detected Style:** {detected_style}
300
+ - **Main Subject:** {detected_subject}
301
+ - **Pipeline:** CLIP Interrogator → Flux Optimization → Technical Enhancement
302
+
303
+ **📊 CLIP INTERROGATOR ANALYSIS:**
304
+ - **Base Prompt:** {base_prompt_preview}
305
+ - **Fast Analysis:** {analysis.get('clip_fast', '')[:80]}...
306
+ - **Classic Analysis:** {analysis.get('clip_classic', '')[:80]}...
307
+
308
+ **⚡ OPTIMIZATION APPLIED:**
309
+ - ✅ Preserved CLIP Interrogator's rich description
310
+ - ✅ Added professional camera specifications
311
+ - ✅ Enhanced lighting descriptions
312
+ - ✅ Applied Flux-specific optimizations
313
+ - ✅ Removed redundant/generic elements
314
+
315
+ **🔬 Powered by Pariente AI Research + CLIP Interrogator**"""
316
 
317
+ return analysis_info