MVP#1 Gathering viewing statistics for Donald Schenkel https://rubenvandeven.com/mvp1
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mvp1/scan_faces.py

152 lines
4.2 KiB

#!/usr/bin/python
import io
import picamera
import cv2
import numpy as np
import datetime
import time
import os
from si_prefix import si_format
import Adafruit_CharLCD as LCD
import urllib2
import socket
# Set FPS (though RPi is probably to slow to meet it ;-)
FPS = 1.0
frameTimeDelta = datetime.timedelta(seconds=1.0/FPS)
dimTimeDelta = datetime.timedelta(seconds=10)
# Init LCD
lcd_rs = 27
lcd_en = 22
lcd_d4 = 25
lcd_d5 = 24
lcd_d6 = 23
lcd_d7 = 18
lcd_backlight = 4
lcd_columns = 16
lcd_rows = 2
lcd = LCD.Adafruit_CharLCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7,
lcd_columns, lcd_rows, lcd_backlight)
# ip if config is needed over ssh. Username pi, Password: artwork1
try:
ip = (([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")] or [[(s.connect(("8.8.8.8", 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) + ["no IP found"])[0]
except Exception:
ip = "No network"
lcd.clear()
lcd.message("Init scanner.\n{}".format(ip) )
time.sleep(6) # give some time to read the ip.
# Init camera
camera = picamera.PiCamera()
#~ camera.resolution = (1280, 720)
camera.resolution = (1920, 1080)
lcd.clear()
lcd.message("Init scanner..")
# Init classifier, various options:
#~ /usr/share/opencv/haarcascades/haarcascade_frontalface_default.xml (~22sec)
#~ /usr/share/opencv/haarcascades/haarcascade_frontalface_alt.xml (>25sec)
#~ /usr/share/opencv/haarcascades/haarcascade_frontalface_alt2.xml (~21sec)
#~ /usr/share/opencv/haarcascades/haarcascade_frontalface_alt_tree.xml (~14sec, seems to miss many faces)
classifier = cv2.CascadeClassifier('/usr/share/opencv/haarcascades/haarcascade_frontalface_alt2.xml')
lcd.clear()
lcd.message("Init scanner...")
prevFaceCount = 0
totalUse = 0 #in face-seconds
logfile = "/home/pi/scan_faces/scan_face.log"
def tail(filepath):
"""
Thanks: https://stackoverflow.com/a/41491521
"""
with open(filepath, "rb") as f:
first = f.readline() # Read the first line.
f.seek(-2, 2) # Jump to the second last byte.
while f.read(1) != b"\n": # Until EOL is found...
try:
f.seek(-2, 1) # ...jump back the read byte plus one more.
except IOError:
f.seek(-1, 1)
if f.tell() == 0:
break
last = f.readline() # Read last line.
return last
# make sure log file exists
if not os.path.exists(logfile):
with open(logfile,"w") as f:
f.write("{},{},{}".format(time.time(), 0,0))
# get last line of log file and update 'total use' using that.
last = tail(logfile)
bits = last.split(",")
totalUse = float(bits[2])
print "Total use:", totalUse
log = open(logfile, "a")
lastFaceTime = datetime.datetime.utcnow()
while True:
try:
print(time.time(),"GO")
start = datetime.datetime.utcnow()
stream = io.BytesIO()
camera.capture(stream, format='jpeg')
print(time.time(),"captured")
buff = np.fromstring(stream.getvalue(), dtype=np.uint8)
image = cv2.imdecode(buff,1)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
print(time.time(),"grayed")
faces = classifier.detectMultiScale(gray, 1.2, 5, minSize=(30,20))
print(time.time(),"Found {} faces".format(len(faces)))
end = datetime.datetime.utcnow()
# take the frame as being representative of whole frame
scanDuration = (end - start).total_seconds()
totalUse += len(faces) * scanDuration
lcd.clear()
#~ lcd.message("viewers {:>8}\nview-min. {:>7.2f}".format(len(faces), totalUse/60))
lcd.message("{:>7} viewers \n{:>7}view-sec".format(len(faces), si_format(totalUse,precision=1)))
log.write("{},{},{}\n".format(time.time(), len(faces), int(totalUse)))
log.flush()
os.fsync(log.fileno())
if len(faces) < 1 and end - lastFaceTime > dimTimeDelta:
lcd.set_backlight(0)
else:
lcd.set_backlight(1)
if len(faces) > 0:
lastFaceTime = end
content = urllib2.urlopen("https://artstats.rubenvandeven.com/artwork1/views.php?time=%d&count=%d&total=%d&duration=%f" % (int(time.time()), len(faces), int(totalUse), scanDuration) ).read()
#~ if end - start < frameTimeDelta:
#~ waitTime = frameTimeDelta - (end-start)
#~ print("wait {}".waitTime.total_seconds())
#~ time.sleep(waitTime.total_seconds())
except Exception as e:
print e