Malaji71 commited on
Commit
3fe3e93
·
verified ·
1 Parent(s): f746366

Update processor.py

Browse files
Files changed (1) hide show
  1. processor.py +248 -92
processor.py CHANGED
@@ -1,6 +1,8 @@
1
  """
2
- Main processing logic for FLUX Prompt Optimizer
3
- Handles image analysis, prompt optimization, and scoring
 
 
4
  """
5
 
6
  import logging
@@ -9,19 +11,20 @@ from typing import Tuple, Dict, Any, Optional
9
  from PIL import Image
10
  from datetime import datetime
11
 
12
- from config import APP_CONFIG, PROCESSING_CONFIG, get_device_config
13
  from utils import (
14
  optimize_image, validate_image, apply_flux_rules,
15
  calculate_prompt_score, get_score_grade, format_analysis_report,
16
- clean_memory, safe_execute
 
17
  )
18
  from models import analyze_image
19
 
20
  logger = logging.getLogger(__name__)
21
 
22
 
23
- class FluxOptimizer:
24
- """Main optimizer class for FLUX prompt generation"""
25
 
26
  def __init__(self, model_name: str = None):
27
  self.model_name = model_name
@@ -30,17 +33,20 @@ class FluxOptimizer:
30
  "total_processed": 0,
31
  "successful_analyses": 0,
32
  "failed_analyses": 0,
33
- "average_processing_time": 0.0
 
 
34
  }
35
 
36
- logger.info(f"FluxOptimizer initialized - Device: {self.device_config['device']}")
37
 
38
- def process_image(self, image: Any) -> Tuple[str, str, str, Dict[str, Any]]:
39
  """
40
- Complete image processing pipeline
41
 
42
  Args:
43
  image: Input image (PIL, numpy array, or file path)
 
44
 
45
  Returns:
46
  Tuple of (optimized_prompt, analysis_report, score_html, metadata)
@@ -49,14 +55,17 @@ class FluxOptimizer:
49
  metadata = {
50
  "processing_time": 0.0,
51
  "success": False,
52
- "model_used": self.model_name or "auto",
53
  "device": self.device_config["device"],
 
 
 
54
  "error": None
55
  }
56
 
57
  try:
58
  # Step 1: Validate and optimize input image
59
- logger.info("Starting image processing pipeline...")
60
 
61
  if not validate_image(image):
62
  error_msg = "Invalid or unsupported image format"
@@ -71,36 +80,56 @@ class FluxOptimizer:
71
 
72
  logger.info(f"Image optimized to size: {optimized_image.size}")
73
 
74
- # Step 2: Analyze image with selected model
75
- logger.info("Running image analysis...")
76
  analysis_success, analysis_result = safe_execute(
77
  analyze_image,
78
  optimized_image,
79
- self.model_name
 
80
  )
81
 
82
  if not analysis_success:
83
- error_msg = f"Image analysis failed: {analysis_result}"
84
  logger.error(error_msg)
85
  return self._create_error_response(error_msg, metadata)
86
 
87
  description, analysis_metadata = analysis_result
88
- logger.info(f"Analysis complete: {len(description)} characters")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
- # Step 3: Apply FLUX optimization rules
91
- logger.info("Applying FLUX optimization rules...")
92
- optimized_prompt = apply_flux_rules(description)
 
 
 
93
 
94
  if not optimized_prompt:
95
- optimized_prompt = "A professional photograph"
96
- logger.warning("Empty prompt after optimization, using fallback")
97
 
98
- # Step 4: Calculate quality score
99
- logger.info("Calculating quality score...")
100
  score, score_breakdown = calculate_prompt_score(optimized_prompt, analysis_metadata)
101
  grade_info = get_score_grade(score)
102
 
103
- # Step 5: Generate analysis report
104
  processing_time = time.time() - start_time
105
  metadata.update({
106
  "processing_time": processing_time,
@@ -108,26 +137,29 @@ class FluxOptimizer:
108
  "prompt_length": len(optimized_prompt),
109
  "score": score,
110
  "grade": grade_info["grade"],
111
- "analysis_metadata": analysis_metadata
 
 
 
112
  })
113
 
114
- analysis_report = self._generate_detailed_report(
115
  optimized_prompt, analysis_metadata, score,
116
- score_breakdown, processing_time
117
  )
118
 
119
- # Step 6: Create score HTML
120
- score_html = self._generate_score_html(score, grade_info)
121
 
122
  # Update statistics
123
  self._update_stats(processing_time, True)
124
 
125
- logger.info(f"Processing complete - Score: {score}, Time: {processing_time:.1f}s")
126
  return optimized_prompt, analysis_report, score_html, metadata
127
 
128
  except Exception as e:
129
  processing_time = time.time() - start_time
130
- error_msg = f"Unexpected error in processing pipeline: {str(e)}"
131
  logger.error(error_msg, exc_info=True)
132
 
133
  metadata.update({
@@ -142,74 +174,122 @@ class FluxOptimizer:
142
  # Always clean up memory
143
  clean_memory()
144
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  def _create_error_response(self, error_msg: str, metadata: Dict[str, Any]) -> Tuple[str, str, str, Dict[str, Any]]:
146
  """Create standardized error response"""
147
- error_prompt = "❌ Processing failed"
148
- error_report = f"**Error:** {error_msg}\n\nPlease try with a different image or check the logs for more details."
149
- error_html = self._generate_score_html(0, get_score_grade(0))
 
 
 
 
 
 
 
 
 
150
 
151
  metadata["success"] = False
152
  metadata["error"] = error_msg
153
 
154
  return error_prompt, error_report, error_html, metadata
155
 
156
- def _generate_detailed_report(self, prompt: str, analysis_metadata: Dict[str, Any],
157
  score: int, breakdown: Dict[str, int],
158
- processing_time: float) -> str:
159
- """Generate comprehensive analysis report"""
160
 
161
  model_used = analysis_metadata.get("model", "Unknown")
162
  device_used = analysis_metadata.get("device", self.device_config["device"])
163
  confidence = analysis_metadata.get("confidence", 0.0)
 
 
164
 
165
  # Device status emoji
166
  device_emoji = "⚡" if device_used == "cuda" else "💻"
 
167
 
168
- report = f"""**Analysis Complete**
169
  **Processing:** {device_emoji} {device_used.upper()} • {processing_time:.1f}s • Model: {model_used}
