Spaces:
Running
on
Zero
Running
on
Zero
Update models.py
Browse files
models.py
CHANGED
@@ -90,234 +90,123 @@ class BagelAPIAnalyzer(BaseImageAnalyzer):
|
|
90 |
return False
|
91 |
|
92 |
def _create_professional_enhanced_prompt(self, analysis_type: str = "multimodal") -> str:
|
93 |
-
"""Create professionally enhanced prompt
|
94 |
|
95 |
-
# Import the complete professional knowledge
|
96 |
-
try:
|
97 |
-
from professional_photography import EXPERT_PHOTOGRAPHY_KNOWLEDGE
|
98 |
-
except ImportError:
|
99 |
-
logger.warning("Professional photography knowledge not available")
|
100 |
-
return self._create_fallback_prompt(analysis_type)
|
101 |
-
|
102 |
-
# Extract complete knowledge sections safely
|
103 |
-
knowledge_sections = {
|
104 |
-
'scene_types': EXPERT_PHOTOGRAPHY_KNOWLEDGE.get("scene_types", {}),
|
105 |
-
'lighting_principles': EXPERT_PHOTOGRAPHY_KNOWLEDGE.get("lighting_principles", {}),
|
106 |
-
'composition_rules': EXPERT_PHOTOGRAPHY_KNOWLEDGE.get("composition_rules", {}),
|
107 |
-
'camera_angles': EXPERT_PHOTOGRAPHY_KNOWLEDGE.get("camera_angles", {}),
|
108 |
-
'photographic_planes': EXPERT_PHOTOGRAPHY_KNOWLEDGE.get("photographic_planes", {}),
|
109 |
-
'focus_techniques': EXPERT_PHOTOGRAPHY_KNOWLEDGE.get("focus_techniques", {}),
|
110 |
-
'camera_modes': EXPERT_PHOTOGRAPHY_KNOWLEDGE.get("camera_modes", {}),
|
111 |
-
'iso_guidelines': EXPERT_PHOTOGRAPHY_KNOWLEDGE.get("iso_guidelines", {}),
|
112 |
-
'lighting_situations': EXPERT_PHOTOGRAPHY_KNOWLEDGE.get("lighting_situations", {}),
|
113 |
-
'movement_techniques': EXPERT_PHOTOGRAPHY_KNOWLEDGE.get("movement_techniques", {}),
|
114 |
-
'specialized_techniques': EXPERT_PHOTOGRAPHY_KNOWLEDGE.get("specialized_techniques", {})
|
115 |
-
}
|
116 |
-
|
117 |
-
# Build prompt based on analysis type
|
118 |
if analysis_type == "cinematic":
|
119 |
-
return
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
• Overcast: {lighting_principles.get("natural_light_types", {}).get("overcast", {}).get("characteristics", "soft, even, diffused light")} - advantage: {lighting_principles.get("natural_light_types", {}).get("overcast", {}).get("advantage", "no harsh shadows")}
|
164 |
-
|
165 |
-
2. CAMERA_SETUP: Recommend specific professional equipment based on scene analysis using these configurations:
|
166 |
-
|
167 |
-
SCENE TYPES - Match scene to appropriate setup:
|
168 |
-
Portrait Studio: Equipment: {scene_types.get("portrait_studio", {}).get("equipment", {}).get("camera", "Canon EOS R5")}, {scene_types.get("portrait_studio", {}).get("equipment", {}).get("lens", "85mm f/1.4")}, Settings: {scene_types.get("portrait_studio", {}).get("camera_settings", {}).get("mode", "AV/A")}, {scene_types.get("portrait_studio", {}).get("camera_settings", {}).get("aperture", "f/2.8")}, {scene_types.get("portrait_studio", {}).get("camera_settings", {}).get("iso", "100-400")}
|
169 |
-
|
170 |
-
Street Photography: Equipment: {scene_types.get("street_photography", {}).get("equipment", {}).get("camera", "Leica M11")}, {scene_types.get("street_photography", {}).get("equipment", {}).get("lens", "35mm f/1.4")}, Settings: {scene_types.get("street_photography", {}).get("camera_settings", {}).get("mode", "TV/S or Program")}, {scene_types.get("street_photography", {}).get("camera_settings", {}).get("aperture", "f/5.6-f/8")}, {scene_types.get("street_photography", {}).get("camera_settings", {}).get("iso", "400-1600")}
|
171 |
|
172 |
-
|
173 |
-
|
174 |
-
Architecture: Equipment: {scene_types.get("architecture", {}).get("equipment", {}).get("camera", "Canon EOS R5")}, {scene_types.get("architecture", {}).get("equipment", {}).get("lens", "24-70mm f/2.8")}, Settings: {scene_types.get("architecture", {}).get("camera_settings", {}).get("mode", "AV/A")}, {scene_types.get("architecture", {}).get("camera_settings", {}).get("aperture", "f/8-f/11")}, {scene_types.get("architecture", {}).get("camera_settings", {}).get("iso", "100-400")}
|
175 |
-
|
176 |
-
Action Sports: Equipment: {scene_types.get("action_sports", {}).get("equipment", {}).get("camera", "Sony A1")}, {scene_types.get("action_sports", {}).get("equipment", {}).get("lens", "70-200mm f/2.8")}, Settings: {scene_types.get("action_sports", {}).get("camera_settings", {}).get("mode", "TV/S")}, {scene_types.get("action_sports", {}).get("camera_settings", {}).get("aperture", "f/2.8-f/4")}, {scene_types.get("action_sports", {}).get("camera_settings", {}).get("iso", "800-3200")}
|
177 |
-
|
178 |
-
Apply complete professional cinematography knowledge to generate concise, technically accurate prompt for cinema-quality generation."""
|
179 |
-
|
180 |
-
return prompt
|
181 |
-
|
182 |
-
def _build_flux_prompt(self, knowledge: Dict[str, Any]) -> str:
|
183 |
-
"""Build FLUX-optimized prompt with complete professional knowledge"""
|
184 |
-
|
185 |
-
camera_angles = knowledge.get('camera_angles', {})
|
186 |
-
lighting_situations = knowledge.get('lighting_situations', {})
|
187 |
-
composition_rules = knowledge.get('composition_rules', {})
|
188 |
-
scene_types = knowledge.get('scene_types', {})
|
189 |
-
camera_modes = knowledge.get('camera_modes', {})
|
190 |
-
|
191 |
-
prompt = f"""Analyze this image for FLUX prompt generation using complete professional photography expertise. Apply the full knowledge base for photorealistic output. Provide exactly two sections:
|
192 |
-
|
193 |
-
1. DESCRIPTION: Professional technical analysis using complete photography framework:
|
194 |
-
|
195 |
-
CAMERA ANGLES - Identify specific angle and apply professional knowledge:
|
196 |
-
• Eye Level: {camera_angles.get("eye_level_normal", {}).get("description", "Eye level normal")} - {camera_angles.get("eye_level_normal", {}).get("effect", "neutral perspective")}, best for: {camera_angles.get("eye_level_normal", {}).get("best_for", "portraits, documentary")}
|
197 |
-
• Low Angle: {camera_angles.get("low_angle_worms_eye", {}).get("description", "Low angle worms eye")} - {camera_angles.get("low_angle_worms_eye", {}).get("effect", "subject appears larger")}, best for: {camera_angles.get("low_angle_worms_eye", {}).get("best_for", "architecture, powerful portraits")}
|
198 |
-
• High Angle: {camera_angles.get("high_angle_birds_eye", {}).get("description", "High angle birds eye")} - {camera_angles.get("high_angle_birds_eye", {}).get("effect", "subject appears smaller")}, best for: {camera_angles.get("high_angle_birds_eye", {}).get("best_for", "environmental context, patterns")}
|
199 |
-
|
200 |
-
LIGHTING SITUATIONS - Match to appropriate lighting condition:
|
201 |
-
• Bright Daylight: ISO {lighting_situations.get("bright_daylight", {}).get("iso", "100-200")} - challenge: {lighting_situations.get("bright_daylight", {}).get("challenge", "harsh shadows")}, solutions: use reflectors, find open shade
|
202 |
-
• Overcast Day: ISO {lighting_situations.get("overcast_day", {}).get("iso", "200-400")} - {lighting_situations.get("overcast_day", {}).get("characteristics", "soft, even light but dimmer")}, advantage: {lighting_situations.get("overcast_day", {}).get("advantage", "natural diffusion")}
|
203 |
-
• Indoor Natural: ISO {lighting_situations.get("indoor_natural_light", {}).get("iso", "800-1600")} - {lighting_situations.get("indoor_natural_light", {}).get("window_light", "excellent for portraits")}, technique: {lighting_situations.get("indoor_natural_light", {}).get("technique", "position subject relative to window")}
|
204 |
-
• Low Light: ISO {lighting_situations.get("low_light_available", {}).get("iso", "1600-6400")} - {lighting_situations.get("low_light_available", {}).get("stabilization", "essential for sharp images")}, technique: {lighting_situations.get("low_light_available", {}).get("technique", "wider apertures, slower movements")}
|
205 |
-
|
206 |
-
COMPOSITION APPLICATION - Apply these specific rules:
|
207 |
-
• Rule of Thirds: {composition_rules.get("rule_of_thirds", {}).get("principle", "Divide frame into 9 equal sections")} - {composition_rules.get("rule_of_thirds", {}).get("subject_placement", "eyes on upper third line for portraits")}, {composition_rules.get("rule_of_thirds", {}).get("horizon_placement", "upper or lower third for landscapes")}
|
208 |
-
• Leading Lines: {composition_rules.get("leading_lines", {}).get("purpose", "Guide viewer's eye through the image")} - technique: {composition_rules.get("leading_lines", {}).get("technique", "use lines to lead to main subject")}
|
209 |
-
• Depth Layers: {composition_rules.get("depth_layers", {}).get("technique", "Create separation between layers")} - {composition_rules.get("depth_layers", {}).get("foreground", "Nearest elements")}, {composition_rules.get("depth_layers", {}).get("middle_ground", "Main subject area")}, {composition_rules.get("depth_layers", {}).get("background", "Context and environment")}
|
210 |
-
|
211 |
-
2. CAMERA_SETUP: Apply complete professional equipment knowledge:
|
212 |
|
213 |
-
|
214 |
-
Portrait Studio: Equipment: {scene_types.get("portrait_studio", {}).get("equipment", {}).get("camera", "Canon EOS R5")}, {scene_types.get("portrait_studio", {}).get("equipment", {}).get("lens", "85mm f/1.4")}, Camera settings: {scene_types.get("portrait_studio", {}).get("camera_settings", {}).get("mode", "AV/A")}, {scene_types.get("portrait_studio", {}).get("camera_settings", {}).get("aperture", "f/2.8")}, {scene_types.get("portrait_studio", {}).get("camera_settings", {}).get("iso", "100-400")}, Focus: {scene_types.get("portrait_studio", {}).get("camera_settings", {}).get("focus", "single point AF on eyes")}
|
215 |
|
216 |
-
|
|
|
|
|
|
|
|
|
|
|
217 |
|
218 |
-
|
|
|
|
|
|
|
|
|
219 |
|
220 |
-
|
|
|
|
|
|
|
|
|
|
|
221 |
|
222 |
-
|
|
|
|
|
|
|
|
|
|
|
223 |
|
224 |
-
|
225 |
|
226 |
-
|
227 |
-
• Aperture Priority: {camera_modes.get("aperture_priority", {}).get("mode_designation", "AV (Canon) / A (Nikon)")} - photographer sets {camera_modes.get("aperture_priority", {}).get("photographer_sets", "aperture value")}, camera sets {camera_modes.get("aperture_priority", {}).get("camera_sets", "shutter speed")}, best for: {camera_modes.get("aperture_priority", {}).get("best_for", "controlling depth of field")}
|
228 |
-
• Shutter Priority: {camera_modes.get("shutter_priority", {}).get("mode_designation", "TV (Canon) / S (Nikon)")} - photographer sets {camera_modes.get("shutter_priority", {}).get("photographer_sets", "shutter speed")}, camera sets {camera_modes.get("shutter_priority", {}).get("camera_sets", "aperture")}, best for: {camera_modes.get("shutter_priority", {}).get("best_for", "controlling motion")}
|
229 |
-
• Manual Mode: {camera_modes.get("manual_mode", {}).get("photographer_sets", "Both aperture and shutter speed")} - when to use: consistent lighting, studio work, advantage: {camera_modes.get("manual_mode", {}).get("advantage", "complete creative control")}
|
230 |
|
231 |
-
|
232 |
-
|
233 |
-
|
|
|
|
|
234 |
|
235 |
-
|
236 |
-
"""Build multimodal analysis prompt with complete professional knowledge"""
|
237 |
-
|
238 |
-
prompt = """Analyze this image with professional cinematography expertise for multi-platform prompt generation. You are a master cinematographer with extensive technical and artistic knowledge from 30+ years in cinema. Provide exactly two sections:
|
239 |
-
|
240 |
-
1. DESCRIPTION: Expert visual analysis for prompt generation:
|
241 |
-
- Comprehensive scene description with photographic insight
|
242 |
-
- Subject matter, composition, and visual hierarchy
|
243 |
-
- Lighting analysis: quality, direction, mood, technical setup
|
244 |
-
- Color palette, contrast, and tonal relationships
|
245 |
-
- Artistic elements: style, mood, atmosphere, visual impact
|
246 |
-
- Technical photographic qualities and execution
|
247 |
-
|
248 |
-
2. CAMERA_SETUP: Professional equipment and technique recommendation:
|
249 |
-
- Camera system recommendation based on scene requirements
|
250 |
-
- Lens selection with specific focal length and aperture range
|
251 |
-
- Technical shooting parameters and considerations
|
252 |
-
- Lighting setup and methodology for scene recreation
|
253 |
-
- Professional approach: shooting style and technical execution
|
254 |
-
|
255 |
-
Apply master-level cinematography knowledge: advanced composition techniques, professional lighting principles, camera system expertise, lens characteristics, and technical excellence. Create content suitable for multiple generative engines (Flux, Midjourney, etc.) with emphasis on photorealistic quality."""
|
256 |
-
|
257 |
-
return prompt
|
258 |
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
if analysis_type == "cinematic":
|
263 |
-
return """Analyze this image as a professional cinematographer. Provide exactly two sections:
|
264 |
-
|
265 |
-
1. DESCRIPTION: Create a detailed, flowing paragraph describing the image for cinematic reproduction:
|
266 |
-
- Scene composition and visual storytelling elements
|
267 |
-
- Lighting quality, direction, and dramatic mood
|
268 |
-
- Color palette, tonal relationships, and atmospheric elements
|
269 |
-
- Subject positioning, environmental context, and framing
|
270 |
-
- Cinematic qualities: film grain, depth of field, visual style
|
271 |
-
- Technical photographic elements that enhance realism
|
272 |
-
|
273 |
-
2. CAMERA_SETUP: Recommend professional cinema/photography equipment based on scene analysis:
|
274 |
-
- Camera body: Choose from Canon EOS R5/R6, Sony A7R/A1, Leica M11, ARRI Alexa, RED cameras
|
275 |
-
- Lens: Specific focal length and aperture (e.g., "85mm f/1.4", "35mm anamorphic f/2.8")
|
276 |
-
- Technical settings: Aperture consideration for depth of field and story mood
|
277 |
-
- Lighting setup: Professional lighting rationale (key, fill, rim, practical lights)
|
278 |
-
- Shooting style: Documentary, portrait, landscape, architectural, or cinematic approach
|
279 |
|
280 |
-
|
281 |
|
282 |
-
|
283 |
-
return """Analyze this image for FLUX prompt generation with professional cinematography expertise. Provide exactly two sections:
|
284 |
|
285 |
-
|
286 |
-
- Scene elements and composition with precise technical language
|
287 |
-
- Lighting setup and quality with specific technical terms
|
288 |
-
- Camera angle and perspective with professional terminology
|
289 |
-
- Color grading and tonal balance for photorealistic output
|
290 |
-
- Depth of field and focus characteristics
|
291 |
-
- Professional photographic style and execution
|
292 |
|
293 |
-
|
294 |
-
- Professional camera body with model specifications
|
295 |
-
- Lens specifications with focal length and aperture
|
296 |
-
- ISO settings and technical parameters
|
297 |
-
- Professional lighting setup and rationale
|
298 |
-
- Shooting technique and professional approach
|
299 |
|
300 |
-
|
301 |
|
302 |
-
|
303 |
-
return """Analyze this image with professional cinematography expertise for multi-platform prompt generation. Provide exactly two sections:
|
304 |
|
305 |
-
|
306 |
-
- Comprehensive scene description with photographic insight
|
307 |
-
- Subject matter, composition, and visual hierarchy
|
308 |
-
- Lighting analysis: quality, direction, mood, technical setup
|
309 |
-
- Color palette, contrast, and tonal relationships
|
310 |
-
- Artistic elements: style, mood, atmosphere, visual impact
|
311 |
-
- Technical photographic qualities and execution
|
312 |
|
313 |
-
|
314 |
-
-
|
315 |
-
-
|
316 |
-
-
|
317 |
-
-
|
318 |
-
-
|
319 |
|
320 |
-
|
321 |
|
322 |
def _extract_professional_camera_setup(self, description: str) -> Optional[str]:
|
323 |
"""Extract and enhance camera setup with professional photography knowledge"""
|
@@ -329,138 +218,54 @@ Apply master-level cinematography knowledge: advanced composition techniques, pr
|
|
329 |
parts = description.split("CAMERA_SETUP:")
|
330 |
if len(parts) > 1:
|
331 |
camera_section = parts[1].strip()
|
332 |
-
|
333 |
-
|
334 |
-
|
|
|
|
|
|
|
|
|
335 |
|
336 |
elif "2. CAMERA_SETUP" in description:
|
337 |
parts = description.split("2. CAMERA_SETUP")
|
338 |
if len(parts) > 1:
|
339 |
camera_section = parts[1].strip()
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
camera_setup = self._find_professional_camera_recommendation(description)
|
347 |
-
|
348 |
-
return camera_setup
|
349 |
-
|
350 |
-
except Exception as e:
|
351 |
-
logger.warning(f"Failed to extract professional camera setup: {e}")
|
352 |
-
return None
|
353 |
-
|
354 |
-
def _parse_professional_camera_recommendation(self, camera_text: str) -> Optional[str]:
|
355 |
-
"""Parse camera recommendation with professional photography enhancement"""
|
356 |
-
try:
|
357 |
-
# Clean and extract with professional patterns
|
358 |
-
camera_text = re.sub(r'^(Based on.*?recommend|I would recommend|For this.*?recommend)\s*', '', camera_text, flags=re.IGNORECASE)
|
359 |
-
|
360 |
-
# Professional camera patterns (more comprehensive)
|
361 |
-
camera_patterns = [
|
362 |
-
r'(Canon EOS R[^\s,]*(?:\s+[^\s,]*)?)',
|
363 |
-
r'(Sony A[^\s,]*(?:\s+[^\s,]*)?)',
|
364 |
-
r'(Leica [^\s,]+)',
|
365 |
-
r'(Hasselblad [^\s,]+)',
|
366 |
-
r'(Phase One [^\s,]+)',
|
367 |
-
r'(Fujifilm [^\s,]+)',
|
368 |
-
r'(ARRI [^\s,]+)',
|
369 |
-
r'(RED [^\s,]+)',
|
370 |
-
r'(Nikon [^\s,]+)'
|
371 |
-
]
|
372 |
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
if match:
|
377 |
-
camera_model = match.group(1).strip()
|
378 |
-
break
|
379 |
-
|
380 |
-
# Professional lens patterns (enhanced)
|
381 |
-
lens_patterns = [
|
382 |
-
r'(\d+mm\s*f/[\d.]+(?:\s*(?:lens|anamorphic|telephoto|wide))?)',
|
383 |
-
r'(\d+-\d+mm\s*f/[\d.]+(?:\s*lens)?)',
|
384 |
-
r'(with\s+(?:a\s+)?(\d+mm[^,.]*))',
|
385 |
-
r'(paired with.*?(\d+mm[^,.]*))',
|
386 |
-
r'(\d+mm[^,]*anamorphic[^,]*)',
|
387 |
-
r'(\d+mm[^,]*telephoto[^,]*)'
|
388 |
-
]
|
389 |
-
|
390 |
-
lens_info = None
|
391 |
-
for pattern in lens_patterns:
|
392 |
-
match = re.search(pattern, camera_text, re.IGNORECASE)
|
393 |
-
if match:
|
394 |
-
lens_info = match.group(1).strip()
|
395 |
-
lens_info = re.sub(r'^(with\s+(?:a\s+)?|paired with\s+)', '', lens_info, flags=re.IGNORECASE)
|
396 |
-
break
|
397 |
-
|
398 |
-
# Build professional recommendation
|
399 |
-
parts = []
|
400 |
-
if camera_model:
|
401 |
-
parts.append(camera_model)
|
402 |
-
if lens_info:
|
403 |
-
parts.append(lens_info)
|
404 |
-
|
405 |
-
if parts:
|
406 |
-
result = ', '.join(parts)
|
407 |
-
logger.info(f"Professional camera setup extracted: {result}")
|
408 |
-
return result
|
409 |
-
|
410 |
-
return None
|
411 |
-
|
412 |
-
except Exception as e:
|
413 |
-
logger.warning(f"Failed to parse professional camera recommendation: {e}")
|
414 |
-
return None
|
415 |
-
|
416 |
-
def _find_professional_camera_recommendation(self, text: str) -> Optional[str]:
|
417 |
-
"""Find professional camera recommendations with enhanced detection"""
|
418 |
-
try:
|
419 |
-
sentences = re.split(r'[.!?]', text)
|
420 |
-
|
421 |
-
for sentence in sentences:
|
422 |
-
# Professional camera brands and technical terms
|
423 |
-
if any(brand in sentence.lower() for brand in ['canon', 'sony', 'leica', 'hasselblad', 'phase one', 'fujifilm', 'arri', 'red']):
|
424 |
-
if any(term in sentence.lower() for term in ['recommend', 'suggest', 'would use', 'camera', 'lens', 'shot on']):
|
425 |
-
parsed = self._parse_professional_camera_recommendation(sentence.strip())
|
426 |
-
if parsed:
|
427 |
-
return parsed
|
428 |
|
429 |
return None
|
430 |
|
431 |
except Exception as e:
|
432 |
-
logger.warning(f"Failed to
|
433 |
return None
|
434 |
|
435 |
-
def
|
436 |
-
"""
|
437 |
try:
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
# Get professional cinematography context without being invasive
|
442 |
-
enhanced_context = self.professional_analyzer.generate_enhanced_context(description)
|
443 |
|
444 |
-
#
|
445 |
-
|
446 |
-
technical_context = enhanced_context.get("technical_context", "")
|
447 |
-
professional_insight = enhanced_context.get("professional_insight", "")
|
448 |
|
449 |
-
#
|
450 |
-
|
|
|
451 |
|
452 |
-
|
453 |
-
if technical_context and len(technical_context) > 20:
|
454 |
-
# Only add if it doesn't duplicate existing information
|
455 |
-
if not any(term in description.lower() for term in ["shot on", "professional", "camera"]):
|
456 |
-
enhanced_description += f"\n\nProfessional Context: {technical_context}"
|
457 |
-
|
458 |
-
logger.info(f"Enhanced description with cinematography context for {scene_type} scene")
|
459 |
-
return enhanced_description
|
460 |
|
461 |
except Exception as e:
|
462 |
-
logger.warning(f"
|
463 |
-
return
|
464 |
|
465 |
def _save_temp_image(self, image: Image.Image) -> str:
|
466 |
"""Save image to temporary file for API call"""
|
@@ -517,7 +322,7 @@ Apply master-level cinematography knowledge: advanced composition techniques, pr
|
|
517 |
if not temp_path:
|
518 |
return "Image processing failed", {"error": "Could not save image"}
|
519 |
|
520 |
-
logger.info("Calling BAGEL API with professional cinematography
|
521 |
|
522 |
# Call BAGEL API with enhanced prompt
|
523 |
result = self.client.predict(
|
@@ -547,15 +352,13 @@ Apply master-level cinematography knowledge: advanced composition techniques, pr
|
|
547 |
logger.info(f"Professional camera setup extracted: {camera_setup}")
|
548 |
else:
|
549 |
metadata["has_camera_suggestion"] = False
|
550 |
-
logger.info("No camera setup found
|
551 |
|
552 |
-
#
|
553 |
-
|
554 |
-
description = self._enhance_description_with_professional_context(description, image)
|
555 |
-
metadata["cinematography_context_applied"] = True
|
556 |
|
557 |
else:
|
558 |
-
description = "Professional
|
559 |
metadata["has_camera_suggestion"] = False
|
560 |
|
561 |
# Update metadata
|
@@ -620,32 +423,25 @@ class FallbackAnalyzer(BaseImageAnalyzer):
|
|
620 |
mode = image.mode
|
621 |
aspect_ratio = width / height
|
622 |
|
623 |
-
# Enhanced scene detection
|
624 |
if aspect_ratio > 1.5:
|
625 |
orientation = "landscape"
|
626 |
scene_type = "landscape"
|
627 |
-
|
|
|
628 |
elif aspect_ratio < 0.75:
|
629 |
orientation = "portrait"
|
630 |
scene_type = "portrait_studio"
|
631 |
-
|
|
|
632 |
else:
|
633 |
orientation = "square"
|
634 |
scene_type = "general"
|
635 |
-
|
636 |
-
|
637 |
-
# Generate professional description
|
638 |
-
description = f"A {orientation} format professional photograph with balanced composition and technical excellence. The image demonstrates clear visual hierarchy and professional execution, suitable for high-quality reproduction across multiple generative platforms. Recommended professional setup: {camera_suggestion}, with careful attention to exposure, lighting, and artistic composition."
|
639 |
|
640 |
-
#
|
641 |
-
|
642 |
-
if PROFESSIONAL_PHOTOGRAPHY_CONFIG.get("enable_expert_analysis", True):
|
643 |
-
enhanced_context = self.professional_analyzer.generate_enhanced_context(description)
|
644 |
-
technical_context = enhanced_context.get("technical_context", "")
|
645 |
-
if technical_context:
|
646 |
-
description += f" Cinematography context: {technical_context}"
|
647 |
-
except Exception as e:
|
648 |
-
logger.warning(f"Cinematography context enhancement failed in fallback: {e}")
|
649 |
|
650 |
metadata = {
|
651 |
"model": "Professional-Fallback",
|
@@ -657,15 +453,16 @@ class FallbackAnalyzer(BaseImageAnalyzer):
|
|
657 |
"aspect_ratio": round(aspect_ratio, 2),
|
658 |
"scene_type": scene_type,
|
659 |
"has_camera_suggestion": True,
|
660 |
-
"camera_setup": camera_suggestion,
|
661 |
-
"professional_enhancement": True
|
|
|
662 |
}
|
663 |
|
664 |
return description, metadata
|
665 |
|
666 |
except Exception as e:
|
667 |
logger.error(f"Professional fallback analysis failed: {e}")
|
668 |
-
return "Professional
|
669 |
"error": str(e),
|
670 |
"model": "Professional-Fallback"
|
671 |
}
|
|
|
90 |
return False
|
91 |
|
92 |
def _create_professional_enhanced_prompt(self, analysis_type: str = "multimodal") -> str:
|
93 |
+
"""Create professionally enhanced prompt that makes BAGEL see with cinematographic eyes"""
|
94 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
if analysis_type == "cinematic":
|
96 |
+
return """You are a master cinematographer with 30+ years of experience. Analyze this image with complete professional cinematography knowledge and provide exactly two sections:
|
97 |
+
|
98 |
+
1. DESCRIPTION: Analyze what you see using professional cinematography terminology:
|
99 |
+
|
100 |
+
First, identify the PHOTOGRAPHIC PLANE:
|
101 |
+
- EXTREME WIDE SHOT: Subject very small in environment (establishes location)
|
102 |
+
- WIDE SHOT: Full body visible with environment (subject in context)
|
103 |
+
- MEDIUM SHOT: From waist up (balance subject/environment)
|
104 |
+
- CLOSE-UP: Head and shoulders (emotion and expression)
|
105 |
+
- EXTREME CLOSE-UP: Part of face or detail (intense emotion)
|
106 |
+
- DETAIL SHOT: Specific small element (highlight aspect)
|
107 |
+
|
108 |
+
Second, identify the CAMERA ANGLE:
|
109 |
+
- EYE LEVEL: Camera at subject's eye level (neutral, natural perspective)
|
110 |
+
- LOW ANGLE: Camera below looking up (subject appears powerful, heroic)
|
111 |
+
- HIGH ANGLE: Camera above looking down (subject appears vulnerable, shows context)
|
112 |
+
- DUTCH ANGLE: Camera tilted (dynamic tension, instability)
|
113 |
+
|
114 |
+
Third, analyze the LIGHTING:
|
115 |
+
- GOLDEN HOUR: Warm, soft, directional light (first/last hour of sun)
|
116 |
+
- BLUE HOUR: Even blue light, dramatic mood (20-30 min after sunset)
|
117 |
+
- NATURAL DAYLIGHT: Bright sunny conditions
|
118 |
+
- SOFT NATURAL: Overcast, diffused, even light
|
119 |
+
- DRAMATIC: High contrast, moody shadows
|
120 |
+
- STUDIO: Controlled professional lighting
|
121 |
+
|
122 |
+
Fourth, identify COMPOSITION:
|
123 |
+
- RULE OF THIRDS: Key elements on intersection points
|
124 |
+
- LEADING LINES: Lines guide viewer's eye to subject
|
125 |
+
- SYMMETRICAL: Mirror-like balance
|
126 |
+
- CENTERED: Subject in middle for impact
|
127 |
+
- DEPTH LAYERS: Foreground, middle ground, background separation
|
128 |
+
|
129 |
+
Now describe the scene combining all these professional elements in flowing descriptive language.
|
130 |
+
|
131 |
+
2. CAMERA_SETUP: Recommend specific professional equipment based on your analysis:
|
132 |
+
|
133 |
+
For PORTRAIT scenes: Canon EOS R5, 85mm f/1.4 lens, f/2.8, ISO 200, single point AF on eyes
|
134 |
+
For LANDSCAPE scenes: Phase One XT, 24-70mm f/4 lens, f/8-f/11, ISO 100, hyperfocal distance
|
135 |
+
For STREET scenes: Leica M11, 35mm f/1.4 lens, f/5.6-f/8, ISO 400-1600, zone focusing
|
136 |
+
For ARCHITECTURE: Canon EOS R5, 24-70mm f/2.8 lens, f/8-f/11, ISO 100, tilt-shift correction
|
137 |
+
For ACTION: Sony A1, 70-200mm f/2.8 lens, f/2.8-f/4, ISO 800-3200, continuous AF tracking
|
138 |
+
|
139 |
+
Apply your complete professional cinematography knowledge to see this image as a master would."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
|
141 |
+
elif analysis_type == "flux_optimized":
|
142 |
+
return """You are a professional cinematographer analyzing this image for photorealistic prompt generation. Use complete technical knowledge and provide exactly two sections:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
143 |
|
144 |
+
1. DESCRIPTION: Technical cinematographic analysis:
|
|
|
145 |
|
146 |
+
PHOTOGRAPHIC PLANE (choose one):
|
147 |
+
- Wide shot: Full subject visible with environment
|
148 |
+
- Medium shot: Waist up, balanced composition
|
149 |
+
- Close-up: Head and shoulders, tight framing
|
150 |
+
- Extreme close-up: Facial details or specific elements
|
151 |
+
- Detail shot: Small specific elements highlighted
|
152 |
|
153 |
+
CAMERA ANGLE (identify):
|
154 |
+
- Eye level: Natural, relatable perspective
|
155 |
+
- Low angle: Looking up, subject appears powerful
|
156 |
+
- High angle: Looking down, shows vulnerability/context
|
157 |
+
- Dutch angle: Tilted, creates dynamic tension
|
158 |
|
159 |
+
LIGHTING TYPE (analyze):
|
160 |
+
- Golden hour: Warm, soft directional light
|
161 |
+
- Natural daylight: Bright outdoor conditions
|
162 |
+
- Soft natural: Overcast, even diffusion
|
163 |
+
- Dramatic: High contrast, moody shadows
|
164 |
+
- Blue hour: Even twilight, dramatic mood
|
165 |
|
166 |
+
COMPOSITION TECHNIQUE (apply):
|
167 |
+
- Rule of thirds: Subject on intersection points
|
168 |
+
- Leading lines: Elements guide eye to subject
|
169 |
+
- Symmetrical: Balanced mirror composition
|
170 |
+
- Centered: Subject middle for impact
|
171 |
+
- Dynamic: Diagonal elements, movement
|
172 |
|
173 |
+
Describe the scene using these professional cinematography elements in precise technical language.
|
174 |
|
175 |
+
2. CAMERA_SETUP: Professional equipment recommendation:
|
|
|
|
|
|
|
176 |
|
177 |
+
PORTRAIT SETUP: Canon EOS R5 with 85mm f/1.4 lens at f/2.8, ISO 200, rule of thirds composition
|
178 |
+
LANDSCAPE SETUP: Phase One XT with 24-70mm f/4 lens at f/8, ISO 100, hyperfocal distance focus
|
179 |
+
STREET SETUP: Leica M11 with 35mm f/1.4 lens at f/5.6, ISO 800, zone focusing technique
|
180 |
+
ARCHITECTURE SETUP: Canon EOS R5 with 24-70mm f/2.8 lens at f/11, ISO 100, perspective correction
|
181 |
+
ACTION SETUP: Sony A1 with 70-200mm f/2.8 lens at f/4, ISO 1600, continuous AF tracking
|
182 |
|
183 |
+
Choose the setup that matches your scene analysis and provide complete technical specifications."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
184 |
|
185 |
+
else: # multimodal analysis
|
186 |
+
return """You are a master cinematographer with decades of professional experience. Analyze this image using complete cinematography knowledge and provide exactly two sections:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
187 |
|
188 |
+
1. DESCRIPTION: Professional cinematographic analysis combining:
|
189 |
|
190 |
+
PHOTOGRAPHIC PLANES: Identify if this is a wide shot (full subject with environment), medium shot (waist up), close-up (head/shoulders), extreme close-up (facial details), or detail shot (specific elements).
|
|
|
191 |
|
192 |
+
CAMERA ANGLES: Determine if shot from eye level (natural perspective), low angle (looking up, powerful), high angle (looking down, vulnerable), or dutch angle (tilted, dynamic).
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
|
194 |
+
LIGHTING ANALYSIS: Analyze if this is golden hour (warm directional), natural daylight (bright outdoor), soft natural (overcast even), dramatic (high contrast), blue hour (twilight mood), or studio (controlled).
|
|
|
|
|
|
|
|
|
|
|
195 |
|
196 |
+
COMPOSITION: Identify rule of thirds (key elements on intersections), leading lines (guiding elements), symmetrical (balanced), centered (middle impact), or dynamic (diagonal movement).
|
197 |
|
198 |
+
Describe the complete scene using professional cinematography terminology in flowing descriptive language that captures all visual and technical elements.
|
|
|
199 |
|
200 |
+
2. CAMERA_SETUP: Professional equipment recommendation based on scene analysis:
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
|
202 |
+
Choose from these professional setups:
|
203 |
+
- PORTRAIT: Canon EOS R5, 85mm f/1.4 lens, f/2.8, ISO 200
|
204 |
+
- LANDSCAPE: Phase One XT, 24-70mm f/4 lens, f/8, ISO 100
|
205 |
+
- STREET: Leica M11, 35mm f/1.4 lens, f/5.6, ISO 800
|
206 |
+
- ARCHITECTURE: Canon EOS R5, 24-70mm f/2.8 lens, f/11, ISO 100
|
207 |
+
- ACTION: Sony A1, 70-200mm f/2.8 lens, f/4, ISO 1600
|
208 |
|
209 |
+
Provide complete technical specifications matching your cinematographic analysis."""
|
210 |
|
211 |
def _extract_professional_camera_setup(self, description: str) -> Optional[str]:
|
212 |
"""Extract and enhance camera setup with professional photography knowledge"""
|
|
|
218 |
parts = description.split("CAMERA_SETUP:")
|
219 |
if len(parts) > 1:
|
220 |
camera_section = parts[1].strip()
|
221 |
+
# Take the first substantial line
|
222 |
+
lines = camera_section.split('\n')
|
223 |
+
for line in lines:
|
224 |
+
clean_line = line.strip()
|
225 |
+
if len(clean_line) > 20 and not clean_line.startswith('2.'):
|
226 |
+
camera_setup = clean_line
|
227 |
+
break
|
228 |
|
229 |
elif "2. CAMERA_SETUP" in description:
|
230 |
parts = description.split("2. CAMERA_SETUP")
|
231 |
if len(parts) > 1:
|
232 |
camera_section = parts[1].strip()
|
233 |
+
lines = camera_section.split('\n')
|
234 |
+
for line in lines:
|
235 |
+
clean_line = line.strip()
|
236 |
+
if len(clean_line) > 20:
|
237 |
+
camera_setup = clean_line
|
238 |
+
break
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
239 |
|
240 |
+
# Clean and format camera setup
|
241 |
+
if camera_setup:
|
242 |
+
return self._clean_camera_setup(camera_setup)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
243 |
|
244 |
return None
|
245 |
|
246 |
except Exception as e:
|
247 |
+
logger.warning(f"Failed to extract professional camera setup: {e}")
|
248 |
return None
|
249 |
|
250 |
+
def _clean_camera_setup(self, raw_setup: str) -> str:
|
251 |
+
"""Clean and format camera setup"""
|
252 |
try:
|
253 |
+
# Remove common prefixes
|
254 |
+
setup = re.sub(r'^(Based on.*?recommend|I would recommend|For this.*?setup)\s*:?\s*', '', raw_setup, flags=re.IGNORECASE)
|
255 |
+
setup = re.sub(r'^(CAMERA_SETUP:|2\.\s*CAMERA_SETUP:?)\s*', '', setup, flags=re.IGNORECASE)
|
|
|
|
|
256 |
|
257 |
+
# Clean up formatting
|
258 |
+
setup = re.sub(r'\s+', ' ', setup).strip()
|
|
|
|
|
259 |
|
260 |
+
# Ensure proper format
|
261 |
+
if setup and not setup.lower().startswith('shot on'):
|
262 |
+
setup = f"shot on {setup}"
|
263 |
|
264 |
+
return setup
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
265 |
|
266 |
except Exception as e:
|
267 |
+
logger.warning(f"Camera setup cleaning failed: {e}")
|
268 |
+
return raw_setup
|
269 |
|
270 |
def _save_temp_image(self, image: Image.Image) -> str:
|
271 |
"""Save image to temporary file for API call"""
|
|
|
322 |
if not temp_path:
|
323 |
return "Image processing failed", {"error": "Could not save image"}
|
324 |
|
325 |
+
logger.info("Calling BAGEL API with professional cinematography prompt...")
|
326 |
|
327 |
# Call BAGEL API with enhanced prompt
|
328 |
result = self.client.predict(
|
|
|
352 |
logger.info(f"Professional camera setup extracted: {camera_setup}")
|
353 |
else:
|
354 |
metadata["has_camera_suggestion"] = False
|
355 |
+
logger.info("No camera setup found in BAGEL response")
|
356 |
|
357 |
+
# Mark as cinematography enhanced
|
358 |
+
metadata["cinematography_context_applied"] = True
|
|
|
|
|
359 |
|
360 |
else:
|
361 |
+
description = "Professional cinematographic analysis completed"
|
362 |
metadata["has_camera_suggestion"] = False
|
363 |
|
364 |
# Update metadata
|
|
|
423 |
mode = image.mode
|
424 |
aspect_ratio = width / height
|
425 |
|
426 |
+
# Enhanced scene detection with cinematographic analysis
|
427 |
if aspect_ratio > 1.5:
|
428 |
orientation = "landscape"
|
429 |
scene_type = "landscape"
|
430 |
+
plane = "Wide shot"
|
431 |
+
camera_suggestion = "Phase One XT with 24-70mm f/4 lens, f/8, ISO 100"
|
432 |
elif aspect_ratio < 0.75:
|
433 |
orientation = "portrait"
|
434 |
scene_type = "portrait_studio"
|
435 |
+
plane = "Close-up"
|
436 |
+
camera_suggestion = "Canon EOS R5 with 85mm f/1.4 lens, f/2.8, ISO 200"
|
437 |
else:
|
438 |
orientation = "square"
|
439 |
scene_type = "general"
|
440 |
+
plane = "Medium shot"
|
441 |
+
camera_suggestion = "Canon EOS R6 with 50mm f/1.8 lens, f/4, ISO 400"
|
|
|
|
|
442 |
|
443 |
+
# Generate professional cinematographic description
|
444 |
+
description = f"{plane} composition with balanced framing and professional execution, natural lighting with good contrast, rule of thirds composition, suitable for high-quality reproduction across multiple generative platforms"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
445 |
|
446 |
metadata = {
|
447 |
"model": "Professional-Fallback",
|
|
|
453 |
"aspect_ratio": round(aspect_ratio, 2),
|
454 |
"scene_type": scene_type,
|
455 |
"has_camera_suggestion": True,
|
456 |
+
"camera_setup": f"shot on {camera_suggestion}",
|
457 |
+
"professional_enhancement": True,
|
458 |
+
"cinematography_context_applied": True
|
459 |
}
|
460 |
|
461 |
return description, metadata
|
462 |
|
463 |
except Exception as e:
|
464 |
logger.error(f"Professional fallback analysis failed: {e}")
|
465 |
+
return "Professional cinematographic analysis with technical excellence", {
|
466 |
"error": str(e),
|
467 |
"model": "Professional-Fallback"
|
468 |
}
|