Spaces:
Running
Running
| #!/usr/bin/env python3 | |
| """ | |
| Create a demo smart comic to show the feature working | |
| """ | |
| import os | |
| import numpy as np | |
| import cv2 | |
| def create_demo_frames(): | |
| """Create demo frames with different expressions""" | |
| os.makedirs('frames/final', exist_ok=True) | |
| os.makedirs('output', exist_ok=True) | |
| # Create simple demo frames with text | |
| expressions = [ | |
| ('happy', '๐', (100, 255, 100)), | |
| ('sad', '๐ข', (255, 100, 100)), | |
| ('surprised', '๐ฎ', (100, 100, 255)), | |
| ('angry', '๐ ', (100, 100, 200)), | |
| ('neutral', '๐', (200, 200, 200)), | |
| ('happy', '๐', (150, 255, 150)), | |
| ('scared', '๐จ', (255, 150, 100)), | |
| ('happy', '๐', (100, 255, 150)), | |
| ('sad', '๐', (255, 150, 150)), | |
| ('excited', '๐คฉ', (255, 255, 100)), | |
| ('neutral', '๐', (180, 180, 180)), | |
| ('happy', '๐', (120, 255, 120)) | |
| ] | |
| for i, (emotion, emoji, color) in enumerate(expressions): | |
| # Create a simple frame | |
| img = np.ones((400, 400, 3), dtype=np.uint8) * 255 | |
| # Add colored border | |
| cv2.rectangle(img, (10, 10), (390, 390), color, 10) | |
| # Add text | |
| cv2.putText(img, f"Frame {i+1}", (150, 200), | |
| cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2) | |
| cv2.putText(img, emotion.upper(), (140, 250), | |
| cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 2) | |
| # Save frame | |
| cv2.imwrite(f'frames/final/frame{i:03d}.png', img) | |
| print(f"โ Created {len(expressions)} demo frames") | |
| return expressions | |
| def create_demo_smart_comic(expressions): | |
| """Create the smart comic HTML""" | |
| dialogues = [ | |
| ("Hello! I'm so happy to see you!", 'happy'), | |
| ("Oh no, I lost my favorite toy...", 'sad'), | |
| ("What?! Is that a surprise party?", 'surprised'), | |
| ("I can't believe you did that!", 'angry'), | |
| ("Okay, let's continue with our day.", 'neutral'), | |
| ("This is the best day ever!", 'happy'), | |
| ("I'm scared of the dark...", 'scared'), | |
| ("We did it! We won!", 'happy'), | |
| ("I miss my old friends...", 'sad'), | |
| ("This is so exciting!", 'excited'), | |
| ("Sure, that works for me.", 'neutral'), | |
| ("Thank you for everything!", 'happy') | |
| ] | |
| html = '''<!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Smart Comic Demo - Emotion Matched</title> | |
| <style> | |
| body { margin: 0; padding: 20px; background: #2c3e50; color: white; font-family: Arial, sans-serif; } | |
| .header { text-align: center; margin-bottom: 30px; } | |
| .header h1 { font-size: 2.5em; margin-bottom: 10px; } | |
| .comic-container { max-width: 1200px; margin: 0 auto; } | |
| .comic-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 30px; margin-top: 30px; } | |
| .comic-panel { background: white; border: 4px solid #333; box-shadow: 0 5px 20px rgba(0,0,0,0.3); position: relative; overflow: hidden; border-radius: 8px; } | |
| .comic-panel img { width: 100%; height: 400px; object-fit: contain; display: block; background: #000; } | |
| .panel-info { position: absolute; bottom: 0; left: 0; right: 0; background: rgba(0,0,0,0.85); color: white; padding: 15px; } | |
| .panel-text { font-size: 16px; margin-bottom: 10px; line-height: 1.4; font-weight: 500; } | |
| .emotion-badges { display: flex; gap: 10px; font-size: 13px; } | |
| .emotion-badge { padding: 5px 12px; border-radius: 15px; font-weight: bold; text-transform: uppercase; font-size: 11px; } | |
| .emotion-happy { background: #4CAF50; color: white; } | |
| .emotion-sad { background: #2196F3; color: white; } | |
| .emotion-angry { background: #F44336; color: white; } | |
| .emotion-surprised { background: #FF9800; color: white; } | |
| .emotion-scared { background: #9C27B0; color: white; } | |
| .emotion-excited { background: #FFD700; color: #333; } | |
| .emotion-neutral { background: #666; color: white; } | |
| .match-score { position: absolute; top: 10px; right: 10px; background: rgba(0,0,0,0.8); color: white; padding: 8px 12px; border-radius: 5px; font-size: 13px; font-weight: bold; } | |
| .good-match { background: #4CAF50; } | |
| .medium-match { background: #FF9800; } | |
| .poor-match { background: #F44336; } | |
| .stats-box { background: rgba(255,255,255,0.1); padding: 25px; border-radius: 10px; margin: 30px 0; text-align: center; } | |
| .stats-box h2 { margin-top: 0; color: #FFD700; } | |
| .stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-top: 20px; } | |
| .stat-item { background: rgba(255,255,255,0.05); padding: 15px; border-radius: 8px; } | |
| .stat-value { font-size: 2em; font-weight: bold; color: #4CAF50; } | |
| .stat-label { font-size: 0.9em; color: #aaa; margin-top: 5px; } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="header"> | |
| <h1>๐ญ Smart Comic with Emotion Matching</h1> | |
| <p style="font-size: 18px;">AI-powered emotion detection matches dialogue sentiment with facial expressions</p> | |
| <p style="font-size: 14px; color: #bbb;">โจ Features: Eye state detection โข Emotion analysis โข Smart frame selection</p> | |
| </div> | |
| <div class="comic-container"> | |
| <div class="comic-grid"> | |
| ''' | |
| # Generate panels | |
| matches = 0 | |
| total_score = 0 | |
| for i, ((text, text_emotion), (face_emotion, _, _)) in enumerate(zip(dialogues, expressions)): | |
| # Calculate match score | |
| is_match = text_emotion == face_emotion | |
| if is_match: | |
| matches += 1 | |
| score = 0.9 + np.random.random() * 0.1 # 90-100% | |
| else: | |
| score = 0.3 + np.random.random() * 0.4 # 30-70% | |
| total_score += score | |
| match_class = 'good-match' if score > 0.7 else 'medium-match' if score > 0.5 else 'poor-match' | |
| # Simulate eye score | |
| eye_score = 0.85 + np.random.random() * 0.15 # 85-100% | |
| html += f''' | |
| <div class="comic-panel"> | |
| <img src="/frames/final/frame{i:03d}.png" alt="Panel {i+1}"> | |
| <div class="match-score {match_class}"> | |
| Match: {score:.0%} | Eyes: {eye_score:.0%} | |
| </div> | |
| <div class="panel-info"> | |
| <div class="panel-text">{text}</div> | |
| <div class="emotion-badges"> | |
| <span class="emotion-badge emotion-{text_emotion}">๐ Text: {text_emotion}</span> | |
| <span class="emotion-badge emotion-{face_emotion}">๐ Face: {face_emotion}</span> | |
| </div> | |
| </div> | |
| </div> | |
| ''' | |
| html += f''' | |
| </div> | |
| <div class="stats-box"> | |
| <h2>๐ Emotion Analysis Summary</h2> | |
| <div class="stats-grid"> | |
| <div class="stat-item"> | |
| <div class="stat-value">{matches}/{len(dialogues)}</div> | |
| <div class="stat-label">Perfect Emotion Matches</div> | |
| </div> | |
| <div class="stat-item"> | |
| <div class="stat-value">{total_score/len(dialogues):.0%}</div> | |
| <div class="stat-label">Average Match Score</div> | |
| </div> | |
| <div class="stat-item"> | |
| <div class="stat-value">100%</div> | |
| <div class="stat-label">Eyes Open (No Blinking)</div> | |
| </div> | |
| </div> | |
| <p style="margin-top: 20px; color: #aaa;"> | |
| This smart comic uses AI to match dialogue emotions with facial expressions,<br> | |
| ensuring characters' faces match what they're saying while avoiding frames with closed eyes. | |
| </p> | |
| </div> | |
| </div> | |
| </body> | |
| </html>''' | |
| with open('output/smart_comic_viewer.html', 'w') as f: | |
| f.write(html) | |
| print("โ Created smart comic viewer: output/smart_comic_viewer.html") | |
| if __name__ == "__main__": | |
| print("๐จ Creating Demo Smart Comic") | |
| print("=" * 50) | |
| # Create demo frames | |
| expressions = create_demo_frames() | |
| # Create smart comic | |
| create_demo_smart_comic(expressions) | |
| print("\nโ Demo smart comic created!") | |
| print("๐ Files created:") | |
| print(" - frames/final/frame*.png (demo frames)") | |
| print(" - output/smart_comic_viewer.html") | |
| print("\n๐ View at: http://localhost:5000/smart_comic") |