170
- **Score:** {score}/100 • Confidence: {confidence:.0%}
171
 
172
- **Score Breakdown:**
173
- • **Prompt Quality:** {breakdown.get('prompt_quality', 0)}/30 - Content detail and description
174
- • **Technical Details:** {breakdown.get('technical_details', 0)}/25 - Camera and photography settings
175
- • **Artistic Value:** {breakdown.get('artistic_value', 0)}/25 - Creative elements
176
- • **FLUX Optimization:** {breakdown.get('flux_optimization', 0)}/20 - Platform optimizations
177
 
178
- **Analysis Summary:**
179
- **Description Length:** {len(prompt)} characters
180
- **Model Used:** {analysis_metadata.get('model', 'N/A')}
 
181
 
182
- **Applied Optimizations:**
183
- Camera settings added
184
- Lighting configuration applied
185
- ✅ Technical parameters optimized
186
- FLUX rules implemented
187
- Content cleaned and enhanced
 
188
 
189
- **Performance:**
190
  • **Processing Time:** {processing_time:.1f}s
191
  • **Device:** {device_used.upper()}
192
  • **Model Confidence:** {confidence:.0%}
 
 
193
 
194
- **Frame 0 Laboratory for MIA**"""
 
 
 
 
 
 
195
 
196
  return report
197
 
198
- def _generate_score_html(self, score: int, grade_info: Dict[str, str]) -> str:
199
- """Generate HTML for score display"""
 
 
 
 
 
 
 
 
 
 
 
 
200
 
201
  html = f'''
202
  <div style="text-align: center; padding: 2rem; background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%); border: 3px solid {grade_info["color"]}; border-radius: 16px; margin: 1rem 0; box-shadow: 0 8px 25px -5px rgba(0, 0, 0, 0.1);">
 
203
  <div style="font-size: 3rem; font-weight: 800; color: {grade_info["color"]}; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.1);">{score}</div>
204
  <div style="font-size: 1.25rem; color: #15803d; margin: 0.5rem 0; text-transform: uppercase; letter-spacing: 0.1em; font-weight: 700;">{grade_info["grade"]}</div>
205
- <div style="font-size: 1rem; color: #15803d; margin: 0; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 500;">FLUX Quality Score</div>
 
206
  </div>
207
  '''
208
 
209
  return html
210
 
211
  def _update_stats(self, processing_time: float, success: bool) -> None:
212
- """Update processing statistics"""
213
  self.processing_stats["total_processed"] += 1
214
 
215
  if success:
@@ -225,16 +305,19 @@ class FluxOptimizer:
225
  (current_avg * (total_count - 1) + processing_time) / total_count
226
  )
227
 
228
- def get_stats(self) -> Dict[str, Any]:
229
- """Get current processing statistics"""
230
  stats = self.processing_stats.copy()
231
 
232
  if stats["total_processed"] > 0:
233
  stats["success_rate"] = stats["successful_analyses"] / stats["total_processed"]
 
234
  else:
235
  stats["success_rate"] = 0.0
 
236
 
237
  stats["device_info"] = self.device_config
 
238
 
239
  return stats
240
 
@@ -244,89 +327,162 @@ class FluxOptimizer:
244
  "total_processed": 0,
245
  "successful_analyses": 0,
246
  "failed_analyses": 0,
247
- "average_processing_time": 0.0
 
 
248
  }
249
- logger.info("Processing statistics reset")
250
 
251
 
252
- class BatchProcessor:
253
- """Handle batch processing of multiple images"""
254
 
255
- def __init__(self, optimizer: FluxOptimizer):
256
  self.optimizer = optimizer
257
  self.batch_results = []
 
 
 
 
 
 
 
258
 
259
- def process_batch(self, images: list) -> list:
260
- """Process multiple images in batch"""
261
  results = []
 
 
 
 
262
 
263
  for i, image in enumerate(images):
264
- logger.info(f"Processing batch item {i+1}/{len(images)}")
265
 
266
  try:
267
- result = self.optimizer.process_image(image)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  results.append({
269
  "index": i,
270
- "success": result[3]["success"],
271
- "result": result
 
 
272
  })
273
 
274
  except Exception as e:
275
- logger.error(f"Batch item {i} failed: {e}")
276
  results.append({
277
  "index": i,
278
  "success": False,
279
- "error": str(e)
 
 
280
  })
281
 
 
 
 
 
 
 
 
282
  self.batch_results = results
 
 
283
  return results
284
 
285
- def get_batch_summary(self) -> Dict[str, Any]:
286
- """Get summary of batch processing results"""
287
  if not self.batch_results:
288
- return {"total": 0, "successful": 0, "failed": 0}
289
 
290
  successful = sum(1 for r in self.batch_results if r["success"])
291
  total = len(self.batch_results)
292
 
293
- return {
294
  "total": total,
295
  "successful": successful,
296
  "failed": total - successful,
297
- "success_rate": successful / total if total > 0 else 0.0
 
 
 
298
  }
 
 
299
 
300
 
301
- # Global optimizer instance
302
- flux_optimizer = FluxOptimizer()
303
 
304
 
305
- def process_image_simple(image: Any, model_name: str = None) -> Tuple[str, str, str]:
306
  """
307
- Simple interface for image processing
308
 
309
  Args:
310
  image: Input image
311
  model_name: Optional model name
 
312
 
313
  Returns:
314
  Tuple of (prompt, report, score_html)
315
  """
316
- if model_name and model_name != flux_optimizer.model_name:
317
  # Create temporary optimizer with specified model
318
- temp_optimizer = FluxOptimizer(model_name)
319
- prompt, report, score_html, _ = temp_optimizer.process_image(image)
320
  else:
321
- prompt, report, score_html, _ = flux_optimizer.process_image(image)
322
 
323
  return prompt, report, score_html
324
 
325
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
  # Export main components
327
  __all__ = [
328
- "FluxOptimizer",
329
- "BatchProcessor",
330
- "flux_optimizer",
331
- "process_image_simple"
 
 
332
  ]
 
1
  """
2
+ Main processing logic for Phramer AI
3
+ By Pariente AI, for MIA TV Series
4
+
5
+ Enhanced image analysis with professional cinematography integration and multi-engine optimization
6
  """
7
 
8
  import logging
 
11
  from PIL import Image
12
  from datetime import datetime
13
 
14
+ from config import APP_CONFIG, PROCESSING_CONFIG, get_device_config, PROFESSIONAL_PHOTOGRAPHY_CONFIG
15
  from utils import (
16
  optimize_image, validate_image, apply_flux_rules,
17
  calculate_prompt_score, get_score_grade, format_analysis_report,
18
+ clean_memory, safe_execute, detect_scene_type_from_analysis,
19
+ enhance_prompt_with_cinematography_knowledge
20
  )
21
  from models import analyze_image
22
 
23
  logger = logging.getLogger(__name__)
24
 
25
 
26
+ class PhramerlAIOptimizer:
27
+ """Main optimizer class for Phramer AI prompt generation with cinematography integration"""
28
 
29
  def __init__(self, model_name: str = None):
30
  self.model_name = model_name
 
33
  "total_processed": 0,
34
  "successful_analyses": 0,
35
  "failed_analyses": 0,
36
+ "average_processing_time": 0.0,
37
+ "cinematography_enhancements": 0,
38
+ "scene_types_detected": {}
39
  }
40
 
41
+ logger.info(f"Phramer AI Optimizer initialized - Device: {self.device_config['device']}")
42
 
43
+ def process_image(self, image: Any, analysis_type: str = "multiengine") -> Tuple[str, str, str, Dict[str, Any]]:
44
  """
