Storing metrics + displaying table

This commit is contained in:
Ruben van de Ven 2018-05-05 23:27:52 +02:00
parent d37c50e394
commit 6d7c870be3
1 changed files with 47 additions and 10 deletions

View File

@ -15,13 +15,18 @@ import subprocess
import json
from threading import Thread
import termios, fcntl, os
import glob
import os
class Heatmap:
def __init__(self, metricsSize, logger, coordinates_filename):
def __init__(self, metricsSize, logger, coordinates_filename, tag):
self.coordinates_filename = coordinates_filename
self.logger = logger
self.metricsSize = metricsSize
self.metrics = np.zeros((metricsSize[1], metricsSize[0])) # (y, x)
self.tag = tag
self.metricSaveDiff = 60*5 # save metrics every 5 minutes
self.loadMetrics()
self.screenDrawCorners = np.array([
[0,0],
[metricsSize[0]-1,0],
@ -32,15 +37,17 @@ class Heatmap:
self.loadCoordinates()
self.windowRoot = Tk.Tk()
self.windowRoot.geometry('800x600+4000+0')
self.windowRoot.title('Heatmap')
self.windowRoot.attributes("-fullscreen", True)
imageWindowSize = tuple(metricsSize)
# self.windowRoot.geometry('%dx%d+%d+%d' % (imageWindowSize[0],imageWindowSize[1],0,0)) # we go full screen so not needed
self.canvas = Tk.Canvas(self.windowRoot,width=imageWindowSize[0],height=imageWindowSize[1],bd=0, highlightthickness=0, relief='ridge')
self.canvas.pack(fill="both", expand=True)
self.mapSize = [1200,400]
self.mapSize = [1600,600]
self.mapWindowRoot = Tk.Toplevel(master=self.windowRoot)
self.mapWindowRoot.geometry('%dx%d' % tuple(self.mapSize))
self.mapWindowRoot.geometry('%dx%d+0+800' % tuple(self.mapSize))
self.mapWindowRoot.title("Tracking Overview")
self.mapCanvas = Tk.Canvas(self.mapWindowRoot,width=self.mapSize[0],height=self.mapSize[1],bd=0, highlightthickness=0, relief='ridge')
self.mapCanvas.create_rectangle(20, 50, 22, 350, fill="black", width=0, tags="screenTop")
self.mapCanvas.create_rectangle(600, 50, 602, 300, fill="black", width=0, tags="screenSide")
@ -79,6 +86,25 @@ class Heatmap:
self.logger.info("Window size: %s", self.windowGeometry)
self.updateWindow()
def getOutputPrefix(self):
return "output/metrics-%s-%dx%d-" % (self.tag, self.metricsSize[0], self.metricsSize[1])
def loadMetrics(self):
list_of_files = glob.glob('%s*.p' % self.getOutputPrefix())
if len(list_of_files) < 1:
self.metrics = np.zeros((self.metricsSize[1], self.metricsSize[0])) # (y, x)
else:
latest_file = max(list_of_files, key=os.path.getctime)
with open(latest_file, "rb") as f:
self.metrics = pickle.load(f)
self.lastMetricSave = time.time()
def saveMetrics(self):
name = "{}{}.p".format(self.getOutputPrefix(), time.strftime("%Y-%m-%d %H:%M:%S"))
with open(name, "wb") as fp:
pickle.dump(self.metrics, fp)
self.lastMetricSave = time.time()
def onKeyPress(self, event=None, charachter=None):
if event is None and charachter is not None:
k = charachter
@ -124,6 +150,8 @@ class Heatmap:
def keepWindowUpdated(self):
while True:
self.updateWindow()
if time.time() - self.lastMetricSave > self.metricSaveDiff:
self.saveMetrics()
def updateFromJson(self, frame):
t1 = time.time()
@ -168,7 +196,7 @@ class Heatmap:
dz = face['head_pos'][2]/mmPerPixel # front/back
p1x = int(20 + dz)
p1y = int(virtualWidth / 2 + 50 + dx)
p1y = int(virtualWidth / 2 + 50 - dx)
p2x = int(600 + dz)
p2y = int(virtualHeight / 2 + 50 + dy)
@ -176,7 +204,7 @@ class Heatmap:
self.mapCanvas.create_oval(p2x-3, p2y-3, p2x+3, p2y+3, fill="red", width=0, tags="figure")
p3x = int(20)
p3y = int(float(face['target'][0]) / self.metricsSize[0] * virtualWidth + 50)
p3y = int(virtualWidth + 50 - (float(face['target'][0]) / self.metricsSize[0] * virtualWidth))
p4x = int(600)
p4y = int(float(face['target'][1]) / self.metricsSize[1] * virtualHeight + 50)
@ -185,7 +213,13 @@ class Heatmap:
self.logger.debug("DRAW FACE TO", face, (p1x,p1y), "AND", (p2x,p2y))
def updateTable(self):
# clear terminal
os.system('cls' if os.name == 'nt' else 'clear')
print("{} gazes".format(len(self.currentTargets)))
print("{:>5} {:>10} {:>10} {:>10} {:>5} {:>5}".format(" ", "x", "y", "z", "angle", "angle", ))
for face in self.currentTargets:
print(u"{:>5} {:>10} mm {:>10} mm {:>10} mm {:>5.2f}\xb0 {:>5.2f}\xb0".format(face['fid'], face['head_pos'][0], face['head_pos'][1], face['head_pos'][2], face['gaze_angle'][0], face['gaze_angle'][1]))
def updateWindow(self):
t1 = time.time()
@ -193,9 +227,11 @@ class Heatmap:
# convert to colormap, thanks to: https://stackoverflow.com/a/10967471
colormap = cm.plasma
colormap = cm.CMRmap
colormap = cm.nipy_spectral
normalisedMetrics = np.uint8(colormap(normalisedMetrics)*255)
image = Image.fromarray(normalisedMetrics)
self.updateMap()
self.updateTable()
# Too clunky for now:
# if len(self.currentTargets) > 0:
# c = ImageDraw.Draw(image)
@ -264,7 +300,7 @@ class Heatmap:
def main(openface_exec, coordinates_filename, device=0):
def main(openface_exec, coordinates_filename, tag, device=0):
logging.basicConfig( format='%(asctime)-15s %(name)s %(levelname)s: %(message)s' )
logger = logging.getLogger(__name__)
@ -285,7 +321,7 @@ def main(openface_exec, coordinates_filename, device=0):
metricsSize = [1920/2,1080/2]
metricsSize = [800,600]
heatmap = Heatmap(metricsSize, logger, coordinates_filename)
heatmap = Heatmap(metricsSize, logger, coordinates_filename, tag)
# heatmap.runCam(openface_exec, device)
thread = Thread(target=heatmap.runCam, args=(openface_exec, device))
thread.start()
@ -416,7 +452,8 @@ if __name__ == '__main__':
parser.add_argument('--of', default="../build/bin/FaceLandmarkVidMulti", help='The modified version of OpenFace\'s FaceLandmarkVidMulti')
parser.add_argument('--coordinates', default="coordinates.p", help='Use a specific coordinates.p file')
parser.add_argument('--device', type=int, default=0, help='Webcam device nr. to use')
parser.add_argument('--tag', type=str, default="default", help='Heatmap instance. Determines the name of saved (& thus loaded) files')
args = parser.parse_args()
main(openface_exec=args.of, coordinates_filename=args.coordinates, device=args.device)
main(openface_exec=args.of, coordinates_filename=args.coordinates, device=args.device, tag=args.tag)