Malaji71 commited on
Commit
ce445c7
·
verified ·
1 Parent(s): 2979863

Update analyzer.py

Browse files
Files changed (1) hide show
  1. analyzer.py +569 -39
analyzer.py CHANGED
@@ -1,60 +1,590 @@
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
- "demographic": {"age_category": None, "age_confidence": 0, "gender": None, "cultural_religious": []},
23
- "facial_ultra": {"eyes": [], "eyebrows": [], "nose": [], "mouth": [], "facial_hair": [], "skin": [], "structure": []},
24
- "emotional_state": {"primary_emotion": None, "emotion_confidence": 0, "micro_expressions": [], "overall_demeanor": []},
25
- "clothing_accessories": {"headwear": [], "eyewear": [], "clothing": [], "accessories": []},
26
- "environmental": {"setting_type": None, "specific_location": None, "lighting_analysis": [], "atmosphere": []},
27
- "pose_composition": {"body_language": [], "head_position": [], "eye_contact": [], "posture": []},
28
- "technical_analysis": {"shot_type": None, "angle": None, "lighting_setup": None, "suggested_equipment": {}},
29
- "intelligence_metrics": {"total_features_detected": 0, "analysis_depth_score": 0, "cultural_awareness_score": 0, "technical_optimization_score": 0}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
  def build_ultra_supreme_prompt(self, ultra_analysis: Dict[str, Any], clip_results: List[str]) -> str:
33
- """NO construye nada - este método ya no se usa con el nuevo pipeline"""
34
- # Este método existe solo por compatibilidad
35
- # El verdadero trabajo se hace en optimizer.py con apply_flux_rules()
36
- return clip_results[0] if clip_results else ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
  def calculate_ultra_supreme_score(self, prompt: str, ultra_analysis: Dict[str, Any]) -> Tuple[int, Dict[str, int]]:
39
- """Calcula score basado en la longitud y riqueza del prompt"""
40
- score = 0
41
  breakdown = {}
42
 
43
- # Simple scoring basado en características del prompt final
44
- if len(prompt) > 50:
45
- score += 25
46
- breakdown["length"] = 25
47
 
48
- if "Shot on" in prompt:
49
- score += 25
50
- breakdown["camera"] = 25
51
-
52
- if "lighting" in prompt.lower():
53
- score += 25
54
- breakdown["lighting"] = 25
55
-
56
- if any(word in prompt.lower() for word in ["photography", "cinematic", "professional"]):
57
- score += 25
58
- breakdown["style"] = 25
 
59
 
60
- return min(score, 100), breakdown
 
1
  """
2
+ Ultra Supreme Analyzer - Complete Multi-Model Analysis
3
+ Integrates multiple specialized models for comprehensive image analysis
4
  """
5
 
6
  import re
7
+ import logging
8
+ import spaces
9
+ import torch
10
+ import cv2
11
+ import numpy as np
12
+ from typing import Dict, List, Any, Tuple, Optional
13
+ from PIL import Image
14
+
15
+ # Deep learning models for specialized analysis
16
+ try:
17
+ from deepface import DeepFace
18
+ DEEPFACE_AVAILABLE = True
19
+ except:
20
+ DEEPFACE_AVAILABLE = False
21
+
22
+ try:
23
+ import mediapipe as mp
24
+ MEDIAPIPE_AVAILABLE = True
25
+ except:
26
+ MEDIAPIPE_AVAILABLE = False
27
+
28
+ try:
29
+ from transformers import pipeline
30
+ TRANSFORMERS_AVAILABLE = True
31
+ except:
32
+ TRANSFORMERS_AVAILABLE = False
33
+
34
+ from constants import (
35
+ FORBIDDEN_ELEMENTS, MICRO_AGE_INDICATORS, ULTRA_FACIAL_ANALYSIS,
36
+ EMOTION_MICRO_EXPRESSIONS, CULTURAL_RELIGIOUS_ULTRA, CLOTHING_ACCESSORIES_ULTRA,
37
+ ENVIRONMENTAL_ULTRA_ANALYSIS, POSE_BODY_LANGUAGE_ULTRA, COMPOSITION_PHOTOGRAPHY_ULTRA,
38
+ TECHNICAL_PHOTOGRAPHY_ULTRA, QUALITY_DESCRIPTORS_ULTRA, GENDER_INDICATORS
39
+ )
40
+
41
+ logger = logging.getLogger(__name__)
42
+
43
 