45
+ Complete image processing pipeline with cinematography enhancement
46
 
47
  Args:
48
  image: Input image (PIL, numpy array, or file path)
49
+ analysis_type: Type of analysis ("multiengine", "cinematic", "flux")
50
 
51
  Returns:
52
  Tuple of (optimized_prompt, analysis_report, score_html, metadata)
 
55
  metadata = {
56
  "processing_time": 0.0,
57
  "success": False,
58
+ "model_used": self.model_name or "bagel-professional",
59
  "device": self.device_config["device"],
60
+ "analysis_type": analysis_type,
61
+ "cinematography_enhanced": False,
62
+ "scene_type": "unknown",
63
  "error": None
64
  }
65
 
66
  try:
67
  # Step 1: Validate and optimize input image
68
+ logger.info(f"Starting Phramer AI processing pipeline - Analysis type: {analysis_type}")
69
 
70
  if not validate_image(image):
71
  error_msg = "Invalid or unsupported image format"
 
80
 
81
  logger.info(f"Image optimized to size: {optimized_image.size}")
82
 
83
+ # Step 2: Enhanced image analysis with cinematography context
84
+ logger.info("Running enhanced BAGEL analysis with cinematography integration...")
85
  analysis_success, analysis_result = safe_execute(
86
  analyze_image,
87
  optimized_image,
88
+ self.model_name,
89
+ analysis_type
90
  )
91
 
92
  if not analysis_success:
93
+ error_msg = f"Enhanced image analysis failed: {analysis_result}"
94
  logger.error(error_msg)
95
  return self._create_error_response(error_msg, metadata)
96
 
97
  description, analysis_metadata = analysis_result
98
+ logger.info(f"Enhanced analysis complete: {len(description)} characters")
99
+
100
+ # Step 3: Detect scene type and apply cinematography enhancements
101
+ scene_type = detect_scene_type_from_analysis(analysis_metadata)
102
+ metadata["scene_type"] = scene_type
103
+
104
+ # Update scene statistics
105
+ if scene_type in self.processing_stats["scene_types_detected"]:
106
+ self.processing_stats["scene_types_detected"][scene_type] += 1
107
+ else:
108
+ self.processing_stats["scene_types_detected"][scene_type] = 1
109
+
110
+ logger.info(f"Scene type detected: {scene_type}")
111
+
112
+ # Step 4: Apply enhanced FLUX optimization with cinematography knowledge
113
+ logger.info("Applying enhanced multi-engine optimization...")
114
+ optimized_prompt = apply_flux_rules(description, analysis_metadata)
115
 
