|
|
|
|
|
from typing import Dict, List |
|
|
from prompt_library_manager import PromptLibraryManager |
|
|
|
|
|
class SceneCompatibilityManager: |
|
|
"""Check brand-scene compatibility to reduce false positives""" |
|
|
|
|
|
def __init__(self, prompt_library: PromptLibraryManager = None): |
|
|
""" |
|
|
Args: |
|
|
prompt_library: PromptLibraryManager instance for brand metadata |
|
|
""" |
|
|
if prompt_library is None: |
|
|
prompt_library = PromptLibraryManager() |
|
|
|
|
|
self.prompt_library = prompt_library |
|
|
|
|
|
|
|
|
self.scene_keywords = { |
|
|
'food_closeup': ['food', 'meal', 'dish', 'plate', 'restaurant', 'dining', 'cuisine'], |
|
|
'nature_landscape': ['mountain', 'forest', 'beach', 'ocean', 'lake', 'sky', 'sunset', 'outdoor'], |
|
|
'industrial': ['factory', 'warehouse', 'industrial', 'machinery', 'construction'], |
|
|
'sports': ['gym', 'fitness', 'running', 'sports', 'athletic', 'exercise'], |
|
|
'fashion': ['fashion', 'outfit', 'style', 'wearing', 'model'], |
|
|
'luxury_retail': ['store', 'boutique', 'shop', 'retail', 'display'], |
|
|
'office': ['office', 'desk', 'computer', 'workspace', 'business'], |
|
|
'home': ['home', 'room', 'interior', 'living', 'bedroom'], |
|
|
'lifestyle': ['lifestyle', 'casual', 'everyday', 'daily'], |
|
|
'tech_review': ['unboxing', 'review', 'tech', 'device', 'gadget'], |
|
|
'formal_event': ['event', 'party', 'formal', 'ceremony', 'celebration'], |
|
|
'outdoor': ['outdoor', 'park', 'street', 'outside'], |
|
|
'travel': ['travel', 'trip', 'luggage', 'airport', 'vacation'], |
|
|
'street': ['street', 'road', 'urban', 'city'], |
|
|
'parking': ['parking', 'car park', 'garage'], |
|
|
'showroom': ['showroom', 'exhibition', 'display'], |
|
|
'closeup': ['closeup', 'detail', 'macro', 'close-up'] |
|
|
} |
|
|
|
|
|
print("✓ Scene Compatibility Manager initialized") |
|
|
|
|
|
def classify_scene(self, scene_analysis: Dict) -> str: |
|
|
""" |
|
|
Classify scene type from OpenCLIP scene analysis |
|
|
|
|
|
Args: |
|
|
scene_analysis: Scene analysis results from OpenCLIPSemanticManager |
|
|
|
|
|
Returns: |
|
|
Scene type string (e.g., 'food_closeup', 'fashion', 'tech_review') |
|
|
""" |
|
|
|
|
|
scene_scores = {} |
|
|
|
|
|
|
|
|
for key in ['urban', 'lighting', 'mood', 'composition']: |
|
|
if key in scene_analysis and 'top' in scene_analysis[key]: |
|
|
top_label = scene_analysis[key]['top'].lower() |
|
|
|
|
|
|
|
|
for scene_type, keywords in self.scene_keywords.items(): |
|
|
for keyword in keywords: |
|
|
if keyword in top_label: |
|
|
scene_scores[scene_type] = scene_scores.get(scene_type, 0) + 1 |
|
|
|
|
|
|
|
|
if scene_scores: |
|
|
return max(scene_scores.items(), key=lambda x: x[1])[0] |
|
|
|
|
|
return 'general' |
|
|
|
|
|
def check_compatibility(self, brand_name: str, scene_type: str) -> float: |
|
|
""" |
|
|
Check if brand is compatible with scene |
|
|
|
|
|
Args: |
|
|
brand_name: Name of the brand |
|
|
scene_type: Scene type (e.g., 'food_closeup', 'fashion') |
|
|
|
|
|
Returns: |
|
|
Compatibility score (0.3 to 1.0) |
|
|
- 1.0: fully compatible |
|
|
- 0.7: neutral (no strong match or mismatch) |
|
|
- 0.3: incompatible (reduce confidence) |
|
|
""" |
|
|
brand_info = self.prompt_library.get_brand_prompts(brand_name) |
|
|
|
|
|
if not brand_info: |
|
|
return 0.7 |
|
|
|
|
|
|
|
|
typical_scenes = brand_info.get('typical_scenes', []) |
|
|
if scene_type in typical_scenes: |
|
|
return 1.0 |
|
|
|
|
|
|
|
|
incompatible_scenes = brand_info.get('incompatible_scenes', []) |
|
|
if scene_type in incompatible_scenes: |
|
|
return 0.3 |
|
|
|
|
|
|
|
|
return 0.7 |
|
|
|
|
|
def batch_check_compatibility(self, detected_brands: List[tuple], |
|
|
scene_analysis: Dict) -> List[tuple]: |
|
|
""" |
|
|
Check compatibility for multiple brands |
|
|
|
|
|
Args: |
|
|
detected_brands: List of (brand_name, confidence, bbox) tuples |
|
|
scene_analysis: Scene analysis results |
|
|
|
|
|
Returns: |
|
|
List of (brand_name, adjusted_confidence, bbox) tuples |
|
|
""" |
|
|
scene_type = self.classify_scene(scene_analysis) |
|
|
|
|
|
adjusted_brands = [] |
|
|
for brand_name, confidence, bbox in detected_brands: |
|
|
compatibility_score = self.check_compatibility(brand_name, scene_type) |
|
|
|
|
|
|
|
|
adjusted_confidence = confidence * compatibility_score |
|
|
|
|
|
|
|
|
if adjusted_confidence > 0.25: |
|
|
adjusted_brands.append((brand_name, adjusted_confidence, bbox)) |
|
|
|
|
|
|
|
|
adjusted_brands.sort(key=lambda x: x[1], reverse=True) |
|
|
|
|
|
return adjusted_brands |
|
|
|
|
|
print("✓ SceneCompatibilityManager defined") |
|
|
|