44
  class UltraSupremeAnalyzer:
45
+ """Complete analyzer with multiple specialized models"""
46
 
47
  def __init__(self):
48
+ self.face_cascade = None
49
+ self.pose_detector = None
50
+ self.emotion_classifier = None
51
+ self.scene_classifier = None
52
+ self.models_initialized = False
53
+
54
+ def _initialize_models(self):
55
+ """Lazy initialization of models"""
56
+ if self.models_initialized:
57
+ return
58
+
59
+ try:
60
+ # OpenCV face detector (lightweight)
61
+ self.face_cascade = cv2.CascadeClassifier(
62
+ cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
63
+ )
64
+
65
+ # MediaPipe pose detector
66
+ if MEDIAPIPE_AVAILABLE:
67
+ self.mp_pose = mp.solutions.pose
68
+ self.pose_detector = self.mp_pose.Pose(
69
+ static_image_mode=True,
70
+ min_detection_confidence=0.5
71
+ )
72
+
73
+ # Emotion classifier from transformers
74
+ if TRANSFORMERS_AVAILABLE:
75
+ self.emotion_classifier = pipeline(
76
+ "image-classification",
77
+ model="dima806/facial_emotions_image_detection"
78
+ )
79
+
80
+ self.models_initialized = True
81
+ logger.info("Additional analysis models initialized")
82
+
83
+ except Exception as e:
84
+ logger.error(f"Error initializing models: {e}")
85
+ self.models_initialized = False
86
 
87
+ @spaces.GPU(duration=30)
88
+ def ultra_supreme_analysis(self, image: Any, clip_fast: str, clip_classic: str, clip_best: str) -> Dict[str, Any]:
89
+ """Complete analysis using all available models"""
90
+
91
+ # Initialize models if needed
92
+ self._initialize_models()
93
+
94
+ # Start with CLIP analysis
95
+ clip_analysis = self._parse_clip_results(clip_fast, clip_classic, clip_best)
96
+
97
+ # Convert image for processing
98
+ if isinstance(image, Image.Image):
99
+ img_array = np.array(image)
100
+ img_rgb = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR)
101
+ else:
102
+ img_rgb = image
103
+ image = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
104
+
105
+ # Initialize complete analysis structure
106
+ analysis = {
107
  "clip_fast": clip_fast,
108
+ "clip_classic": clip_classic,
109
  "clip_best": clip_best,
110
  "full_description": f"{clip_fast} {clip_classic} {clip_best}",
111
+ "demographic": {
112
+ "age_category": None,
113
+ "age_confidence": 0,
114
+ "gender": None,
115
+ "gender_confidence": 0,
116
+ "cultural_religious": []
117
+ },
118
+ "facial_ultra": {
119
+ "eyes": [],
120
+ "eyebrows": [],
121
+ "nose": [],
122
+ "mouth": [],
123
+ "facial_hair": [],
124
+ "skin": [],
125
+ "structure": [],
126
+ "face_count": 0,
127
+ "face_locations": []
128
+ },
129
+ "emotional_state": {
130
+ "primary_emotion": None,
131
+ "emotion_confidence": 0,
132
+ "emotion_distribution": {},
133
+ "micro_expressions": [],
134
+ "overall_demeanor": []
135
+ },
136
+ "clothing_accessories": {
137
+ "headwear": [],
138
+ "eyewear": [],
139
+ "clothing": [],
140
+ "accessories": [],
141
+ "style": []
142
+ },
143
+ "environmental": {
144
+ "setting_type": None,
145
+ "specific_location": None,
146
+ "lighting_analysis": [],
147
+ "atmosphere": [],
148
+ "objects": []
149
+ },
150
+ "pose_composition": {
151
+ "body_language": [],
152
+ "head_position": [],
153
+ "eye_contact": [],
154
+ "posture": [],
155
+ "gesture": [],
156
+ "pose_confidence": 0
157
+ },
158
+ "technical_analysis": {
159
+ "shot_type": None,
160
+ "angle": None,
161
+ "lighting_setup": None,
162
+ "composition": [],
163
+ "suggested_equipment": {}
164
+ },
165
+ "intelligence_metrics": {
166
+ "total_features_detected": 0,
167
+ "analysis_depth_score": 0,
168
+ "cultural_awareness_score": 0,
169
+ "technical_optimization_score": 0,
170
+ "model_confidence_average": 0
171
+ }
172
+ }
173
+
174
+ # Merge CLIP analysis
175
+ analysis = self._merge_analysis(analysis, clip_analysis)
176
+
177
+ # Face detection and analysis
178
+ face_analysis = self._analyze_faces(img_rgb, image)
179
+ analysis = self._merge_analysis(analysis, face_analysis)
180
+
181
+ # Pose analysis
182
+ if MEDIAPIPE_AVAILABLE:
183
+ pose_analysis = self._analyze_pose(image)
184
+ analysis = self._merge_analysis(analysis, pose_analysis)
185
+
186
+ # Emotion analysis
187
+ if TRANSFORMERS_AVAILABLE and analysis["facial_ultra"]["face_count"] > 0:
188
+ emotion_analysis = self._analyze_emotions(image)
189
+ analysis = self._merge_analysis(analysis, emotion_analysis)
190
+
191
+ # Scene and environment analysis
192
+ scene_analysis = self._analyze_scene(clip_analysis)
193
+ analysis = self._merge_analysis(analysis, scene_analysis)
194
+
195
+ # Calculate intelligence metrics
196
+ analysis = self._calculate_intelligence_metrics(analysis)
197
+
198
+ return analysis
199
+
200
+ def _parse_clip_results(self, clip_fast: str, clip_classic: str, clip_best: str) -> Dict[str, Any]:
201
+ """Parse CLIP results for structured information"""
202
+ combined_text = f"{clip_fast} {clip_classic} {clip_best}".lower()
203
+
204
+ analysis = {
205
+ "demographic": {},
206
+ "facial_ultra": {},
207
+ "emotional_state": {},
208
+ "clothing_accessories": {},
209
+ "environmental": {},
210
+ "pose_composition": {},
211
+ "technical_analysis": {}
212
  }