116
+ # Step 5: Additional cinematography enhancement if enabled
117
+ if PROFESSIONAL_PHOTOGRAPHY_CONFIG.get("enable_expert_analysis", True):
118
+ logger.info("Applying professional cinematography enhancement...")
119
+ optimized_prompt = enhance_prompt_with_cinematography_knowledge(optimized_prompt, scene_type)
120
+ metadata["cinematography_enhanced"] = True
121
+ self.processing_stats["cinematography_enhancements"] += 1
122
 
123
  if not optimized_prompt:
124
+ optimized_prompt = "A professional cinematic photograph with technical excellence"
125
+ logger.warning("Empty prompt after optimization, using cinematography fallback")
126
 
127
+ # Step 6: Calculate enhanced quality score
128
+ logger.info("Calculating professional quality score...")
129
  score, score_breakdown = calculate_prompt_score(optimized_prompt, analysis_metadata)
130
  grade_info = get_score_grade(score)
131
 
132
+ # Step 7: Generate comprehensive analysis report
133
  processing_time = time.time() - start_time
134
  metadata.update({
135
  "processing_time": processing_time,
 
137
  "prompt_length": len(optimized_prompt),
138
  "score": score,
139
  "grade": grade_info["grade"],
140
+ "analysis_metadata": analysis_metadata,
141
+ "score_breakdown": score_breakdown,
142
+ "has_camera_suggestion": analysis_metadata.get("has_camera_suggestion", False),
143
+ "professional_enhancement": analysis_metadata.get("professional_enhancement", False)
144
  })
145
 
146
+ analysis_report = self._generate_enhanced_report(
147
  optimized_prompt, analysis_metadata, score,
148
+ score_breakdown, processing_time, scene_type
149
  )
150
 
151
+ # Step 8: Create enhanced score HTML
152
+ score_html = self._generate_enhanced_score_html(score, grade_info, scene_type)
153
 
154
  # Update statistics
155
  self._update_stats(processing_time, True)
156
 
157
+ logger.info(f"Phramer AI processing complete - Scene: {scene_type}, Score: {score}, Time: {processing_time:.1f}s")
158
  return optimized_prompt, analysis_report, score_html, metadata
159
 
160
  except Exception as e:
161
  processing_time = time.time() - start_time
162
+ error_msg = f"Unexpected error in Phramer AI pipeline: {str(e)}"
163
  logger.error(error_msg, exc_info=True)
164
 
