Commit a874f674 authored by Aditya Hiteshbhai's avatar Aditya Hiteshbhai

feat: implemented emotion based music recommendation system

parent a2d00ff0
# Importing necessary libraries
import numpy as np
import streamlit as st
import sqlite3
from textblob import TextBlob
conn = sqlite3.connect('sentiment.db')
cursor = conn.cursor()
import pandas as pd
import cv2
from collections import Counter
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Flatten
from tensorflow.keras.layers import Conv2D
from tensorflow.keras.layers import MaxPooling2D
# Connect to the SQLite database
conn = sqlite3.connect('sentiment.db')
cursor = conn.cursor()
# Create a table for user inputs if it doesn't exist
cursor.execute('''
CREATE TABLE IF NOT EXISTS user_inputs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_input TEXT,
sentiment TEXT
)
''')
conn.commit()
# Configure Streamlit page layout
st.set_page_config(layout="wide")
# Dictionary mapping emotion index to emotion labels
emotion_dict = {0: "Angry", 1: "Disgusted", 2: "Fearful", 3: "Happy", 4: "Neutral", 5: "Sad", 6: "Surprised"}
# Load music data from CSV file
df = pd.read_csv('muse_v3.csv')
df['link'] = df['lastfm_url']
df['name'] = df['track']
df['emotional'] = df['number_of_emotion_tags']
df['pleasant'] = df['valence_tags']
df = df[['name','emotional','pleasant','link','artist']]
df = df.sort_values(by=["emotional", "pleasant"])
df.reset_index()
# Rename columns for better readability
df_sadp = df[:9000]
df_sadn = df[9000:18000]
df_fearp = df[18000:27000]
df_fearn = df[27000:36000]
df_angryp = df[36000:45000]
df_angryn = df[45000:54000]
df_neutralp = df[54000:63000]
df_neutraln = df[63000:72000]
df_happyp = df[72000:81000]
df_happyn = df[81000:]
# Split the dataframe into different emotion categories
# (e.g., df_sadp, df_sadn, df_fearp, df_fearn, etc.)
# Function to generate music recommendations based on selected emotions
def fun(emotions):
data = pd.DataFrame()
# Logic to select music based on the combination of emotions
if len(emotions) == 1:
v = emotions[0]
t = 30
if v == 'neutralp':
temp = df_neutralp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'neutraln':
temp = df_neutraln.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'angryp':
temp = df_angryp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'angryn':
temp = df_angryn.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'fearfulp':
temp = df_fearp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'fearfuln':
temp = df_fearn.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'happyp':
temp = df_happyp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'happyn':
temp = df_happypn.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'sadp':
temp = df_sadp.sample(n=t)
data = pd.concat([data, temp[:]])
else:
temp = df_sadn.sample(n=t)
data = pd.concat([data, temp[:]])
elif len(emotions) == 2:
times = [20,10]
for i in range(len(emotions)):
v = emotions[i]
t = times[i]
if v == 'neutralp':
temp = df_neutralp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'neutraln':
temp = df_neutraln.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'angryp':
temp = df_angryp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'angryn':
temp = df_angryn.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'fearfulp':
temp = df_fearp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'fearfuln':
temp = df_fearn.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'happyp':
temp = df_happyp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'happyn':
temp = df_happypn.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'sadp':
temp = df_sadp.sample(n=t)
data = pd.concat([data, temp[:]])
else:
temp = df_sadn.sample(n=t)
data = pd.concat([data, temp[:]])
elif len(emotions) == 3:
times = [15,10,5]
for i in range(len(emotions)):
v = emotions[i]
t = times[i]
if v == 'neutralp':
temp = df_neutralp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'neutraln':
temp = df_neutraln.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'angryp':
temp = df_angryp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'angryn':
temp = df_angryn.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'fearfulp':
temp = df_fearp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'fearfuln':
temp = df_fearn.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'happyp':
temp = df_happyp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'happyn':
temp = df_happypn.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'sadp':
temp = df_sadp.sample(n=t)
data = pd.concat([data, temp[:]])
else:
temp = df_sadn.sample(n=t)
data = pd.concat([data, temp[:]])
elif len(emotions) == 4:
times = [10,9,8,3]
for i in range(len(emotions)):
v = emotions[i]
t = times[i]
if v == 'neutralp':
temp = df_neutralp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'neutraln':
temp = df_neutraln.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'angryp':
temp = df_angryp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'angryn':
temp = df_angryn.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'fearfulp':
temp = df_fearp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'fearfuln':
temp = df_fearn.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'happyp':
temp = df_happyp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'happyn':
temp = df_happypn.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'sadp':
temp = df_sadp.sample(n=t)
data = pd.concat([data, temp[:]])
else:
temp = df_sadn.sample(n=t)
data = pd.concat([data, temp[:]])
else:
times = [10,7,6,5,2]
for i in range(len(emotions)):
v = emotions[i]
t = times[i]
if v == 'neutralp':
temp = df_neutralp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'neutraln':
temp = df_neutraln.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'angryp':
temp = df_angryp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'angryn':
temp = df_angryn.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'fearfulp':
temp = df_fearp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'fearfuln':
temp = df_fearn.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'happyp':
temp = df_happyp.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'happyn':
temp = df_happypn.sample(n=t)
data = pd.concat([data, temp[:]])
elif v == 'sadp':
temp = df_sadp.sample(n=t)
data = pd.concat([data, temp[:]])
else:
temp = df_sadn.sample(n=t)
data = pd.concat([data, temp[:]])
return data
# Function to preprocess a list and return unique elements in the order of occurrence
def pre(l):
result = [item for items, c in Counter(l).most_common() for item in [items] * c]
ul = []
for x in result:
if x not in ul:
ul.append(x)
return ul
# Function to create a convolutional neural network (CNN) model
def create_model():
# Define the model architecture
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(48,48,1)))
model.add(Conv2D(64, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(1024, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(7, activation='softmax'))
model.load_weights('model.h5')
return model
# Function to insert user input into the SQLite database
def insert_user_input(user_input,sentiment):
sentiment = 'Positive' if sentiment == 'P' else 'Negative'
cursor.execute('INSERT INTO user_inputs (user_input,sentiment) VALUES (?,?)', (user_input,sentiment,))
conn.commit()
# Function to retrieve user inputs from the database
def get_user_inputs():
cursor.execute('SELECT user_input,sentiment FROM user_inputs')
data = cursor.fetchall()
return data
# Function to perform sentiment analysis using TextBlob
def sentiment_analysis(text):
blob = TextBlob(text)
polarity = blob.sentiment.polarity
if polarity >= 0:
return 'P'
else:
return 'N'
# Main function to run the Streamlit app
def main():
model = create_model()
cv2.ocl.setUseOpenCL(False)
cap = cv2.VideoCapture(0)
st.markdown("<h2 style='text-align: center; color: grey;'><b>Emotion based music recommendation</b></h2>", unsafe_allow_html=True)
st.markdown("<h5 style='text-align: center; color: grey;'><b>Click on the name of recommended song to reach website</b></h5>", unsafe_allow_html=True)
col1,col2,col3 = st.columns(3)
with col1:
c1,c2 = st.columns(2)
c1.subheader("Text")
c2.subheader("Sentiment")
user_inputs = get_user_inputs()
user_inputs.reverse()
for input_text,sentiment in user_inputs:
c1.write(f"- {input_text[:15]}")
c2.write(f"- {sentiment}")
submit = False
user_input=""
with col2:
user_input = st.text_area("Enter Text:", height=500)
sentiment = sentiment_analysis(user_input)
c1,c2,c3 = st.columns(3)
submit = col2.button("Submit")
if submit and user_input != "":
insert_user_input(user_input,sentiment)
new_emotions = []
with col3:
if submit and user_input != "":
count = 0
emotions = []
while True:
emotions.clear()
ret, frame = cap.read()
if not ret:
break
face = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5)
count = count + 1
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y - 50), (x + w, y + h + 10), (255, 0, 0), 2)
roi_gray = gray[y:y + h, x:x + w]
cropped_img = np.expand_dims(np.expand_dims(cv2.resize(roi_gray, (48, 48)), -1), 0)
prediction = model.predict(cropped_img)
max_index = int(np.argmax(prediction))
emotions.append(emotion_dict[max_index])
cv2.putText(frame, emotion_dict[max_index], (x + 20, y - 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)
cv2.imshow('Video', cv2.resize(frame, (1000, 700), interpolation=cv2.INTER_CUBIC))
if cv2.waitKey(1) & 0xFF == ord('x'):
break
if count >= 20:
break
cap.release()
cv2.destroyAllWindows()
emotions = pre(emotions)
for i in emotions:
new_emotions.append(i.lower()+sentiment)
elif submit and user_input == "":
st.error("Please enter text to get recommendations")
new_df = fun(new_emotions)
col3.markdown("<h5 style='text-align: center; color: grey;'><b>Recommended song's with artist names</b></h5>", unsafe_allow_html=True)
col3.write("---------------------------------------------------------------------------------------------------------------------")
try:
for l,a,n,i in zip(new_df["link"],new_df['artist'],new_df['name'],range(30)):
col3.markdown("""<h4 style='text-align: center;'><a href={}>{} - {}</a></h4>""".format(l,i+1,n),unsafe_allow_html=True)
col3.markdown("<h5 style='text-align: center; color: grey;'><i>{}</i></h5>".format(a), unsafe_allow_html=True)
col3.write("---------------------------------------------------------------------------------------------------------------------")
except:
pass
# Run the Streamlit app if the script is executed directly
if __name__ == '__main__':
main()
This source diff could not be displayed because it is too large. You can view the blob instead.
File added
This source diff could not be displayed because it is too large. You can view the blob instead.
File added
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment