Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import sys
- import numpy as np
- import cv2
- from imutils import face_utils
- import imutils
- import dlib
- import PySimpleGUI as sg
- import gspread
- from oauth2client.service_account import ServiceAccountCredentials
- import time
- import pandas as pd
- import ast
- import random
- import tensorflow as tf
- from tensorflow import keras
- from tensorflow.keras import layers
- import tensorflow_datasets as tfds
- from statsmodels.tsa.arima_model import ARIMA
- import datetime
- import matplotlib.pyplot as plt
- import matplotlib
- import pyimgur
- import os
- data_list = []
- scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
- creds = ServiceAccountCredentials.from_json_keyfile_name('Resync-12a9f4471898.json', scope)
- client = gspread.authorize(creds)
- sheet = client.open("Daily Resync Survey Results").sheet1
- sg.theme('LightPurple') # Add a touch of color
- # All the stuff inside your window.
- layout = [[ sg.Column([[sg.Text('On a scale of 1-4, how effective do you believe Resync is in reducing your symptoms right now?'), sg.InputText()],
- [sg.Text('On a scale of 1-4, how helpful are the 2-week projections of your improvement?'), sg.InputText()],
- [sg.Text('On a scale of 1-4, how difficult is it to set up/use Resync?'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I look forward to waking up every morning.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I feel cheerful and full of energy.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I find joy in the simple things of life.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I am often in a good mood during these past two weeks.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I tend to work on things to my fullest.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I am energized by my surroundings.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I feel happy talking to my loved ones.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I get motivated and excited easily.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I feel content with my current life.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I am feeling happy these days.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I do not look forward to waking up every morning.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I cannot find joy in the simple things of life.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I am often feeling sad these past two weeks.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I often lack the energy to do simple things these past two weeks.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I have often lost motivation these past two weeks.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I often put on a fake smile for others.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I often put on a fake smile for myself.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): Talking with others drains my energy.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I carry out my tasks to get by with my day and life, to only exist.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): Everything feels numb and repetitive. '), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I am often worried about the future. '), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I feel overwhelmed with my life.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I often wake up in a cold sweat at night.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I feel nervous when talking with others.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I often get this irrational sense of anxiety.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I tend to imagine the worst possible outcome.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I stop myself before I get my hopes up.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I feel anxious being in my environment.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I tend to stay away from others out of fear/rejection.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I think I often have bad luck/cause incidents.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I often get angry.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I am often bothered by the little inconveniences.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I often raise my voice towards others in an aggressive manner.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): When angered, I cannot keep my emotions in check.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I have been feeling angered these past two weeks.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): Other people have been telling me I have been aggressive/angry these past two weeks.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): People often piss me off.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I can get very angry when thinking about negative thoughts/things that upset me.'), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I get angry when someone completely ignores me; e.g. thoughts, feelings, existence, etc. '), sg.InputText()],
- [sg.Text('1 (Not at all) to 4 (Strongly agree): I often imagine scenarios of getting revenge on a person that made me angry; e.g. through verbal and/or physical actions.'), sg.InputText()],
- [sg.Button('Ok'), sg.Button('Cancel')]], key='-COL1-', scrollable=True) ]]
- # Create the Window
- window = sg.Window('Daily Resync Survey!', layout)
- while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Cancel': # if user closes window or clicks cancel
- break
- if event == 'Ok':
- response = [values[0], values[1], values[2]]
- row = 1
- while(sheet.cell(row, 1).value != ''): # originally sheet.cell(row, 1).value == ' '
- row += 1
- time.sleep(1)
- sheet.insert_row(response, row)
- break
- window.close()
- def rect_to_bb(rect):
- # take a bounding predicted by dlib and convert it
- # to the format (x, y, w, h) as we would normally do
- # with OpenCV
- x = rect.left()
- y = rect.top()
- w = rect.right() - x
- h = rect.bottom() - y
- # return a tuple of (x, y, w, h)
- return (x, y, w, h)
- def shape_to_np(shape, dtype="int"):
- # initialize the list of (x, y)-coordinates
- coords = np.zeros((68, 2), dtype=dtype)
- # loop over the 68 facial landmarks and convert them
- # to a 2-tuple of (x, y)-coordinates
- for i in range(0, 68):
- coords[i] = (shape.part(i).x, shape.part(i).y)
- # return the list of (x, y)-coordinates
- return coords
- # initialize dlib's face detector (HOG-based) and then create
- # the facial landmark predictor
- detector = dlib.get_frontal_face_detector()
- predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
- counter = 0
- iterations = 0
- already_calibrated = False
- cap = cv2.VideoCapture(0)
- while(True):
- # Capture frame-by-frame
- ret, frame = cap.read()
- # Our operations on the frame come here
- gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
- image = gray
- rects = detector(gray, 1)
- # loop over the face detections
- for (i, rect) in enumerate(rects):
- # determine the facial landmarks for the face region, then
- # convert the facial landmark (x, y)-coordinates to a NumPy
- # array
- shape = predictor(gray, rect)
- shape = face_utils.shape_to_np(shape) # SHAPE IS A NUMPY ARRAY; YOU CAN SIMPLY INDEX TO GET THE COORDS THAT YOU NEED
- data = str(int(shape[20][1])) + ", " + str(int(shape[25][1])) + ", " + str(int(shape[38][1])) + ", " + str(int(shape[39][1])) + ", " + str(int(shape[41][1])) + ", " + str(int(shape[40][1])) + ", " + str(int(shape[43][1])) + ", " + str(int(shape[44][1])) + ", " + str(int(shape[47][1])) + ", " + str(int(shape[46][1])) + ", " + str(int(shape[49][1])) + ", " + str(int(shape[55][1])) + "\n"
- data_list.append(data)
- counter += 1
- # convert dlib's rectangle to a OpenCV-style bounding box
- # [i.e., (x, y, w, h)], then draw the face bounding box
- (x, y, w, h) = face_utils.rect_to_bb(rect)
- cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
- # show the face number
- cv2.putText(image, "Face #{}".format(i + 1), (x - 10, y - 10),
- cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
- # loop over the (x, y)-coordinates for the facial landmarks
- # and draw them on the image
- for (x, y) in shape:
- cv2.circle(image, (x, y), 1, (0, 0, 255), -1)
- print(counter)
- if(counter > 120):
- scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
- creds = ServiceAccountCredentials.from_json_keyfile_name('Resync-12a9f4471898.json', scope)
- client = gspread.authorize(creds)
- sheet = client.open("Resync Database").sheet1
- # each element of s (containing the most relevant facial landmarks) is separated by 120 "ticks" (approximately 24 seconds in total) in the script
- s = data_list
- #s = ['98, 99, 141, 151, 157, 156, 137, 137, 151, 152, 282, 303\n', '251, 256, 278, 283, 286, 286, 279, 279, 285, 286, 357, 371\n', '251, 256, 279, 283, 286, 285, 279, 280, 284, 285, 357, 372\n', '250, 257, 278, 282, 285, 285, 279, 280, 285, 285, 357, 372\n', '251, 257, 279, 282, 285, 285, 280, 280, 284, 285, 356, 372\n', '251, 257, 280, 284, 287, 286, 279, 280, 285, 285, 357, 372\n', '250, 256, 279, 283, 287, 286, 279, 280, 285, 286, 357, 372\n', '251, 257, 278, 282, 285, 285, 278, 279, 284, 285, 357, 372\n', '251, 258, 278, 282, 285, 284, 280, 280, 285, 286, 357, 372\n', '250, 258, 276, 280, 283, 283, 279, 280, 284, 285, 357, 373\n', '252, 258, 280, 284, 287, 286, 281, 281, 286, 286, 358, 373\n', '251, 257, 279, 283, 286, 285, 279, 280, 285, 285, 357, 371\n', '254, 258, 281, 285, 288, 287, 281, 281, 286, 287, 357, 373\n', '253, 257, 281, 285, 288, 287, 280, 281, 285, 286, 357, 373\n', '252, 258, 280, 284, 287, 286, 280, 280, 285, 286, 358, 372\n', '254, 257, 280, 285, 288, 287, 280, 280, 286, 286, 358, 373\n', '253, 258, 280, 284, 287, 287, 280, 281, 286, 287, 358, 374\n', '252, 259, 279, 283, 286, 286, 280, 281, 286, 287, 358, 373\n', '252, 257, 278, 284, 286, 286, 279, 279, 286, 286, 358, 374\n', '250, 258, 279, 282, 286, 285, 280, 281, 285, 286, 358, 374\n', '255, 257, 281, 285, 289, 287, 281, 281, 286, 286, 358, 374\n']
- # convert all inner lists (string representation) in s to actual lists
- s = [i.replace('\n', '') for i in s]
- s = [i.replace(',', '') for i in s]
- s = [i.split() for i in s]
- s = [[int(j) for j in i] for i in s]
- if(not already_calibrated):
- calibration = True
- else:
- calibration = False
- # preprocessing and feature extraction (max, min, peak-to-peak)
- eyebrows = [[a[0] for a in s], [a[1] for a in s]]
- left_eye = [[a[2] for a in s], [a[3] for a in s], [a[4] for a in s], [a[5] for a in s]]
- right_eye = [[a[6] for a in s], [a[7] for a in s], [a[8] for a in s], [a[9] for a in s]]
- mouth_corners = [[a[10] for a in s], [a[11] for a in s]]
- # wait do you need to normalize the heights
- # conversion to pandas dataframes
- eyebrows = [pd.DataFrame({"y": l}) for l in eyebrows]
- left_eye = [pd.DataFrame({"y": l}) for l in left_eye]
- right_eye = [pd.DataFrame({"y": l}) for l in right_eye]
- mouth_corners = [pd.DataFrame({"y": l}) for l in mouth_corners]
- # max
- eyebrows_max = [df.max() for df in eyebrows]
- left_eye_max = [df.max() for df in left_eye]
- right_eye_max = [df.max() for df in right_eye]
- mouth_corners_max = [df.max() for df in mouth_corners]
- # min
- eyebrows_min = [df.min() for df in eyebrows]
- left_eye_min = [df.min() for df in left_eye]
- right_eye_min = [df.min() for df in right_eye]
- mouth_corners_min = [df.min() for df in mouth_corners]
- # peak-to-peak
- eyebrows_peak = [max_value - eyebrows_min[index] for index, max_value in enumerate(eyebrows_max)]
- left_eye_peak = [max_value - left_eye_min[index] for index, max_value in enumerate(left_eye_max)]
- right_eye_peak = [max_value - right_eye_min[index] for index, max_value in enumerate(right_eye_max)]
- mouth_corners_peak = [max_value - mouth_corners_min[index] for index, max_value in enumerate(mouth_corners_max)]
- print(int(mouth_corners_peak[0]))
- # machine/deep learning classifier trained with labels that the client generates from an emotion evaluation test;
- # the one-shot/few-shot learning part is just data augmentation and/or regularization
- batch_size = 1
- epochs = 150
- characteristic_dist = np.asarray([14.0, 35.0, 22.0, 20.0])
- scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
- creds = ServiceAccountCredentials.from_json_keyfile_name('Resync-12a9f4471898.json', scope)
- client = gspread.authorize(creds)
- sheet = client.open("Resync Database").sheet1
- print(calibration)
- # model.fit() doesn't erase progress
- if(calibration):
- # format inputs: they'll just be all of the values in the dataframes generated above
- x = [int(eyebrows_max[0]), int(eyebrows_max[1]), int(left_eye_max[0]), int(left_eye_max[1]), int(left_eye_max[2]), int(left_eye_max[3]), int(right_eye_max[0]), int(right_eye_max[1]), int(right_eye_max[2]), int(right_eye_max[3]), int(left_eye_max[0]), int(left_eye_max[1]), int(left_eye_max[2]), int(mouth_corners_max[0]), int(mouth_corners_max[1])]
- x.extend([int(eyebrows_min[0]), int(eyebrows_min[1]), int(left_eye_min[0]), int(left_eye_min[1]), int(left_eye_min[2]), int(left_eye_min[3]), int(right_eye_min[0]), int(right_eye_min[1]), int(right_eye_min[2]), int(right_eye_min[3]), int(left_eye_min[0]), int(left_eye_min[1]), int(left_eye_min[2]), int(mouth_corners_min[0]), int(mouth_corners_min[1])])
- x.extend([int(eyebrows_peak[0]), int(eyebrows_peak[1]), int(left_eye_peak[0]), int(left_eye_peak[1]), int(left_eye_peak[2]), int(left_eye_peak[3]), int(right_eye_peak[0]), int(right_eye_peak[1]), int(right_eye_peak[2]), int(right_eye_peak[3]), int(left_eye_peak[0]), int(left_eye_peak[1]), int(left_eye_peak[2]), int(mouth_corners_peak[0]), int(mouth_corners_peak[1])])
- x = np.asarray(x)
- X = np.asarray([x])
- values = list(values.values())
- values = [int(i) for i in values]
- y = [a_i - b_i for a_i, b_i in zip(characteristic_dist, [sum(values[3:13]), sum(values[13:23]), sum(values[23:33]), sum(values[33:43])])]
- idx = y.index(max(y))
- y = [0.0]*4
- y[idx] = 1.0
- y = np.asarray(y)
- Y = np.asarray([y])
- # load the model from last time (h5) (the model should be defined elsewhere, saved as an h5, and put in the same directory)
- model = keras.models.load_model("resync.h5")
- model.fit(X, Y, batch_size=batch_size, epochs=epochs)
- model.save("resync.h5")
- already_calibrated = True
- counter = 0
- else:
- current_time = datetime.datetime.now()
- # format inputs: they'll just be all of the values in the dataframes generated above
- x = [int(eyebrows_max[0]), int(eyebrows_max[1]), int(left_eye_max[0]), int(left_eye_max[1]), int(left_eye_max[2]), int(left_eye_max[3]), int(right_eye_max[0]), int(right_eye_max[1]), int(right_eye_max[2]), int(right_eye_max[3]), int(left_eye_max[0]), int(left_eye_max[1]), int(left_eye_max[2]), int(mouth_corners_max[0]), int(mouth_corners_max[1])]
- x.extend([int(eyebrows_min[0]), int(eyebrows_min[1]), int(left_eye_min[0]), int(left_eye_min[1]), int(left_eye_min[2]), int(left_eye_min[3]), int(right_eye_min[0]), int(right_eye_min[1]), int(right_eye_min[2]), int(right_eye_min[3]), int(left_eye_min[0]), int(left_eye_min[1]), int(left_eye_min[2]), int(mouth_corners_min[0]), int(mouth_corners_min[1])])
- x.extend([int(eyebrows_peak[0]), int(eyebrows_peak[1]), int(left_eye_peak[0]), int(left_eye_peak[1]), int(left_eye_peak[2]), int(left_eye_peak[3]), int(right_eye_peak[0]), int(right_eye_peak[1]), int(right_eye_peak[2]), int(right_eye_peak[3]), int(left_eye_peak[0]), int(left_eye_peak[1]), int(left_eye_peak[2]), int(mouth_corners_peak[0]), int(mouth_corners_peak[1])])
- x = np.asarray(x)
- X = np.asarray([x])
- # load the model from last time (h5) (the model should be defined elsewhere, saved as an h5, and put in the same directory)
- model = keras.models.load_model("resync.h5")
- # REAL-TIME METRICS
- preds = model.predict(X)
- general_metric = np.average((characteristic_dist - preds[0])) # this is the other
- um_preds = preds.copy()
- preds = str(preds)
- general_metric = str(general_metric)
- preds = preds.replace("[[", "")
- preds = preds.replace("]]", "")
- #print(preds) # wait isn't this just the output of softmax
- #print(general_metric) # wait what does this actually indicate
- # GRAPHS
- # doesn't have to be restricted to the past two weeks
- # host on imgur or smth
- row = int(sheet.cell(1, 7).value)
- general_metrics = []
- predictions = []
- timestamps = []
- for idx in range(2, row):
- general_metrics.append(float(list(sheet.row_values(idx))[1]))
- timestamps.append(list(sheet.row_values(idx))[0])
- general_metrics = pd.Series(general_metrics)
- timestamps = pd.Series(timestamps)
- table = {"General Metric" : general_metrics, "Time" : timestamps}
- data = pd.DataFrame(table)
- fig, ax = plt.subplots()
- fig.autofmt_xdate()
- plt.gcf().subplots_adjust(bottom=0.35, left = 0.35)
- plt.plot_date([i for i in list(timestamps) if i != "Time"], [i for i in list(general_metrics) if i != "General Severity Metric"], xdate=True)
- plt.close(fig)
- cwd = os.getcwd()
- fig.savefig(cwd + '\\' + str(timestamps[0]).replace("-", "").replace(":","") + ".png") # temp path
- CLIENT_ID = "9d912e738dfe437" # client_secret: 81d5d9435ad9a6ebf6c76bdc1149d171a7321ae0
- im = pyimgur.Imgur(CLIENT_ID)
- uploaded_image = im.upload_image(cwd + '\\' + str(timestamps[0]).replace("-", "").replace(":","") + ".png", title="Uploaded with PyImgur")
- link = uploaded_image.link
- #print(link)
- # LONG-TERM METRICS
- arima_model = ARIMA(data["General Metric"], order=(1,1,0))
- arima_model_fit = arima_model.fit(disp=1)
- fig = arima_model_fit.plot_predict(1, 100)
- plt.close(fig)
- fig.savefig(cwd + '\\' + str(timestamps[0]).replace("-", "").replace(":","") + ".png") # temp path
- im = pyimgur.Imgur(CLIENT_ID)
- uploaded_image = im.upload_image(cwd + '\\' + str(timestamps[0]).replace("-", "").replace(":","") + ".png", title="Uploaded with PyImgur")
- link2 = uploaded_image.link
- #print(link2)
- # BIOFEEDBACK DATA
- characteristic_dist = characteristic_dist.astype('float32')
- um_preds[0] = um_preds[0].astype('float32')
- elementwise_diff = np.subtract(characteristic_dist, um_preds[0])
- links = {
- 0 : 'https://open.spotify.com/user/macaronlover8/playlist/7Bcu7I60Ir0jQ6IjXMZflc?si=DgITEw72RsKPncUOkAZyfw',
- 1 : 'https://open.spotify.com/user/macaronlover8/playlist/7Bcu7I60Ir0jQ6IjXMZflc?si=DgITEw72RsKPncUOkAZyfw',
- 2 : 'https://open.spotify.com/user/macaronlover8/playlist/7Bcu7I60Ir0jQ6IjXMZflc?si=DgITEw72RsKPncUOkAZyfw',
- 3 : 'https://open.spotify.com/user/macaronlover8/playlist/7Bcu7I60Ir0jQ6IjXMZflc?si=DgITEw72RsKPncUOkAZyfw'
- }
- biofeedback_data = links[np.argmax(elementwise_diff)] # placeholder
- #print(biofeedback_data)
- # DATABASE
- # -> rt metrics, long-term metrics/graphs, history graphs, music biofeedback data
- payload = [str(current_time), general_metric, preds, link2, link, biofeedback_data]
- sheet.insert_row(payload, row)
- sheet.update_cell(1, 7, int(sheet.cell(1, 7).value) + 1)
- counter = 0
- #cv2.imshow("Output", image)
- if cv2.waitKey(1) & 0xFF == ord('q'):
- break
- # When everything done, release the capture
- cap.release()
- cv2.destroyAllWindows()
- # dlib facial landmarks used for this: [20, 25] (eyebrows), [38, 39, 41, 40] (left eye), [43, 44, 47, 46] (right eye), [49, 55] (corners of mouth)
- #^you'll just get the vertical height of those
- # command to run this script in the nedc-2021-webcam folder is "python main.py --shape-predictor shape_predictor_68_face_landmarks.dat"
- # <class '_dlib_pybind11.shape_predictor'>
- # added simple survey with pysimplegui that outputs to a google spreadsheet: https://docs.google.com/spreadsheets/d/12HRJZJdJlNRn8BM2s3bJbABpVg9C8Q9D2ETvXjnl1cg/edit#gid=0
Advertisement
Add Comment
Please, Sign In to add comment