165
  metadata.update({
 
174
  # Always clean up memory
175
  clean_memory()
176
 
177
+ def process_for_cinematic(self, image: Any) -> Tuple[str, str, str, Dict[str, Any]]:
178
+ """Process image specifically for cinematic/MIA TV Series production"""
179
+ return self.process_image(image, analysis_type="cinematic")
180
+
181
+ def process_for_flux(self, image: Any) -> Tuple[str, str, str, Dict[str, Any]]:
182
+ """Process image specifically for FLUX generation"""
183
+ return self.process_image(image, analysis_type="flux")
184
+
185
+ def process_for_multiengine(self, image: Any) -> Tuple[str, str, str, Dict[str, Any]]:
186
+ """Process image for multi-engine compatibility (Flux, Midjourney, etc.)"""
187
+ return self.process_image(image, analysis_type="multiengine")
188
+
189
  def _create_error_response(self, error_msg: str, metadata: Dict[str, Any]) -> Tuple[str, str, str, Dict[str, Any]]:
190
  """Create standardized error response"""
191
+ error_prompt = "❌ Phramer AI processing failed"
192
+ error_report = f"""**Error:** {error_msg}
193
+
194
+ **Troubleshooting:**
195
+ • Verify image format (JPG, PNG, WebP)
196
+ • Check image size (max 1024px)
197
+ • Ensure stable internet connection
198
+ • Try with a different image
199
+
200
+ **Support:** Contact Pariente AI technical team"""
201
+
202
+ error_html = self._generate_enhanced_score_html(0, get_score_grade(0), "error")
203
 
204
  metadata["success"] = False
205
  metadata["error"] = error_msg
206
 
207
  return error_prompt, error_report, error_html, metadata
208
 
209
+ def _generate_enhanced_report(self, prompt: str, analysis_metadata: Dict[str, Any],
210
  score: int, breakdown: Dict[str, int],
211
+ processing_time: float, scene_type: str) -> str:
212
+ """Generate comprehensive analysis report with cinematography insights"""
213
 
214
  model_used = analysis_metadata.get("model", "Unknown")
215
  device_used = analysis_metadata.get("device", self.device_config["device"])
216
  confidence = analysis_metadata.get("confidence", 0.0)
217
+ has_cinema_context = analysis_metadata.get("cinematography_context_applied", False)
218
+ camera_setup = analysis_metadata.get("camera_setup", "Not detected")
219
 
220
  # Device status emoji
221
  device_emoji = "⚡" if device_used == "cuda" else "💻"
222
+ cinema_emoji = "🎬" if has_cinema_context else "📸"
223
 
224
+ report = f"""**{cinema_emoji} PHRAMER AI ANALYSIS COMPLETE**
225
  **Processing:** {device_emoji} {device_used.upper()} • {processing_time:.1f}s • Model: {model_used}
226
+ **Score:** {score}/100 • Scene: {scene_type.replace('_', ' ').title()} • Confidence: {confidence:.0%}
227
 
228
+ **🎯 SCORE BREAKDOWN:**
229
+ • **Prompt Quality:** {breakdown.get('prompt_quality', 0)}/25 - Content detail and structure
230
+ • **Technical Details:** {breakdown.get('technical_details', 0)}/25 - Camera and equipment specs
231
+ • **Professional Cinematography:** {breakdown.get('professional_cinematography', 0)}/25 - Cinema expertise applied
232
+ • **Multi-Engine Optimization:** {breakdown.get('multi_engine_optimization', 0)}/25 - Platform compatibility
233
 
234
+ **🎬 CINEMATOGRAPHY ANALYSIS:**
235
+ **Scene Type:** {scene_type.replace('_', ' ').title()}
236
+ **Camera Setup:** {camera_setup}
237
+ **Professional Context:** {'✅ Applied' if has_cinema_context else '❌ Basic'}
238
 
239
+ **⚙️ OPTIMIZATIONS APPLIED:**
240
+ Professional camera configuration
241
+ Cinematography lighting principles
242
+ ✅ Technical specifications enhanced
243
+ Multi-engine compatibility (Flux, Midjourney)
244
+ Cinema-quality terminology
245
+ ✅ Scene-specific enhancements
246
 
247
+ **📊 PERFORMANCE METRICS:**
248
  • **Processing Time:** {processing_time:.1f}s
249
  • **Device:** {device_used.upper()}
250
  • **Model Confidence:** {confidence:.0%}
251
+ • **Prompt Length:** {len(prompt)} characters
252
+ • **Enhancement Level:** {'Professional' if has_cinema_context else 'Standard'}
253
 
254
+ **🏆 COMPATIBILITY:**
255
+ • **FLUX:** ✅ Optimized
256
+ • **Midjourney:** ✅ Compatible
257
+ • **Stable Diffusion:** ✅ Ready
258
+ • **Other Engines:** ✅ Universal format
259
+
260
+ **Pariente AI • MIA TV Series • 30+ Years Cinema Experience**"""
261
 
262
  return report
263
 
264
+ def _generate_enhanced_score_html(self, score: int, grade_info: Dict[str, str], scene_type: str) -> str:
265
+ """Generate enhanced HTML for score display with cinematography context"""
266
+
267
+ # Scene type emoji
268
+ scene_emojis = {
269
+ "cinematic": "🎬",
270
+ "portrait": "👤",
271
+ "landscape": "🏔️",
272
+ "street": "🏙️",
273
+ "architectural": "🏛️",
274
+ "commercial": "💼",
275
+ "error": "❌"
276
+ }
277
+ scene_emoji = scene_emojis.get(scene_type, "📸")
278
 
279
  html = f'''
280
  <div style="text-align: center; padding: 2rem; background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%); border: 3px solid {grade_info["color"]}; border-radius: 16px; margin: 1rem 0; box-shadow: 0 8px 25px -5px rgba(0, 0, 0, 0.1);">
281
+ <div style="font-size: 2.5rem; margin-bottom: 0.5rem;">{scene_emoji}</div>
282
  <div style="font-size: 3rem; font-weight: 800; color: {grade_info["color"]}; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.1);">{score}</div>
283
  <div style="font-size: 1.25rem; color: #15803d; margin: 0.5rem 0; text-transform: uppercase; letter-spacing: 0.1em; font-weight: 700;">{grade_info["grade"]}</div>
284
+ <div style="font-size: 0.9rem; color: #15803d; margin: 0; text-transform: capitalize; letter-spacing: 0.05em; font-weight: 500;">{scene_type.replace('_', ' ')} Scene</div>
285
+ <div style="font-size: 0.8rem; color: #15803d; margin: 0.5rem 0 0 0; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 500;">Phramer AI Quality</div>
286
  </div>
287
  '''
288
 
289
  return html
290
 
291
  def _update_stats(self, processing_time: float, success: bool) -> None:
292
+ """Update processing statistics with cinematography tracking"""
293
  self.processing_stats["total_processed"] += 1
294
 
295
  if success:
 
305
  (current_avg * (total_count - 1) + processing_time) / total_count
306
  )
307
 
308
+ def get_enhanced_stats(self) -> Dict[str, Any]:
309
+ """Get enhanced processing statistics with cinematography insights"""
310
  stats = self.processing_stats.copy()
311
 
312
  if stats["total_processed"] > 0:
313
  stats["success_rate"] = stats["successful_analyses"] / stats["total_processed"]
314
+ stats["cinematography_enhancement_rate"] = stats["cinematography_enhancements"] / stats["total_processed"]
315
  else:
316
  stats["success_rate"] = 0.0
317
+ stats["cinematography_enhancement_rate"] = 0.0
318
 
319
  stats["device_info"] = self.device_config
320
+ stats["most_common_scene"] = max(stats["scene_types_detected"].items(), key=lambda x: x[1])[0] if stats["scene_types_detected"] else "none"
321
 
322
  return stats
323
 
 
327
  "total_processed": 0,
328
  "successful_analyses": 0,
329
  "failed_analyses": 0,
330
+ "average_processing_time": 0.0,
331
+ "cinematography_enhancements": 0,
332
+ "scene_types_detected": {}
333
  }
334
+ logger.info("Phramer AI processing statistics reset")
335
 
336
 
337
+ class CinematicBatchProcessor:
338
+ """Handle batch processing for MIA TV Series production"""
339
 
340
+ def __init__(self, optimizer: PhramerlAIOptimizer):
341
  self.optimizer = optimizer
342
  self.batch_results = []
343
+ self.batch_stats = {
344
+ "total_images": 0,
345
+ "successful_analyses": 0,
346
+ "scene_type_distribution": {},
347
+ "average_score": 0.0,
348
+ "processing_time_total": 0.0
349
+ }
350
 
351
+ def process_cinematic_batch(self, images: list, analysis_type: str = "cinematic") -> list:
352
+ """Process multiple images for cinematic production"""
353
  results = []
354
+ total_score = 0
355
+ successful_count = 0
356
+
357
+ logger.info(f"Starting cinematic batch processing: {len(images)} images")
358
 
359
  for i, image in enumerate(images):
360
+ logger.info(f"Processing cinematic batch item {i+1}/{len(images)}")
361
 
362
  try:
363
+ if analysis_type == "cinematic":
364
+ result = self.optimizer.process_for_cinematic(image)
365
+ elif analysis_type == "flux":
366
+ result = self.optimizer.process_for_flux(image)
367
+ else:
368
+ result = self.optimizer.process_for_multiengine(image)
369
+
370
+ success = result[3]["success"]
371
+
372
+ if success:
373
+ score = result[3].get("score", 0)
374
+ scene_type = result[3].get("scene_type", "unknown")
375
+
376
+ total_score += score
377
+ successful_count += 1
378
+
379
+ # Update scene distribution
380
+ if scene_type in self.batch_stats["scene_type_distribution"]:
381
+ self.batch_stats["scene_type_distribution"][scene_type] += 1
382
+ else:
383
+ self.batch_stats["scene_type_distribution"][scene_type] = 1
384
+
385
  results.append({
386
  "index": i,
387
+ "success": success,
388
+ "result": result,
389
+ "scene_type": result[3].get("scene_type", "unknown"),
390
+ "score": result[3].get("score", 0)
391
  })
