Shivam Prasad commited on
Commit
6f78162
·
verified ·
1 Parent(s): 11ced2e

Upload 10 files

Browse files
DockerFile ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ WORKDIR /app
4
+
5
+ # Install system dependencies
6
+ RUN apt-get update && apt-get install -y \
7
+ libgl1-mesa-glx \
8
+ libglib2.0-0 \
9
+ && rm -rf /var/lib/apt/lists/*
10
+
11
+ # Copy requirements first for better caching
12
+ COPY requirements.txt .
13
+ RUN pip install --no-cache-dir -r requirements.txt
14
+
15
+ # Copy all files
16
+ COPY . .
17
+
18
+ # Expose the port the app runs on
19
+ EXPOSE 7860
20
+
21
+ # Command to run the application
22
+ CMD ["python", "app.py"]
app.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, render_template
2
+ import os
3
+ import gradio as gr
4
+ from emotion_detection import detect_emotion
5
+ from music_recommender import get_music_recommendations
6
+
7
+ app = Flask(__name__)
8
+
9
+ @app.route('/')
10
+ def home():
11
+ return render_template('index.html')
12
+
13
+ @app.route('/recommend', methods=['POST'])
14
+ def recommend():
15
+ # Get emotion from image
16
+
17
+ if len(request.files)>0:
18
+ if 'file' in request.files:
19
+ file = request.files['file']
20
+ file.save("uploaded_image.jpg")
21
+ emotion = detect_emotion("uploaded_image.jpg")
22
+ else:
23
+ emotion = request.form['emotion']
24
+
25
+ # Get music recommendations
26
+ songs = get_music_recommendations(emotion)
27
+ return render_template('results.html', emotion=emotion, songs=songs)
28
+
29
+ @app.route('/about')
30
+ def about():
31
+ return render_template('about.html')
32
+
33
+ # Create a Gradio interface wrapper around our Flask app
34
+ def create_gr_interface():
35
+ def process_image(image):
36
+ # Save the image
37
+ image_path = "uploaded_image.jpg"
38
+ image.save(image_path)
39
+
40
+ # Detect emotion
41
+ emotion = detect_emotion(image_path)
42
+
43
+ # Get recommendations
44
+ songs = get_music_recommendations(emotion)
45
+
46
+ # Format output
47
+ result = f"Detected emotion: {emotion}\n\nRecommended songs:"
48
+ for song in songs:
49
+ result += f"\n- {song['name']} by {song['artist']}"
50
+ result += f"\n Link: {song['url']}"
51
+
52
+ return result
53
+
54
+ def process_text(emotion_text):
55
+ # Get recommendations based on text input
56
+ songs = get_music_recommendations(emotion_text)
57
+
58
+ # Format output
59
+ result = f"Selected emotion: {emotion_text}\n\nRecommended songs:"
60
+ for song in songs:
61
+ result += f"\n- {song['name']} by {song['artist']}"
62
+ result += f"\n Link: {song['url']}"
63
+
64
+ return result
65
+
66
+ # Create two tabs: one for image upload, one for direct emotion selection
67
+ with gr.Blocks(title="MoodifyAI") as demo:
68
+ gr.Markdown("# MoodifyAI")
69
+ gr.Markdown("An AI-powered music recommendation system that detects emotions and suggests songs.")
70
+
71
+ with gr.Tabs():
72
+ with gr.TabItem("Detect from Image"):
73
+ with gr.Row():
74
+ with gr.Column():
75
+ image_input = gr.Image(label="Upload a facial image")
76
+ image_button = gr.Button("Get Recommendations")
77
+ with gr.Column():
78
+ image_output = gr.Textbox(label="Recommendations", lines=10)
79
+ image_button.click(process_image, inputs=image_input, outputs=image_output)
80
+
81
+ with gr.TabItem("Select Emotion"):
82
+ with gr.Row():
83
+ with gr.Column():
84
+ text_input = gr.Dropdown(
85
+ ["Happy", "Sad", "Angry", "Relaxed", "Neutral", "Surprise", "Fear", "Disgust"],
86
+ label="Select your emotion"
87
+ )
88
+ text_button = gr.Button("Get Recommendations")
89
+ with gr.Column():
90
+ text_output = gr.Textbox(label="Recommendations", lines=10)
91
+ text_button.click(process_text, inputs=text_input, outputs=text_output)
92
+
93
+ gr.Markdown("## How it works")
94
+ gr.Markdown("""
95
+ 1. Upload an image with a face or select an emotion
96
+ 2. Our AI detects the emotion or uses your selection
97
+ 3. We recommend songs based on your emotional state using Spotify's API
98
+ """)
99
+
100
+ return demo
101
+
102
+ # Create the Gradio interface
103
+ demo = create_gr_interface()
104
+
105
+ # For Hugging Face Spaces deployment
106
+ if __name__ == "__main__":
107
+ # Check if running on HF Spaces
108
+ if os.environ.get("SPACE_ID"):
109
+ demo.launch()
110
+ else:
111
+ # Run the Flask app locally
112
+ app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 7860)))
emotion_detection.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from tensorflow.keras.preprocessing.image import img_to_array
2
+ from huggingface_hub import hf_hub_download
3
+ from tensorflow.keras.models import load_model # Fixed typo in import
4
+ import numpy as np
5
+ import os
6
+ import cv2
7
+ from textblob import TextBlob
8
+
9
+ # Set environment variable
10
+ os.environ["TF_ENABLE_ONEDNN_OPTS"] = "0"
11
+
12
+ model_path = hf_hub_download(
13
+ repo_id ="shivampr1001/Emo0.1",
14
+ filename = "Emo0.1"
15
+ )
16
+ model = load_model(model_path)
17
+
18
+ def detect_emotion(image_path):
19
+
20
+ img = cv2.imread(image_path)
21
+ img = cv2.resize(img, (48, 48))
22
+ img = img_to_array(img)
23
+ img = img/255.0
24
+ img = np.expand_dims(img, axis=0)
25
+ # img = img.reshape(1, 48, 48, 1)
26
+ predictions = model.predict(img)
27
+ emotions = ['Angry', 'Disgust', 'Fear', 'Happy', 'Sad', 'Surprise', 'Neutral']
28
+ return emotions[predictions.argmax()]
29
+
30
+ def detect_sentiment(text):
31
+ analysis = TextBlob(text)
32
+ return "Positive" if analysis.sentiment.polarity > 0 else "Negative"
music_recommender.py ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import spotipy
2
+ from spotipy.oauth2 import SpotifyClientCredentials
3
+ import random
4
+ import os
5
+
6
+ # Enhanced emotion-to-genre mapping
7
+ def get_music_recommendations(emotion):
8
+ # Define the emotion to genre mapping
9
+ mood_to_genre = {
10
+ "Happy": "pop",
11
+ "Sad": "acoustic",
12
+ "Angry": "rock",
13
+ "Relaxed": "chill",
14
+ "Fear": "ambient",
15
+ "Disgust": "metal",
16
+ "Surprise": "electronic",
17
+ "Neutral": "indie"
18
+ }
19
+
20
+ # Check for Spotify credentials
21
+ client_id = os.getenv("SPOTIFY_CLIENT_ID")
22
+ client_secret = os.getenv("SPOTIFY_CLIENT_SECRET")
23
+
24
+ # If credentials exist, use Spotify API
25
+ if client_id and client_secret:
26
+ # Set up Spotify credentials
27
+ sp = spotipy.Spotify(auth_manager=SpotifyClientCredentials(
28
+ client_id=client_id,
29
+ client_secret=client_secret
30
+ ))
31
+
32
+ # Get genre based on emotion
33
+ genre = mood_to_genre.get(emotion, "pop")
34
+ offset = random.randint(0, 990)
35
+ results = sp.search(q=f"genre:{genre}", type="track", limit=10, offset=offset)
36
+
37
+ songs = []
38
+ for track in results['tracks']['items']:
39
+ songs.append({
40
+ "name": track['name'],
41
+ "artist": track['artists'][0]['name'],
42
+ "url": track['external_urls']['spotify'],
43
+ "image_url": track['album']['images'][0]['url'] if track['album']['images'] else ""
44
+ })
45
+ else:
46
+ # Fallback to mock data if no Spotify credentials
47
+ genre = mood_to_genre.get(emotion, "pop")
48
+ songs = get_mock_recommendations(genre)
49
+
50
+ return songs
51
+
52
+ def get_mock_recommendations(genre):
53
+ """Provide mock recommendations when Spotify API credentials are unavailable"""
54
+ mock_data = {
55
+ "pop": [
56
+ {"name": "Happy", "artist": "Pharrell Williams", "url": "https://open.spotify.com/track/60nZcImufyMA1MKQZ2FfW", "image_url": ""},
57
+ {"name": "Uptown Funk", "artist": "Mark Ronson ft. Bruno Mars", "url": "https://open.spotify.com/track/32OlwWuMpZ6b0aN2RZOeMS", "image_url": ""},
58
+ {"name": "Can't Stop the Feeling!", "artist": "Justin Timberlake", "url": "https://open.spotify.com/track/1WkMMavIMc4JZ8cfMmxHkI", "image_url": ""}
59
+ ],
60
+ "acoustic": [
61
+ {"name": "Someone Like You", "artist": "Adele", "url": "https://open.spotify.com/track/3bNv3VuUOKgrf5hu3YcuRo", "image_url": ""},
62
+ {"name": "Skinny Love", "artist": "Bon Iver", "url": "https://open.spotify.com/track/2CVV8PtUYYsux8XOzWpFZf", "image_url": ""},
63
+ {"name": "Fix You", "artist": "Coldplay", "url": "https://open.spotify.com/track/7LVHVU3tWfcxj5aiPFEW4Q", "image_url": ""}
64
+ ],
65
+ "rock": [
66
+ {"name": "Enter Sandman", "artist": "Metallica", "url": "https://open.spotify.com/track/5sICkBXVmaCQk5aISGR3x1", "image_url": ""},
67
+ {"name": "Back in Black", "artist": "AC/DC", "url": "https://open.spotify.com/track/08mG3Y1vljYA6bvDt4Wqkj", "image_url": ""},
68
+ {"name": "Sweet Child O' Mine", "artist": "Guns N' Roses", "url": "https://open.spotify.com/track/7o2CTH4ctstm8TNelqjb51", "image_url": ""}
69
+ ],
70
+ "chill": [
71
+ {"name": "Weightless", "artist": "Marconi Union", "url": "https://open.spotify.com/track/1ZqHjApl3pfzeZ9lBBCK3H", "image_url": ""},
72
+ {"name": "Intro", "artist": "The xx", "url": "https://open.spotify.com/track/0m1sU0FZbSYNtGNV8lqGqH", "image_url": ""},
73
+ {"name": "Porcelain", "artist": "Moby", "url": "https://open.spotify.com/track/2UKYMN7VnsQo40n0qCt6Sa", "image_url": ""}
74
+ ],
75
+ "ambient": [
76
+ {"name": "Music For Airports", "artist": "Brian Eno", "url": "https://open.spotify.com/track/5oHlSPFpn0SAJpn7hLkiSo", "image_url": ""},
77
+ {"name": "Avril 14th", "artist": "Aphex Twin", "url": "https://open.spotify.com/track/43fd8ynILrlGJddNOrRIH3", "image_url": ""},
78
+ {"name": "Gymnopédie No.1", "artist": "Erik Satie", "url": "https://open.spotify.com/track/5NGtFXVpXSvwunEIGeviY3", "image_url": ""}
79
+ ],
80
+ "metal": [
81
+ {"name": "Master of Puppets", "artist": "Metallica", "url": "https://open.spotify.com/track/2MuWTIM3b0YEAskbeeFE1i", "image_url": ""},
82
+ {"name": "Paranoid", "artist": "Black Sabbath", "url": "https://open.spotify.com/track/4O6ZbsM7nNQtdKSnb9nFR9", "image_url": ""},
83
+ {"name": "Chop Suey!", "artist": "System of a Down", "url": "https://open.spotify.com/track/2DlHlPMa4M17kufBvI2lEN", "image_url": ""}
84
+ ],
85
+ "electronic": [
86
+ {"name": "Strobe", "artist": "deadmau5", "url": "https://open.spotify.com/track/4kO7mrkvBmJ8IjHtl5wmY5", "image_url": ""},
87
+ {"name": "Scary Monsters and Nice Sprites", "artist": "Skrillex", "url": "https://open.spotify.com/track/4lajYQOtLTzIIwueGJJkKj", "image_url": ""},
88
+ {"name": "Around the World", "artist": "Daft Punk", "url": "https://open.spotify.com/track/1pKYYY0dkg23sQQXi0Q5zN", "image_url": ""}
89
+ ],
90
+ "indie": [
91
+ {"name": "Somebody Else", "artist": "The 1975", "url": "https://open.spotify.com/track/50AeFsc75hSSjmY1LlsH9Z", "image_url": ""},
92
+ {"name": "Mr. Brightside", "artist": "The Killers", "url": "https://open.spotify.com/track/003vvx7Niy0yvhvHt4a68B", "image_url": ""},
93
+ {"name": "Do I Wanna Know?", "artist": "Arctic Monkeys", "url": "https://open.spotify.com/track/5FVd6KXrgO9B3JPmC8OPst", "image_url": ""}
94
+ ]
95
+ }
96
+
97
+ # Return either the genre-specific songs or pop as fallback
98
+ return mock_data.get(genre, mock_data["pop"])
readme.md ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # MoodifyAI
2
+
3
+ An AI-powered music recommendation system that detects emotions from facial expressions and suggests songs tailored to the user's mood.
4
+
5
+ [![Hugging Face Spaces](https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-Spaces-blue)](https://huggingface.co/spaces)
6
+
7
+ ## Features
8
+ - Detects emotions from facial expressions using a pre-trained deep learning model
9
+ - Recommends songs based on the detected emotion by integrating with Spotify
10
+ - Provides a user-friendly interface through Gradio and Flask
11
+ - Can run both as a Flask web app and as a Hugging Face Space
12
+
13
+ ## How It Works
14
+ 1. **Emotion Detection:**
15
+ The system uses a deep learning model to analyze facial expressions and classify them into emotions such as happy, sad, angry, neutral, etc.
16
+
17
+ 2. **Spotify API Integration:**
18
+ Based on the detected emotion, the app queries Spotify's API for songs that match the mood and displays the results.
19
+
20
+ 3. **User Interface:**
21
+ Users interact with the system via a Gradio interface where they can upload images to detect emotions or directly select an emotion to get music recommendations.
22
+
23
+ ## Deployment on Hugging Face Spaces
24
+
25
+ This app is ready to be deployed on Hugging Face Spaces. Here's how:
26
+
27
+ 1. Create a new Space on [Hugging Face](https://huggingface.co/spaces)
28
+ 2. Choose "Gradio" as the SDK
29
+ 3. Upload all the files in this repository
30
+ 4. (Optional) Add your Spotify API credentials as Space secrets:
31
+ - `SPOTIFY_CLIENT_ID`
32
+ - `SPOTIFY_CLIENT_SECRET`
33
+
34
+ ## Local Development
35
+
36
+ ### Prerequisites
37
+ - Python 3.8+
38
+ - Spotify Developer Account (optional)
39
+
40
+ ### Setup
41
+ 1. Clone the repository
42
+ 2. Install dependencies:
43
+ ```bash
44
+ pip install -r requirements.txt
45
+ ```
46
+ 3. (Optional) Set up environment variables for Spotify API:
47
+ ```bash
48
+ export SPOTIFY_CLIENT_ID=your_client_id_here
49
+ export SPOTIFY_CLIENT_SECRET=your_client_secret_here
50
+ ```
51
+ 4. Run the application:
52
+ ```bash
53
+ python app.py
54
+ ```
55
+
56
+ ## Using the Application
57
+
58
+ ### Via Gradio Interface
59
+ 1. Open the application in your browser
60
+ 2. Choose between "Detect from Image" or "Select Emotion"
61
+ 3. For image detection, upload an image with a face
62
+ 4. For direct selection, choose an emotion from the dropdown
63
+ 5. Click "Get Recommendations" to receive song suggestions
64
+
65
+ ### Via Flask Interface (Local Only)
66
+ 1. Open http://localhost:7860 in your browser
67
+ 2. Follow the on-screen instructions to upload an image or select an emotion
68
+ 3. View your personalized music recommendations
69
+
70
+ ## Technology Stack
71
+ - **Backend:** Python, Flask, TensorFlow/Keras
72
+ - **Frontend:** Gradio, HTML/CSS (for Flask routes)
73
+ - **APIs:** Spotify Web API
74
+ - **Deployment:** Hugging Face Spaces
75
+
76
+ ## License
77
+ This project is licensed under the MIT License. See `LICENSE` for details.
requirements.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Flask==3.1.0
2
+ tensorflow==2.18.0
3
+ opencv-python==4.10.0.84
4
+ huggingface-hub>=0.19.0
5
+ gradio>=4.0.0
6
+ numpy>=2.0.2
7
+ textblob==0.18.0.post0
8
+ spotipy==2.24.0
9
+ Werkzeug==3.1.3
10
+ Jinja2==3.1.4
11
+ gunicorn==23.0.0
space_metadata.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "title": "MoodifyAI - Emotion-based Music Recommender",
3
+ "emoji": "🎵",
4
+ "colorFrom": "#9C27B0",
5
+ "colorTo": "#3F51B5",
6
+ "sdk": "gradio",
7
+ "sdk_version": "4.0.0",
8
+ "python_version": "3.10",
9
+ "app_file": "app.py",
10
+ "pinned": false,
11
+ "license": "mit"
12
+ }
templates/index.html ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>MoodifyAI - Emotion-based Music Recommendations</title>
7
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
8
+ <style>
9
+ body {
10
+ background-color: #f8f9fa;
11
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
12
+ }
13
+ .header {
14
+ background: linear-gradient(135deg, #9C27B0, #3F51B5);
15
+ color: white;
16
+ padding: 2rem 0;
17
+ text-align: center;
18
+ margin-bottom: 2rem;
19
+ border-radius: 0 0 15px 15px;
20
+ }
21
+ .card {
22
+ border-radius: 15px;
23
+ overflow: hidden;
24
+ box-shadow: 0 6px 12px rgba(0,0,0,0.1);
25
+ margin-bottom: 2rem;
26
+ border: none;
27
+ }
28
+ .card-header {
29
+ background: linear-gradient(135deg, #9C27B0, #3F51B5);
30
+ color: white;
31
+ font-weight: bold;
32
+ }
33
+ .btn-primary {
34
+ background: linear-gradient(135deg, #9C27B0, #3F51B5);
35
+ border: none;
36
+ }
37
+ .btn-primary:hover {
38
+ background: linear-gradient(135deg, #7B1FA2, #303F9F);
39
+ }
40
+ .webcam-container {
41
+ display: flex;
42
+ flex-direction: column;
43
+ align-items: center;
44
+ }
45
+ #webcam {
46
+ width: 100%;
47
+ max-width: 400px;
48
+ border-radius: 10px;
49
+ margin-bottom: 1rem;
50
+ }
51
+ #canvas {
52
+ display: none;
53
+ }
54
+ .emotion-select {
55
+ width: 100%;
56
+ padding: 10px;
57
+ border-radius: 5px;
58
+ border: 1px solid #ced4da;
59
+ margin-bottom: 1rem;
60
+ }
61
+ .footer {
62
+ text-align: center;
63
+ padding: 1rem 0;
64
+ background-color: #f1f1f1;
65
+ margin-top: 2rem;
66
+ border-radius: 15px 15px 0 0;
67
+ }
68
+ </style>
69
+ </head>
70
+ <body>
71
+ <div class="header">
72
+ <div class="container">
73
+ <h1>MoodifyAI</h1>
74
+ <p class="lead">Discover music that matches your emotions</p>
75
+ </div>
76
+ </div>
77
+
78
+ <div class="container">
79
+ <div class="row">
80
+ <div class="col-md-6 mb-4">
81
+ <div class="card">
82
+ <div class="card-header">
83
+ Upload an Image
84
+ </div>
85
+ <div class="card-body">
86
+ <form action="/recommend" method="post" enctype="multipart/form-data">
87
+ <div class="mb-3">
88
+ <label for="file" class="form-label">Choose an image with a clear facial expression</label>
89
+ <input type="file" class="form-control" id="file" name="file" accept="image/*" required>
90
+ </div>
91
+ <button type="submit" class="btn btn-primary">Get Recommendations</button>
92
+ </form>
93
+ </div>
94
+ </div>
95
+ </div>
96
+
97
+ <div class="col-md-6 mb-4">
98
+ <div class="card">
99
+ <div class="card-header">
100
+ Select Your Emotion
101
+ </div>
102
+ <div class="card-body">
103
+ <form action="/recommend" method="post">
104
+ <div class="mb-3">
105
+ <label for="emotion" class="form-label">How are you feeling today?</label>
106
+ <select name="emotion" id="emotion" class="form-select emotion-select" required>
107
+ <option value="">Select an emotion</option>
108
+ <option value="Happy">Happy</option>
109
+ <option value="Sad">Sad</option>
110
+ <option value="Angry">Angry</option>
111
+ <option value="Relaxed">Relaxed</option>
112
+ <option value="Neutral">Neutral</option>
113
+ <option value="Surprise">Surprised</option>
114
+ <option value="Fear">Fearful</option>
115
+ <option value="Disgust">Disgusted</option>
116
+ </select>
117
+ </div>
118
+ <button type="submit" class="btn btn-primary">Get Recommendations</button>
119
+ </form>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ </div>
124
+
125
+ <div class="row">
126
+ <div class="col-12">
127
+ <div class="card">
128
+ <div class="card-header">
129
+ How It Works
130
+ </div>
131
+ <div class="card-body">
132
+ <div class="row">
133
+ <div class="col-md-4 text-center mb-3">
134
+ <h5>1. Capture or Select</h5>
135
+ <p>Upload a photo or select your current emotion</p>
136
+ </div>
137
+ <div class="col-md-4 text-center mb-3">
138
+ <h5>2. Emotion Detection</h5>
139
+ <p>Our AI analyzes your facial expression or uses your selection</p>
140
+ </div>
141
+ <div class="col-md-4 text-center mb-3">
142
+ <h5>3. Music Recommendations</h5>
143
+ <p>Get personalized song suggestions to match your mood</p>
144
+ </div>
145
+ </div>
146
+ </div>
147
+ </div>
148
+ </div>
149
+ </div>
150
+ </div>
151
+
152
+ <div class="footer">
153
+ <div class="container">
154
+ <p><a href="/about">About MoodifyAI</a></p>
155
+ <p class="text-muted">© 2024 MoodifyAI</p>
156
+ </div>
157
+ </div>
158
+
159
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
160
+ </body>
161
+ </html>
templates/results.html ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>MoodifyAI - Your Recommendations</title>
7
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
8
+ <style>
9
+ body {
10
+ background-color: #f8f9fa;
11
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
12
+ }
13
+ .header {
14
+ background: linear-gradient(135deg, #9C27B0, #3F51B5);
15
+ color: white;
16
+ padding: 2rem 0;
17
+ text-align: center;
18
+ margin-bottom: 2rem;
19
+ border-radius: 0 0 15px 15px;
20
+ }
21
+ .card {
22
+ border-radius: 15px;
23
+ overflow: hidden;
24
+ box-shadow: 0 6px 12px rgba(0,0,0,0.1);
25
+ margin-bottom: 2rem;
26
+ border: none;
27
+ transition: transform 0.2s;
28
+ }
29
+ .card:hover {
30
+ transform: translateY(-5px);
31
+ }
32
+ .card-header {
33
+ background: linear-gradient(135deg, #9C27B0, #3F51B5);
34
+ color: white;
35
+ font-weight: bold;
36
+ }
37
+ .btn-primary {
38
+ background: linear-gradient(135deg, #9C27B0, #3F51B5);
39
+ border: none;
40
+ }
41
+ .btn-primary:hover {
42
+ background: linear-gradient(135deg, #7B1FA2, #303F9F);
43
+ }
44
+ .song-card {
45
+ margin-bottom: 1rem;
46
+ border-radius: 10px;
47
+ overflow: hidden;
48
+ height: 100%;
49
+ }
50
+ .song-card img {
51
+ width: 100%;
52
+ height: 200px;
53
+ object-fit: cover;
54
+ }
55
+ .song-info {
56
+ padding: 1rem;
57
+ }
58
+ .emotion-badge {
59
+ font-size: 1.2rem;
60
+ padding: 0.5rem 1rem;
61
+ border-radius: 50px;
62
+ background: linear-gradient(135deg, #9C27B0, #3F51B5);
63
+ color: white;
64
+ display: inline-block;
65
+ margin-bottom: 1rem;
66
+ }
67
+ .footer {
68
+ text-align: center;
69
+ padding: 1rem 0;
70
+ background-color: #f1f1f1;
71
+ margin-top: 2rem;
72
+ border-radius: 15px 15px 0 0;
73
+ }
74
+ </style>
75
+ </head>
76
+ <body>
77
+ <div class="header">
78
+ <div class="container">
79
+ <h1>MoodifyAI</h1>
80
+ <p class="lead">Your Personalized Music Recommendations</p>
81
+ </div>
82
+ </div>
83
+
84
+ <div class="container">
85
+ <div class="text-center mb-4">
86
+ <div class="emotion-badge">
87
+ Detected Emotion: {{ emotion }}
88
+ </div>
89
+ <p class="lead">Here are songs that match your current mood</p>
90
+ </div>
91
+
92
+ <div class="row">
93
+ {% for song in songs %}
94
+ <div class="col-md-4 mb-4">
95
+ <div class="card song-card">
96
+ {% if song.image_url %}
97
+ <img src="{{ song.image_url }}" alt="{{ song.name }}" class="card-img-top">
98
+ {% else %}
99
+ <div class="bg-secondary" style="height: 200px; display: flex; align-items: center; justify-content: center;">
100
+ <span class="text-white">No Image Available</span>
101
+ </div>
102
+ {% endif %}
103
+ <div class="song-info">
104
+ <h5>{{ song.name }}</h5>
105
+ <p class="text-muted">{{ song.artist }}</p>
106
+ <a href="{{ song.url }}" target="_blank" class="btn btn-primary btn-sm">Listen on Spotify</a>
107
+ </div>
108
+ </div>
109
+ </div>
110
+ {% endfor %}
111
+ </div>
112
+
113
+ <div class="text-center mt-4">
114
+ <a href="/" class="btn btn-primary">Try Again</a>
115
+ </div>
116
+ </div>
117
+
118
+ <div class="footer">
119
+ <div class="container">
120
+ <p><a href="/about">About MoodifyAI</a></p>
121
+ <p class="text-muted">© 2024 MoodifyAI</p>
122
+ </div>
123
+ </div>
124
+
125
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
126
+ </body>
127
+ </html>
uploaded_image.jpg ADDED