-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.py
348 lines (267 loc) · 11.9 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# Importing modules
import numpy as np
import streamlit as st
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
# Read csv file containing data.
df = pd.read_csv('muse_v3.csv')
# Renaming column of dataframe.
df['link'] = df['lastfm_url']
df['name'] = df['track']
df['emotional'] = df['number_of_emotion_tags']
df['pleasant'] = df['valence_tags']
# Taking out useful column.
df = df[['name','emotional','pleasant','link','artist']]
# Sort column based on emotional & pleasant column value.
# Pleasant = degree of pleasant in that particular song.
# Emotional = emotional word used in that song.
df = df.sort_values(by=["emotional", "pleasant"])
df.reset_index()
# Diving dataframe based on emotional & pleasant value in sorted order.
df_sad = df[:18000]
df_fear = df[18000:36000]
df_angry = df[36000:54000]
df_neutral = df[54000:72000]
df_happy = df[72000:]
# Task of function 'fun' is to take list of unique emotions & return dataframe of 30 rows.
def fun(list):
# Creating Empty Dataframe
data = pd.DataFrame()
# If list of emotion's contain only 1 emotion
if len(list) == 1:
# Emotion name
v = list[0]
# Number of rows for this emotion
t = 30
if v == 'Neutral':
# Adding rows to data
data = data.append(df_neutral.sample(n=t))
elif v == 'Angry':
# Adding rows to data
data = data.append(df_angry.sample(n=t))
elif v == 'fear':
# Adding rows to data
data = data.append(df_fear.sample(n=t))
elif v == 'happy':
# Adding rows to data
data = data.append(df_happy.sample(n=t))
else:
# Adding rows to data
data = data.append(df_sad.sample(n=t))
# elif len(list) == 2:
# # Row's count per emotion
# times = [20,10]
# for i in range(len(list)):
# # Emotion name
# v = list[i]
# # Number of rows for this emotion
# t = times[i]
# if v == 'Neutral':
# # Adding rows to data
# data = data.append(df_neutral.sample(n=t))
# elif v == 'Angry':
# # Adding rows to data
# data = data.append(df_angry.sample(n=t))
# elif v == 'fear':
# # Adding rows to data
# data = data.append(df_fear.sample(n=t))
# elif v == 'happy':
# # Adding rows to data
# data = data.append(df_happy.sample(n=t))
# else:
# # Adding rows to data
# data = data.append(df_sad.sample(n=t))
elif len(list) == 3:
# Row's count per emotion
times = [15,10,5]
for i in range(len(list)):
# Emotion name
v = list[i]
# Number of rows for this emotion
t = times[i]
if v == 'Neutral':
# Adding rows to data
data = data.append(df_neutral.sample(n=t))
elif v == 'Angry':
# Adding rows to data
data = data.append(df_angry.sample(n=t))
elif v == 'fear':
# Adding rows to data
data = data.append(df_fear.sample(n=t))
elif v == 'happy':
# Adding rows to data
data = data.append(df_happy.sample(n=t))
else:
# Adding rows to data
data = data.append(df_sad.sample(n=t))
elif len(list) == 4:
# Row's count per emotion
times = [10,9,8,3]
for i in range(len(list)):
# Emotion name
v = list[i]
# Number of rows for this emotion
t = times[i]
if v == 'Neutral':
# Adding rows to data
data = data.append(df_neutral.sample(n=t))
elif v == 'Angry':
# Adding rows to data
data = data.append(df_angry.sample(n=t))
elif v == 'fear':
# Adding rows to data
data = data.append(df_fear.sample(n=t))
elif v == 'happy':
# Adding rows to data
data = data.append(df_happy.sample(n=t))
else:
# Adding rows to data
data = data.append(df_sad.sample(n=t))
else:
# Row's count per emotion
times = [10,7,6,5,2]
for i in range(len(list)):
# Emotion name
v = list[i]
# Number of rows for this emotion
t = times[i]
if v == 'Neutral':
# Adding rows to data
data = data.append(df_neutral.sample(n=t))
elif v == 'Angry':
# Adding rows to data
data = data.append(df_angry.sample(n=t))
elif v == 'fear':
# Adding rows to data
data = data.append(df_fear.sample(n=t))
elif v == 'happy':
# Adding rows to data
data = data.append(df_happy.sample(n=t))
else:
# Adding rows to data
data = data.append(df_sad.sample(n=t))
return data
# Task of function 'pre' is to take list of emotions (containing duplicate also) &
#return unique list of emotion in sorted order based on count.
def pre(l):
# result contain sorted emotion's(duplicate present if any)
# Counter has a most_common() method that returns a list of tuples of (element, count) sorted by counts.
result = [item for items, c in Counter(l).most_common()
for item in [items] * c]
# Creating empty unique list
ul = []
for x in result:
if x not in ul:
ul.append(x)
return ul
# Creating model
# kerel_size = specifying the height and width of the 2D convolution window.
# Convolution window : A convolution layer defines a window by which we examine a subset of the image.
# RELU : The rectified linear activation function or ReLU for short is a piecewise linear function that will output the input directly if it is positive,
# otherwise, it will output zero.
model = Sequential()
model.add(Conv2D(32, kernel_size=(6, 6), activation='relu', input_shape=(48,48,1)))
model.add(Conv2D(64, kernel_size=(6, 6), activation='relu'))
# MaxPooling2D : Max poolistrng is a pooling operation that selects the maximum element from the region of the feature map covered by the filter.
model.add(MaxPooling2D(pool_size=(2, 2)))
# Dropout is a technique where randomly selected neurons are ignored during training.Dropout is a technique where randomly selected neurons are ignored during training.
model.add(Dropout(0.25))
model.add(Conv2D(128, kernel_size=(6, 6), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(128, kernel_size=(6, 6), 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))
# Softmax : It is mainly used to normalize neural networks output to fit between zero and one.
model.add(Dense(7, activation='softmax'))
emotion_dict = {0: "Angry", 1: "Disgusted", 2: "Fearful", 3: "Happy", 4: "Neutral", 5: "Sad", 6: "Surprised"}
# Not Attach OpenCL context to OpenCV.
cv2.ocl.setUseOpenCL(False)
# return video from the first webcam on your computer.
cap = cv2.VideoCapture(0)
# Text or heading's
st.markdown("<h2 style='text-align: center; color: gold;'><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)
# Just for indentation
col1,col2,col3 = st.columns(3)
list = []
with col1:
pass
with col2:
if st.button('SCAN EMOTION(Click here)'):
# Clearing values
count = 0
list.clear()
while True:
# Basically, ret is a boolean regarding whether or not there was a return at all, at the frame is each frame that is returned.
ret, frame = cap.read()
if not ret:
break
# CascadeClassifier : It is a machine learning based approach where a cascade function is trained from a lot of positive and negative images.
face = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# cv2.cvtColor() method is used to convert an image from one color space to another.
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Detects objects of different sizes in the input image.
faces = face.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5)
# Counter
count = count + 1
for (x, y, w, h) in faces:
# Creating rectangle around face
cv2.rectangle(frame, (x, y - 50), (x + w, y + h + 10), (255, 0, 0), 2)
# Taking image out
roi_gray = gray[y:y + h, x:x + w]
# expand_dims() function is used to expand the shape of an array.
cropped_img = np.expand_dims(np.expand_dims(cv2.resize(roi_gray, (48, 48)), -1), 0)
# Predicting model on cropped image
prediction = model.predict(cropped_img)
# Appending emotion to list
max_index = int(np.argmax(prediction))
list.append(emotion_dict[max_index])
# Putting text of emotion on top of rectangle
# fontScale = 1
# thickness = 2
cv2.putText(frame, emotion_dict[max_index], (x + 20, y - 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)
# Image interpolation occurs when you resize or distort your image from one pixel grid to another.
cv2.imshow('Video', cv2.resize(frame, (1000, 700), interpolation=cv2.INTER_CUBIC))
# For emergency close window
if cv2.waitKey(1) & 0xFF == ord('x'):
break
# To get time for window to stay, so that we take input
if count >= 30:
break
# Destroy cv2 window
cap.release()
cv2.destroyAllWindows()
# Preprocessing list of emotion's
list = pre(list)
with col3:
pass
# Calling 'fun()' or creating dataframe
new_df = fun(list)
# Just for separation
st.write("")
# Normal text
st.markdown("<h5 style='text-align: center; color: white;'><b>Recommended song's with artist names</b></h5>", unsafe_allow_html=True)
# Just for separation
st.write("---------------------------------------------------------------------------------------------------------------------")
try:
# l = iterator over link column in dataframe
# a = iterator over artist column in dataframe
# i = iterator from (0 to 30)
# n = iterator over name column in dataframe
for l,a,n,i in zip(new_df["link"],new_df['artist'],new_df['name'],range(30)):
# Recommended song name
st.markdown("""<h4 style='text-align: center;'><a href={}>{} - {}</a></h4>""".format(l,i+1,n),unsafe_allow_html=True)
# Artist name
st.markdown("<h5 style='text-align: center; color: grey;'><i>{}</i></h5>".format(a), unsafe_allow_html=True)
# Just for separation
st.write("---------------------------------------------------------------------------------------------------------------------")
except:
pass