392
 
393
  except Exception as e:
394
+ logger.error(f"Cinematic batch item {i} failed: {e}")
395
  results.append({
396
  "index": i,
397
  "success": False,
398
+ "error": str(e),
399
+ "scene_type": "error",
400
+ "score": 0
401
  })
402
 
403
+ # Update batch statistics
404
+ self.batch_stats.update({
405
+ "total_images": len(images),
406
+ "successful_analyses": successful_count,
407
+ "average_score": total_score / successful_count if successful_count > 0 else 0.0
408
+ })
409
+
410
  self.batch_results = results
411
+ logger.info(f"Cinematic batch processing complete: {successful_count}/{len(images)} successful")
412
+
413
  return results
414
 
415
+ def get_cinematic_batch_summary(self) -> Dict[str, Any]:
416
+ """Get comprehensive summary of cinematic batch processing"""
417
  if not self.batch_results:
418
+ return {"total": 0, "successful": 0, "failed": 0, "average_score": 0.0}
419
 
420
  successful = sum(1 for r in self.batch_results if r["success"])
421
  total = len(self.batch_results)
422
 
423
+ summary = {
424
  "total": total,
425
  "successful": successful,
426
  "failed": total - successful,
427
+ "success_rate": successful / total if total > 0 else 0.0,
428
+ "average_score": self.batch_stats["average_score"],
429
+ "scene_distribution": self.batch_stats["scene_type_distribution"],
430
+ "most_common_scene": max(self.batch_stats["scene_type_distribution"].items(), key=lambda x: x[1])[0] if self.batch_stats["scene_type_distribution"] else "none"
431
  }
432
+
433
+ return summary
434
 
435
 
436
+ # Global optimizer instance for Phramer AI
437
+ phramer_optimizer = PhramerlAIOptimizer()
438
 
439
 
440
+ def process_image_simple(image: Any, model_name: str = None, analysis_type: str = "multiengine") -> Tuple[str, str, str]:
441
  """
442
+ Simple interface for Phramer AI image processing
443
 
444
  Args:
445
  image: Input image
446
  model_name: Optional model name
447
+ analysis_type: Type of analysis ("multiengine", "cinematic", "flux")
448
 
449
  Returns:
450
  Tuple of (prompt, report, score_html)
451
  """
452
+ if model_name and model_name != phramer_optimizer.model_name:
453
  # Create temporary optimizer with specified model
454
+ temp_optimizer = PhramerlAIOptimizer(model_name)
455
+ prompt, report, score_html, _ = temp_optimizer.process_image(image, analysis_type)
456
  else:
457
+ prompt, report, score_html, _ = phramer_optimizer.process_image(image, analysis_type)
458
 
459
  return prompt, report, score_html
460
 
461
 
462
+ def process_for_mia_tv_series(image: Any) -> Tuple[str, str, str]:
463
+ """
464
+ Specialized processing for MIA TV Series production
465
+
466
+ Args:
467
+ image: Input image
468
+
469
+ Returns:
470
+ Tuple of (cinematic_prompt, detailed_report, score_html)
471
+ """
472
+ return phramer_optimizer.process_for_cinematic(image)[:3]
473
+
474
+
475
+ def get_phramer_stats() -> Dict[str, Any]:
476
+ """Get comprehensive Phramer AI processing statistics"""
477
+ return phramer_optimizer.get_enhanced_stats()
478
+
479
+
480
  # Export main components
481
  __all__ = [
482
+ "PhramerlAIOptimizer",
483
+ "CinematicBatchProcessor",
484
+ "phramer_optimizer",
485
+ "process_image_simple",
486
+ "process_for_mia_tv_series",
487
+ "get_phramer_stats"
488
  ]