Malaji71 commited on
Commit
56f917a
·
verified ·
1 Parent(s): 1128cf2

Update analyzer.py

Browse files
Files changed (1) hide show
  1. analyzer.py +38 -303
analyzer.py CHANGED
@@ -1,317 +1,52 @@
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
 
1
  """
2
+ Ultra Supreme Analyzer - VERSIÓN SIMPLIFICADA
3
+ Solo formatea, no limita
4
  """
5
 
6
+ import re
7
+ from typing import Dict, List, Any, Tuple
 
 
 
 
8
 
9
+ class UltraSupremeAnalyzer:
10
+ """Analyzer simplificado que NO limita CLIP"""
 
 
 
 
 
 
 
 
 
 
11
 
12
  def __init__(self):
13
+ pass
14
+
15
+ def ultra_supreme_analysis(self, clip_fast: str, clip_classic: str, clip_best: str) -> Dict[str, Any]:
16
+ """Análisis mínimo - solo devuelve los datos raw"""
17
+ return {
18
+ "clip_fast": clip_fast,
19
+ "clip_classic": clip_classic,
20
+ "clip_best": clip_best,
21
+ "full_description": f"{clip_fast} {clip_classic} {clip_best}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  }
23
+
24
+ def build_ultra_supreme_prompt(self, ultra_analysis: Dict[str, Any], clip_results: List[str]) -> str:
25
+ """NO construye nada - este método ya no se usa con el nuevo pipeline"""
26
+ # Este método existe solo por compatibilidad
27
+ # El verdadero trabajo se hace en optimizer.py con apply_flux_rules()
28
+ return clip_results[0] if clip_results else ""
29
+
30
+ def calculate_ultra_supreme_score(self, prompt: str, ultra_analysis: Dict[str, Any]) -> Tuple[int, Dict[str, int]]:
31
+ """Calcula score basado en la longitud y riqueza del prompt"""
 
 
 
 
 
 
 
 
32
  score = 0
33
+ breakdown = {}
34
 
35
+ # Simple scoring basado en características del prompt final
36
+ if len(prompt) > 50:
 
 
 
37
  score += 25
38
+ breakdown["length"] = 25
39
 
40
+ if "Shot on" in prompt:
 
41
  score += 25
42
+ breakdown["camera"] = 25
43
+
44
+ if "lighting" in prompt.lower():
45
  score += 25
46
+ breakdown["lighting"] = 25
47
+
48
+ if any(word in prompt.lower() for word in ["photography", "cinematic", "professional"]):
49
+ score += 25
50
+ breakdown["style"] = 25
51
 
52
+ return min(score, 100), breakdown