3v324v23 commited on
Commit
407720a
·
1 Parent(s): 98cdfbf

initial commit

Browse files
__pycache__/eda.cpython-310.pyc ADDED
Binary file (4.61 kB). View file
 
__pycache__/eda.cpython-39.pyc ADDED
Binary file (4.89 kB). View file
 
__pycache__/model_result.cpython-39.pyc ADDED
Binary file (1.52 kB). View file
 
__pycache__/prediction.cpython-310.pyc ADDED
Binary file (4.49 kB). View file
 
__pycache__/prediction.cpython-39.pyc ADDED
Binary file (3.32 kB). View file
 
app.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import eda
3
+ import model_result
4
+ import prediction
5
+ from streamlit_option_menu import option_menu
6
+
7
+
8
+
9
+ st.sidebar.header("Emotion Classification")
10
+ st.title("Facial Emotion Classification")
11
+
12
+ with st.sidebar:
13
+ st.write("Ediashta Revindra - FTDS-020")
14
+ selected = option_menu(
15
+ "Menu",
16
+ [
17
+ "Distribution",
18
+ "Image Sample",
19
+ "Model Result",
20
+ "Classification",
21
+ ],
22
+ icons=["bar-chart", "link-45deg", "code-square"],
23
+ menu_icon="cast",
24
+ default_index=0,
25
+ )
26
+
27
+ if selected == "Distribution":
28
+ eda.distribution()
29
+ elif selected == "Image Sample":
30
+ eda.samples()
31
+ elif selected == "Model Result":
32
+ model_result.report()
33
+ elif selected == "Classification":
34
+ prediction.predict()
csv/distribution.csv ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ ,label,count
2
+ 3,happy,7215
3
+ 4,neutral,4965
4
+ 5,sad,4830
5
+ 2,fearful,4097
6
+ 0,angry,3995
7
+ 6,surprised,3171
8
+ 1,disgusted,436
csv/training_history.csv ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ,loss,accuracy,val_loss,val_accuracy,lr
2
+ 0,2.1469740867614746,0.25343969464302063,1.856235146522522,0.2595430612564087,0.001
3
+ 1,1.643206000328064,0.36344003677368164,1.4188605546951294,0.45012539625167847,0.001
4
+ 2,1.47542405128479,0.42669546604156494,1.4378496408462524,0.4527723491191864,0.001
5
+ 3,1.3760950565338135,0.4718729257583618,1.4727094173431396,0.44246307015419006,0.001
6
+ 4,1.3218955993652344,0.49879828095436096,1.2228283882141113,0.5337141156196594,0.001
7
+ 5,1.274165391921997,0.51645827293396,1.21588134765625,0.5480635166168213,0.001
8
+ 6,1.2332035303115845,0.5338395833969116,1.138999342918396,0.5658957958221436,0.001
9
+ 7,1.1999855041503906,0.5470758080482483,1.1163111925125122,0.5743939876556396,0.001
10
+ 8,1.1698594093322754,0.5580131411552429,1.2153265476226807,0.5353859066963196,0.001
11
+ 9,1.1533291339874268,0.5654324293136597,1.081765055656433,0.5884647369384766,0.001
12
+ 10,1.1245169639587402,0.5771012306213379,1.1175576448440552,0.5720256567001343,0.001
13
+ 11,1.1052570343017578,0.5884217619895935,1.2645843029022217,0.5263304710388184,0.001
14
+ 12,1.087416172027588,0.5925667881965637,1.1044645309448242,0.5867930054664612,0.001
15
+ 13,1.0727094411849976,0.6007872223854065,1.0925219058990479,0.5810810923576355,0.001
16
+ 14,1.0691781044006348,0.6035041213035583,1.0716830492019653,0.5964056849479675,0.001
17
+ 15,1.0509978532791138,0.6126649975776672,1.0216671228408813,0.615631103515625,0.001
18
+ 16,1.0409389734268188,0.6107492446899414,1.003859043121338,0.6241292953491211,0.001
19
+ 17,1.022071123123169,0.6197708249092102,0.9891683459281921,0.631234347820282,0.001
20
+ 18,1.0206458568572998,0.6199101209640503,1.0193976163864136,0.6253831386566162,0.001
21
+ 19,1.0173377990722656,0.6225225329399109,1.0119186639785767,0.6239899396896362,0.001
22
+ 20,0.9973097443580627,0.6285833716392517,0.9888020753860474,0.6344385743141174,0.001
23
+ 21,0.9959574937820435,0.6298373341560364,0.9672532081604004,0.6361103653907776,0.001
24
+ 22,0.9838335514068604,0.6360374689102173,0.9860186576843262,0.6310949921607971,0.001
25
+ 23,0.9794051647186279,0.635410487651825,0.9807018041610718,0.6375035047531128,0.001
26
+ 24,0.9747901558876038,0.6415410041809082,0.9648522734642029,0.6422401666641235,0.001
27
+ 25,0.965321958065033,0.6438050866127014,0.9513241648674011,0.6448871493339539,0.001
28
+ 26,0.9587099552154541,0.6479501128196716,0.9564236998558044,0.6394538879394531,0.001
29
+ 27,0.9502144455909729,0.6488906145095825,0.9563396573066711,0.6468375325202942,0.001
30
+ 28,0.9410316944122314,0.652060329914093,0.9778268933296204,0.6418222188949585,0.001
31
+ 29,0.9368909001350403,0.6520255208015442,0.9706842303276062,0.6391752362251282,0.001
32
+ 30,0.9361016154289246,0.653140127658844,0.9610183835029602,0.6462802886962891,0.001
33
+ 31,0.9268645644187927,0.6564840078353882,0.9403449296951294,0.6504597663879395,0.001
34
+ 32,0.9242078065872192,0.6620920300483704,0.9947916269302368,0.630259096622467,0.001
35
+ 33,0.9099783897399902,0.6643561124801636,0.976849377155304,0.6409863233566284,0.001
36
+ 34,0.9128876328468323,0.6637291312217712,0.9144724011421204,0.6671774983406067,0.001
37
+ 35,0.9059697985649109,0.6647392511367798,0.9187557101249695,0.6631373763084412,0.001
38
+ 36,0.9036375880241394,0.6690236330032349,0.9340527653694153,0.6521314978599548,0.001
39
+ 37,0.892905056476593,0.6716012358665466,0.9564922451972961,0.6529673933982849,0.001
40
+ 38,0.8900725245475769,0.6724023818969727,1.034966230392456,0.6206464171409607,0.001
41
+ 39,0.8922945261001587,0.6732383370399475,0.9608591198921204,0.6455837488174438,0.001
42
+ 40,0.8557736277580261,0.6858476400375366,0.9025119543075562,0.6681526899337769,0.00020000001
43
+ 41,0.8454394936561584,0.6894005537033081,0.9047268629074097,0.6668988466262817,0.00020000001
44
+ 42,0.8351521492004395,0.6945556998252869,0.913826048374176,0.6688492894172668,0.00020000001
45
+ 43,0.8299487829208374,0.6959141492843628,0.9063172340393066,0.6701030731201172,0.00020000001
46
+ 44,0.8238732814788818,0.6976906061172485,0.9130178689956665,0.6701030731201172,0.00020000001
47
+ 45,0.820328950881958,0.6992232203483582,0.911518394947052,0.6716355681419373,0.00020000001
48
+ 46,0.819961428642273,0.6973074674606323,0.9138140082359314,0.6726107597351074,0.00020000001
49
+ 47,0.8194107413291931,0.6981434226036072,0.9112961888313293,0.6716355681419373,0.00020000001
50
+ 48,0.8144147992134094,0.6992928981781006,0.9087201356887817,0.6751184463500977,0.00020000001
51
+ 49,0.812261700630188,0.7022536396980286,0.9128804206848145,0.6751184463500977,0.00020000001
52
+ 50,0.8110775351524353,0.7035424709320068,0.9172229170799255,0.6671774983406067,0.00020000001
53
+ 51,0.797129213809967,0.7063986659049988,0.906335711479187,0.6756756901741028,0.00020000001
54
+ 52,0.7997974157333374,0.70636385679245,0.915867805480957,0.6726107597351074,0.00020000001
55
+ 53,0.7991617321968079,0.7080706357955933,0.9098061919212341,0.676650881767273,0.00020000001
56
+ 54,0.7924382090568542,0.7120763659477234,0.9165937900543213,0.6735859513282776,0.00020000001
57
+ 55,0.7919761538505554,0.7075133323669434,0.9187894463539124,0.6713569164276123,0.00020000001
58
+ 56,0.7897159457206726,0.7133303284645081,0.9250094294548035,0.6723321080207825,0.00020000001
59
+ 57,0.7903206944465637,0.7092549204826355,0.9148570895195007,0.675954282283783,0.00020000001
60
+ 58,0.7874423861503601,0.7086279392242432,0.916176974773407,0.6755363345146179,0.00020000001
61
+ 59,0.784817099571228,0.7122505307197571,0.9134920239448547,0.6745611429214478,4.0000003e-05
62
+ 60,0.7739878296852112,0.7166742086410522,0.9130846858024597,0.6756756901741028,4.0000003e-05
63
+ 61,0.7737305164337158,0.7153157591819763,0.9111678600311279,0.676650881767273,4.0000003e-05
64
+ 62,0.7797554135322571,0.7169528603553772,0.9143626689910889,0.6765115857124329,4.0000003e-05
65
+ 63,0.7777878642082214,0.7160472273826599,0.9157006144523621,0.6747004985809326,4.0000003e-05
eda.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import seaborn as sns
4
+ import matplotlib.pyplot as plt
5
+ import plotly.express as px
6
+
7
+ dist_df = pd.read_csv('./csv/distribution.csv')
8
+
9
+
10
+ st.set_page_config(
11
+ page_title="Facial Emotion Classification",
12
+ layout="wide",
13
+ initial_sidebar_state="expanded",
14
+ )
15
+
16
+ def distribution():
17
+ # distribution plot
18
+
19
+ st.header("Image Distribution")
20
+
21
+ fig = px.bar(dist_df,
22
+ x="label", y="count",
23
+ labels={"label": "Emotions", "count": "Image Count"},
24
+ color="label", template="plotly_white")
25
+ fig.update_layout(height=600)
26
+
27
+ # Show the plot
28
+ st.plotly_chart(fig, use_container_width=True)
29
+
30
+ st.markdown('''
31
+
32
+ ''')
33
+
34
+ def samples():
35
+ st.header("Image Samples")
36
+
37
+ sample_img = st.sidebar.selectbox(label="Select Emotion Sample",
38
+ options=["Angry", "Disgusted", "Fearful", "Happy", "Neutral", "Sad", "Surprised"])
39
+
40
+ if sample_img == "Angry":
41
+ st.image('./image/angry.png')
42
+ st.markdown('''
43
+ This emotion is usually characterized by feelings of anger, frustration, and dissatisfaction towards something perceived as threatening or hurtful.
44
+
45
+ **Physical Signs:**
46
+
47
+ * The outer part of the eyebrows is raised.
48
+ * The eyes are usually narrowed and sharp.
49
+ * The muscles around the mouth are tensed.
50
+ ''')
51
+
52
+ elif sample_img == "Disgusted":
53
+ st.image('./image/disgusted.png')
54
+ st.markdown('''
55
+ This emotion is related to feelings of fear or being disturbed by something disliked or considered disgusting.
56
+
57
+ **Physical Signs**:
58
+ - The eyebrows are raised.
59
+ - The upper eyelids are raised.
60
+ - The nose is wrinkled.
61
+ - Usually, the mouth is slightly tense and slightly raised.
62
+
63
+ ''')
64
+
65
+ elif sample_img == "Fearful":
66
+ st.image('./image/fearful.png')
67
+ st.markdown('''
68
+ This emotion involves feelings of fear or anxiety due to the presence of a threat or danger.
69
+
70
+ **Physical Signs**:
71
+ - Widened eyes
72
+ - Outer part of the eyebrows slightly lowered
73
+ - Mouth usually slightly downturned
74
+ - In this emotion, hands are often used to cover parts of the face.
75
+
76
+ ''')
77
+
78
+ elif sample_img == "Happy":
79
+ st.image('./image/happy.png')
80
+ st.markdown('''
81
+ This emotion is usually characterized by feelings of joy, happiness, and contentment. Happy facial expressions include smiling, twinkling eyes, and a tendency to be open and friendly.
82
+
83
+ **Physical Signs**:
84
+ - Eyes appear sparkling
85
+ - Mouth is smiling
86
+
87
+ ''')
88
+
89
+ elif sample_img == "Neutral":
90
+ st.image('./image/neutral.png')
91
+ st.markdown('''
92
+ Neutral emotion indicates the absence of strong emotions or facial expressions that do not show intense feelings.
93
+
94
+ Physical Signs in this expression are that each **facial feature appears not prominent**.
95
+
96
+ ''')
97
+
98
+ elif sample_img == "Sad":
99
+ st.image('./image/sad.png')
100
+ st.markdown('''
101
+ This emotion involves feelings of sadness, disappointment, and loss.
102
+
103
+ Physical Signs:
104
+ - Eyebrows are usually furrowed.
105
+ - Eyes become downcast or droopy.
106
+ - The corners of the mouth slightly downturned.
107
+
108
+ ''')
109
+
110
+ elif sample_img == "Surprised":
111
+ st.image('./image/surprised.png')
112
+ st.markdown('''
113
+ This emotion arises when someone experiences an unexpected event or receives surprising information.
114
+
115
+ Physical Signs:
116
+ - Eyebrows raise entirely.
117
+ - Eyes widen.
118
+ - Typically, the mouth opens.
119
+
120
+ ''')
121
+
122
+ st.subheader("Mean (Avg.) of Image")
123
+ st.image('./image/mean.png')
124
+ st.markdown('''
125
+ By calculating the mean of image from each class, the following information is obtained:
126
+
127
+ * The most prominent expressions are **Happy and Surprised**, easily identifiable from the characteristics of the mouth.
128
+ * **Sad, Fearful, and Neutral** expressions are somewhat challenging to differentiate.
129
+ * **Angry and Disgusted** expressions appear similar due to the characteristics of the eyebrows and mouth.
130
+
131
+ ''')
132
+
133
+ if __name__ == "__main__":
134
+ distribution()
image/angry.png ADDED
image/disgusted.png ADDED
image/distribution.png ADDED
image/fearful.png ADDED
image/happy.png ADDED
image/mean.png ADDED
image/neutral.png ADDED
image/sad.png ADDED
image/surprised.png ADDED
model/model_fine_tune.h5 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a74e31c3ddbf80a2fd98801114af1d4d4ae4bdca95fb6a8ba767fbca05813a90
3
+ size 73012760
model_result.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import numpy as np
4
+ import seaborn as sns
5
+ import matplotlib.pyplot as plt
6
+ import plotly.express as px
7
+ import time
8
+
9
+ def report():
10
+
11
+ df = pd.read_csv('./csv/training_history.csv')
12
+ df.rename(columns={'Unnamed: 0':'epoch'}, inplace=True)
13
+
14
+ st.header("Model Report")
15
+
16
+ st.subheader("Performance")
17
+ plot_anim = st.sidebar.selectbox(label='Select Performance Metrics', options=["Accuracy", "Loss"])
18
+
19
+
20
+ def performance_plot(data):
21
+ progress_bar = st.sidebar.progress(0)
22
+ status_text = st.sidebar.empty()
23
+ last_rows = [df[data].iloc[0]]
24
+ chart = st.line_chart(last_rows, use_container_width=True, height=500)
25
+
26
+ for i in range(1, len(df)):
27
+ new_rows = [df[data].iloc[i]]
28
+ status_text.text(f"{round(i/63 * 100, 2)} % Complete")
29
+ chart.add_rows(new_rows)
30
+ progress_bar.progress(i)
31
+ last_rows = new_rows
32
+ time.sleep(0.05)
33
+
34
+ progress_bar.empty()
35
+ if plot_anim == "Accuracy":
36
+ data_plot = ['accuracy', 'val_accuracy']
37
+ performance_plot(data_plot)
38
+ else:
39
+ data_plot = ['loss', 'val_loss']
40
+ performance_plot(data_plot)
41
+
42
+ st.button("Re-run")
43
+
44
+ if __name__ == "__main__":
45
+ report()
prediction.py ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import numpy as np
4
+ import pickle
5
+ import tensorflow as tf
6
+ import matplotlib.pyplot as plt
7
+ from tensorflow.keras.layers import Dense, Input, concatenate
8
+ from tensorflow.keras.models import load_model
9
+ from tensorflow.keras.preprocessing import image
10
+ from PIL import Image
11
+ from urllib import request
12
+ from io import BytesIO
13
+
14
+
15
+ def predict():
16
+
17
+ emotion_classification_model = load_model('./model/model_fine_tune.h5')
18
+
19
+
20
+ url = "https://lh3.googleusercontent.com/0e8O0JPOp_ydq7wqv6kgYz6UpF9w_INfnOLIhnJZBEHFcWIygkuLa3SVghhGYgE0XWzQYBPb6wb1eQFN0pVIAYlzEeNojYuCWg=s0"
21
+
22
+ def img_url(url):
23
+ res = request.urlopen(url).read()
24
+ img_ori = image.load_img(BytesIO(res))
25
+ img = image.load_img(BytesIO(res), target_size=(48, 48), keep_aspect_ratio=True)
26
+ show_predict(img, img_ori)
27
+
28
+ def show_predict(img, img_ori):
29
+ col1, col2 = st.columns(2)
30
+ fig = plt.figure()
31
+ plt.imshow(img_ori)
32
+ plt.axis('off')
33
+ col1.pyplot(fig)
34
+
35
+ img_array = image.img_to_array(img)
36
+ img_array = np.expand_dims(img_array, axis=0)
37
+ img_array /= 255.0 # Normalize the image
38
+
39
+ inf_pred_single = emotion_classification_model.predict(img_array)
40
+
41
+ data_inf_single = []
42
+
43
+ rank = []
44
+
45
+ for i in inf_pred_single[0]:
46
+ value = i * 100
47
+ rank.append(value)
48
+ data_inf_single.append(f'{value.round(2)}%')
49
+
50
+ rank = (-np.array(rank)).argsort()[:2]
51
+
52
+ pred_class_single = pd.DataFrame(class_labels).loc[rank][0].tolist()
53
+
54
+ prediction_result_single = pd.DataFrame(columns=["angry", "disgusted", "fearful", "happy", "neutral", "sad", "surprised"])
55
+ prediction_result_single.loc[len(prediction_result_single)] = data_inf_single
56
+
57
+ prediction_result_single
58
+
59
+ st.markdown("""
60
+ <style>
61
+ .big-font {
62
+ font-size:30px !important;
63
+ }
64
+ </style>
65
+ """, unsafe_allow_html=True)
66
+
67
+ col2.write('Prediction Class:')
68
+ col2.markdown(f'<p class="big-font">{pred_class_single[0].capitalize()}</p>', unsafe_allow_html=True)
69
+
70
+ col2.dataframe(prediction_result_single.set_index(prediction_result_single.columns[0]), use_container_width=True)
71
+
72
+ class_labels = ["angry", "disgusted", "fearful", "happy", "neutral", "sad", "surprised"]
73
+
74
+ st.write('Insert Image URL Below (Make sure face is centered and fitted)')
75
+
76
+ st.markdown('[Example Image](https://cdn.idntimes.com/content-images/community/2021/12/whatsapp-image-2021-12-02-at-190446-8ecf63e1fa6b5c8c5e9ac43034bc86d3-c563813ea99f16a795ad4c53af10881a_600x400.jpeg)')
77
+
78
+ col1, col2 = st.columns((9,1))
79
+ url_input = col1.text_input(label="Image Links")
80
+
81
+ st.markdown(
82
+ """
83
+ <style>
84
+ button {
85
+ height: auto;
86
+ margin-top: 28px !important;
87
+ padding-left: 24px !important;
88
+ padding-right: 24px !important;
89
+ }
90
+ </style>
91
+ """,
92
+ unsafe_allow_html=True,
93
+ )
94
+ pred_button = col2.button(label="Predict")
95
+
96
+ if pred_button:
97
+ img_url(url_input)
98
+ else:
99
+ img_url(url)
100
+
101
+
102
+
103
+ if __name__ == "__main__":
104
+ predict()
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ seaborn
2
+ pandas
3
+ matplotlib
4
+ plotly
5
+ Pillow
6
+ scikit-learn==1.2.2
7
+ feature_engine
8
+ streamlit_option_menu
9
+ tensorflow ==2.10.0