213
+
214
+ # Gender detection
215
+ for gender, indicators in GENDER_INDICATORS.items():
216
+ if any(indicator in combined_text for indicator in indicators):
217
+ analysis["demographic"]["gender"] = gender
218
+ analysis["demographic"]["gender_confidence"] = 0.8
219
+ break
220
+
221
+ # Age detection
222
+ for age_category, indicators in MICRO_AGE_INDICATORS.items():
223
+ if any(indicator in combined_text for indicator in indicators):
224
+ analysis["demographic"]["age_category"] = age_category
225
+ analysis["demographic"]["age_confidence"] = 0.7
226
+ break
227
+
228
+ # Facial features
229
+ for feature_type, features in ULTRA_FACIAL_ANALYSIS.items():
230
+ if isinstance(features, dict):
231
+ for sub_type, sub_features in features.items():
232
+ found = [f for f in sub_features if f in combined_text]
233
+ if found and feature_type in analysis["facial_ultra"]:
234
+ analysis["facial_ultra"][feature_type] = found
235
+ else:
236
+ found = [f for f in features if f in combined_text]
237
+ if found:
238
+ analysis["facial_ultra"][feature_type] = found
239
+
240
+ # Emotions
241
+ all_emotions = EMOTION_MICRO_EXPRESSIONS["primary_emotions"] + EMOTION_MICRO_EXPRESSIONS["complex_emotions"]
242
+ found_emotions = [e for e in all_emotions if e in combined_text]
243
+ if found_emotions:
244
+ analysis["emotional_state"]["primary_emotion"] = found_emotions[0]
245
+ analysis["emotional_state"]["micro_expressions"] = found_emotions
246
+
247
+ # Environment
248
+ for setting_type, settings in ENVIRONMENTAL_ULTRA_ANALYSIS["indoor_settings"].items():
249
+ if any(s in combined_text for s in settings):
250
+ analysis["environmental"]["setting_type"] = f"indoor_{setting_type}"
251
+ break
252
+
253
+ for setting_type, settings in ENVIRONMENTAL_ULTRA_ANALYSIS["outdoor_settings"].items():
254
+ if any(s in combined_text for s in settings):
255
+ analysis["environmental"]["setting_type"] = f"outdoor_{setting_type}"
256
+ break
257
+
258
+ # Technical analysis
259
+ for shot_type in COMPOSITION_PHOTOGRAPHY_ULTRA["shot_types"]:
260
+ if shot_type in combined_text:
261
+ analysis["technical_analysis"]["shot_type"] = shot_type
262
+ break
263
+
264
+ return analysis
265
+
266
+ def _analyze_faces(self, img_bgr: np.ndarray, img_pil: Image.Image) -> Dict[str, Any]:
267
+ """Analyze faces using OpenCV and DeepFace"""
268
+ analysis = {"facial_ultra": {}, "demographic": {}, "emotional_state": {}}
269
+
270
+ # OpenCV face detection
271
+ gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
272
+ faces = self.face_cascade.detectMultiScale(gray, 1.1, 4)
273
+
274
+ analysis["facial_ultra"]["face_count"] = len(faces)
275
+ analysis["facial_ultra"]["face_locations"] = faces.tolist() if len(faces) > 0 else []
276
+
277
+ # DeepFace analysis for the first detected face
278
+ if DEEPFACE_AVAILABLE and len(faces) > 0:
279
+ try:
280
+ # Analyze with DeepFace
281
+ results = DeepFace.analyze(
282
+ img_path=np.array(img_pil),
283
+ actions=['age', 'gender', 'emotion', 'race'],
284
+ enforce_detection=False,
285
+ silent=True
286
+ )
287
+
288
+ if isinstance(results, list):
289
+ results = results[0]
290
+
291
+ # Extract demographics
292
+ analysis["demographic"]["age_category"] = self._age_to_category(results.get('age', 0))
293
+ analysis["demographic"]["age_confidence"] = 0.85
294
+ analysis["demographic"]["gender"] = results.get('dominant_gender', '').lower()
295
+ analysis["demographic"]["gender_confidence"] = results.get('gender', {}).get(
296
+ results.get('dominant_gender', ''), 0
297
+ ) / 100.0
298
+
299
+ # Extract emotions
300
+ emotions = results.get('emotion', {})
301
+ if emotions:
302
+ sorted_emotions = sorted(emotions.items(), key=lambda x: x[1], reverse=True)
303
+ analysis["emotional_state"]["primary_emotion"] = sorted_emotions[0][0]
304
+ analysis["emotional_state"]["emotion_confidence"] = sorted_emotions[0][1] / 100.0
305
+ analysis["emotional_state"]["emotion_distribution"] = {
306
+ k: v/100.0 for k, v in emotions.items()
307
+ }
308
+
309
+ except Exception as e:
310
+ logger.warning(f"DeepFace analysis failed: {e}")
311
+
312
+ return analysis
313
+
314
+ def _analyze_pose(self, image: Image.Image) -> Dict[str, Any]:
315
+ """Analyze body pose using MediaPipe"""
316
+ analysis = {"pose_composition": {}}
317
+
318
+ if not MEDIAPIPE_AVAILABLE or not self.pose_detector:
319
+ return analysis
320
+
321
+ try:
322
+ # Convert PIL to RGB array
323
+ image_rgb = np.array(image)
324
+
325
+ # Process the image
326
+ results = self.pose_detector.process(image_rgb)
327
+
328
+ if results.pose_landmarks:
329
+ landmarks = results.pose_landmarks.landmark
330
+
331
+ # Analyze head position
332
+ nose = landmarks[self.mp_pose.PoseLandmark.NOSE]
333
+ left_eye = landmarks[self.mp_pose.PoseLandmark.LEFT_EYE]
334
+ right_eye = landmarks[self.mp_pose.PoseLandmark.RIGHT_EYE]
335
+
336
+ # Calculate head tilt
337
+ eye_diff_y = abs(left_eye.y - right_eye.y)
338
+ if eye_diff_y > 0.02:
339
+ analysis["pose_composition"]["head_position"] = ["head tilted"]
340
+ else:
341
+ analysis["pose_composition"]["head_position"] = ["head straight"]
342
+
343
+ # Analyze posture
344
+ left_shoulder = landmarks[self.mp_pose.PoseLandmark.LEFT_SHOULDER]
345
+ right_shoulder = landmarks[self.mp_pose.PoseLandmark.RIGHT_SHOULDER]
346
+ shoulder_diff_y = abs(left_shoulder.y - right_shoulder.y)
347
+
348
+ if shoulder_diff_y < 0.02:
349
+ analysis["pose_composition"]["posture"] = ["upright posture", "balanced stance"]
350
+ else:
351
+ analysis["pose_composition"]["posture"] = ["asymmetric posture"]
352
+
353
+ # Confidence based on visibility
354
+ visibility_scores = [l.visibility for l in landmarks]
355
+ analysis["pose_composition"]["pose_confidence"] = np.mean(visibility_scores)
356
+
357
+ # Body language interpretation
358
+ if nose.y < 0.3:
359
+ analysis["pose_composition"]["body_language"].append("confident stance")
360
+
361
+ except Exception as e:
362
+ logger.warning(f"Pose analysis failed: {e}")
363
+
364
+ return analysis
365
+
366
+ def _analyze_emotions(self, image: Image.Image) -> Dict[str, Any]:
367
+ """Analyze emotions using transformer model"""
368
+ analysis = {"emotional_state": {}}
369
+
370
+ if not TRANSFORMERS_AVAILABLE or not self.emotion_classifier:
371
+ return analysis
372
+
373
+ try:
374
+ # Run emotion classification
375
+ predictions = self.emotion_classifier(image)
376
+
377
+ if predictions:
378
+ # Sort by confidence
379
+ predictions.sort(key=lambda x: x['score'], reverse=True)
380
+
381
+ # Primary emotion
382
+ analysis["emotional_state"]["primary_emotion"] = predictions[0]['label'].lower()
383
+ analysis["emotional_state"]["emotion_confidence"] = predictions[0]['score']
384
+
385
+ # Emotion distribution
386
+ analysis["emotional_state"]["emotion_distribution"] = {
387
+ pred['label'].lower(): pred['score'] for pred in predictions[:5]
388
+ }
389
+
390
+ # Map to micro-expressions
391
+ primary = predictions[0]['label'].lower()
392
+ if primary in ['happy', 'joy']:
393
+ analysis["emotional_state"]["micro_expressions"] = ["smile", "positive expression"]
394
+ elif primary in ['sad', 'sorrow']:
395
+ analysis["emotional_state"]["micro_expressions"] = ["downturned mouth", "melancholic"]
396
+ elif primary in ['angry', 'disgust']:
397
+ analysis["emotional_state"]["micro_expressions"] = ["furrowed brow", "tense jaw"]
398
+ elif primary in ['surprise', 'fear']:
399
+ analysis["emotional_state"]["micro_expressions"] = ["raised eyebrows", "wide eyes"]
400
+
401
+ except Exception as e:
402
+ logger.warning(f"Emotion analysis failed: {e}")
403
+
404
+ return analysis
405
+
406
+ def _analyze_scene(self, clip_analysis: Dict[str, Any]) -> Dict[str, Any]:
407
+ """Analyze scene and environment from CLIP results"""
408
+ analysis = {"environmental": clip_analysis.get("environmental", {})}
409
+
410
+ # Lighting analysis based on CLIP description
411
+ combined_text = clip_analysis.get("full_description", "").lower()
412
+
413
+ lighting_keywords = {
414
+ "natural light": ["sunlight", "daylight", "outdoor", "sunny"],
415
+ "artificial light": ["indoor", "lamp", "fluorescent", "led"],
416
+ "dramatic lighting": ["dramatic", "moody", "contrast", "shadow"],
417
+ "soft lighting": ["soft", "diffused", "gentle", "even"]
418
+ }
419
+
420
+ for light_type, keywords in lighting_keywords.items():
421
+ if any(keyword in combined_text for keyword in keywords):
422
+ analysis["environmental"]["lighting_analysis"].append(light_type)
423
+
424
+ # Atmosphere
425
+ if any(word in combined_text for word in ["professional", "formal", "business"]):
426
+ analysis["environmental"]["atmosphere"].append("professional")
427
+ if any(word in combined_text for word in ["casual", "relaxed", "informal"]):
428
+ analysis["environmental"]["atmosphere"].append("casual")
429
+ if any(word in combined_text for word in ["artistic", "creative", "abstract"]):
430
+ analysis["environmental"]["atmosphere"].append("artistic")
431
+
432
+ return analysis
433
+
434
+ def _age_to_category(self, age: int) -> str:
435
+ """Convert numeric age to category"""
436
+ if age < 2:
437
+ return "infant"
438
+ elif age < 12:
439
+ return "child"
440
+ elif age < 20:
441
+ return "teen"
442
+ elif age < 35:
443
+ return "young_adult"
444
+ elif age < 50:
445
+ return "middle_aged"
446
+ elif age < 65:
447
+ return "senior"
448
+ else:
449
+ return "elderly"
450
+
451
+ def _merge_analysis(self, base: Dict[str, Any], new: Dict[str, Any]) -> Dict[str, Any]:
452
+ """Merge analysis results"""
453
+ for key, value in new.items():
454
+ if key in base:
455
+ if isinstance(value, dict) and isinstance(base[key], dict):
456
+ base[key].update(value)
457
+ elif isinstance(value, list) and isinstance(base[key], list):
458
+ base[key].extend(value)
459
+ elif value is not None and (not isinstance(base[key], (int, float)) or base[key] == 0):
460
+ base[key] = value
461
+ return base
462
+
463
+ def _calculate_intelligence_metrics(self, analysis: Dict[str, Any]) -> Dict[str, Any]:
464
+ """Calculate intelligence metrics based on analysis completeness"""
465
+ metrics = analysis["intelligence_metrics"]
466
+
467
+ # Count detected features
468
+ total_features = 0
469
+ confidence_scores = []
470
+
471
+ # Demographic features
472
+ if analysis["demographic"]["age_category"]:
473
+ total_features += 1
474
+ confidence_scores.append(analysis["demographic"]["age_confidence"])
475
+ if analysis["demographic"]["gender"]:
476
+ total_features += 1
477
+ confidence_scores.append(analysis["demographic"]["gender_confidence"])
478
+
479
+ # Facial features
480
+ for feature in ["eyes", "eyebrows", "nose", "mouth", "facial_hair", "skin", "structure"]:
481
+ if analysis["facial_ultra"].get(feature):
482
+ total_features += len(analysis["facial_ultra"][feature])
483
+
484
+ # Emotional features
485
+ if analysis["emotional_state"]["primary_emotion"]:
486
+ total_features += 1
487
+ confidence_scores.append(analysis["emotional_state"]["emotion_confidence"])
488
+
489
+ # Pose features
490
+ if analysis["pose_composition"].get("pose_confidence", 0) > 0:
491
+ total_features += 1
492
+ confidence_scores.append(analysis["pose_composition"]["pose_confidence"])
493
+
494
+ # Environmental features
495
+ if analysis["environmental"]["setting_type"]:
496
+ total_features += 1
497
+ total_features += len(analysis["environmental"].get("lighting_analysis", []))
498
+
499
+ # Technical features
500
+ if analysis["technical_analysis"]["shot_type"]:
501
+ total_features += 1
502
+
503
+ # Calculate scores
504
+ metrics["total_features_detected"] = total_features
505
+ metrics["analysis_depth_score"] = min(100, total_features * 5)
506
+
507
+ # Cultural awareness (if religious/cultural indicators found)
508
+ if analysis["demographic"].get("cultural_religious"):
509
+ metrics["cultural_awareness_score"] = 80
510
+ else:
511
+ metrics["cultural_awareness_score"] = 40
512
+
513
+ # Technical optimization score
514
+ tech_features = sum([
515
+ 1 if analysis["technical_analysis"]["shot_type"] else 0,
516
+ len(analysis["environmental"].get("lighting_analysis", [])),
517
+ len(analysis["pose_composition"].get("posture", []))
518
+ ])
519
+ metrics["technical_optimization_score"] = min(100, tech_features * 25)
520
+
521
+ # Average confidence
522
+ if confidence_scores:
523
+ metrics["model_confidence_average"] = sum(confidence_scores) / len(confidence_scores)
524
+ else:
525
+ metrics["model_confidence_average"] = 0.5
526
+
527
+ return analysis
528
 
529
  def build_ultra_supreme_prompt(self, ultra_analysis: Dict[str, Any], clip_results: List[str]) -> str:
530
+ """Build enhanced prompt based on comprehensive analysis"""
531
+ prompt_parts = []
532
+
533
+ # Start with the best CLIP result
534
+ if clip_results:
535
+ prompt_parts.append(clip_results[0])
536
+
537
+ # Add demographic details if confident
538
+ if ultra_analysis["demographic"]["age_category"] and ultra_analysis["demographic"]["age_confidence"] > 0.7:
539
+ age_descriptors = QUALITY_DESCRIPTORS_ULTRA["based_on_age"].get(
540
+ ultra_analysis["demographic"]["age_category"], []
541
+ )
542
+ if age_descriptors:
543
+ prompt_parts.append(age_descriptors[0])
544
+
545
+ # Add emotional context
546
+ if ultra_analysis["emotional_state"]["primary_emotion"]:
547
+ emotion = ultra_analysis["emotional_state"]["primary_emotion"]
548
+ emotion_descriptors = QUALITY_DESCRIPTORS_ULTRA["based_on_emotion"].get(emotion, [])
549
+ if emotion_descriptors:
550
+ prompt_parts.append(f"{emotion_descriptors[0]} expression")
551
+
552
+ # Add technical details
553
+ if ultra_analysis["technical_analysis"]["shot_type"]:
554
+ prompt_parts.append(ultra_analysis["technical_analysis"]["shot_type"])
555
+
556
+ # Add lighting
557
+ lighting = ultra_analysis["environmental"].get("lighting_analysis", [])
558
+ if lighting:
559
+ prompt_parts.append(f"with {lighting[0]}")
560
+
561
+ # Combine parts
562
+ enhanced_prompt = ", ".join(prompt_parts)
563
+
564
+ # Clean up
565
+ enhanced_prompt = re.sub(r'\s+', ' ', enhanced_prompt)
566
+ enhanced_prompt = re.sub(r',\s*,+', ',', enhanced_prompt)
567
+
568
+ return enhanced_prompt
569
 
570
  def calculate_ultra_supreme_score(self, prompt: str, ultra_analysis: Dict[str, Any]) -> Tuple[int, Dict[str, int]]:
571
+ """Calculate comprehensive score based on multi-model analysis"""
 
572
  breakdown = {}
573
 
574
+ # Base score from prompt quality
575
+ breakdown["prompt_quality"] = min(25, len(prompt) // 10)
 
 
576
 
577
+ # Analysis depth score
578
+ breakdown["analysis_depth"] = min(25, ultra_analysis["intelligence_metrics"]["analysis_depth_score"] // 4)
579
+
580
+ # Model confidence score
581
+ avg_confidence = ultra_analysis["intelligence_metrics"]["model_confidence_average"]
582
+ breakdown["model_confidence"] = int(avg_confidence * 25)
583
+
584
+ # Feature richness score
585
+ total_features = ultra_analysis["intelligence_metrics"]["total_features_detected"]
586
+ breakdown["feature_richness"] = min(25, total_features * 2)
587
+
588
+ total_score = sum(breakdown.values())
589
 
590
+ return total_score, breakdown