我在Quantorium儿童技术园担任老师。在自我孤立的时期,我们和其他所有人一样,转向了远程学习。由于孩子们开始花更多的时间在计算机上,政府决定缩短学习时间,并在两次工作之间休息一下,以保持他们的视力。我们编写了一个应用程序,可以计算在计算机上花费的时间,将统计数据保存在excel中(对父母有用),并在需要休息时发出声音警报。
该应用程序对于那些在PC上浪费时间,想将自己赶入时间表或跟踪数字空间中失去的人生部分的人来说非常有用。
链接到存储库
在剪切下,进行详细分析。
要创建程序,您需要解决以下任务:
- web ( mtcnn);
- ( time)
- excel ( openpyxl);
- ;
- .
web
我们考虑了通过计算机鼠标的移动来跟踪计算机上存在状态的选项,也许这更容易,并且网络摄像头将保持免费状态,但是随后我们将无法考虑观看电视节目或youtube视频,此外,使用面部识别更为有趣。
对于人脸检测,我们使用mtcnn体系结构。即使脸部不完全处于框架中或被手遮盖,但头部处于任何角度,戴着眼镜,即使在光线不足的情况下,神经网络也能正常工作。我们不会自行构建它,而是连接同名的库,这将使用几行代码解决我们的问题。
最初,使用Viola-Jones方法。准确度比mtcnn差得多,处理器加载相同。
我们将结果的输出移到一个单独的函数中,只需要查看识别的工作原理即可。
import cv2
import os
from mtcnn.mtcnn import MTCNN
def show_face_frame():
if faces:
bounding_box = faces[0]['box']
keypoints = faces[0]['keypoints']
cv2.rectangle(img,
(bounding_box[0], bounding_box[1]),
(bounding_box[0] + bounding_box[2],
bounding_box[1] + bounding_box[3]),
(0, 0, 255),
2)
cv2.circle(img, (keypoints['left_eye']), 3, (0, 0, 255), 2)
cv2.circle(img, (keypoints['right_eye']), 2, (0, 0, 255), 2)
cv2.circle(img, (keypoints['nose']), 3, (0, 0, 255), 2)
cv2.circle(img, (keypoints['mouth_left']), 3, (0, 0, 255), 2)
cv2.circle(img, (keypoints['mouth_right']), 3, (0, 0, 255), 2)
cv2.imshow('frame', img)
cap = cv2.VideoCapture(0)
detector = MTCNN()
while cap.isOpened():
_, img = cap.read()
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
faces = detector.detect_faces(img)
show_face_frame()
cv2.waitKey(300)
cap.release()
cv2.destroyAllWindows()
cv2.waitKey(300)的 延迟较大,以免加载处理器。每秒处理3-4帧,平均将i3-8145U加载15%。
计数时间
在以下情况下,程序不应写入日志:
- 在计算机上坐了5秒钟,以做byrik的事情;
- 出去倒咖啡或伸腿。
为了解决这些问题,该程序使用两个秒表time_here(计算面部在帧中的时间)和time_not_here(没有面部)。进行日志输入时,两个秒表都会重置。此外,每次在画面中出现脸部时,都会重置time_not_here。min_time_here
变量指示在计算机上花费的最短时间,之后值得将其写入日志。在使人们分心计算机的时间长于min_time_not_here中指定的时间之后,将进行记录。
在下面的代码中,如果您在计算机上花费了至少5分钟,就会进行录制。该程序不会考虑我分心不到2分钟的事实。
import cv2
import time
import os
from mtcnn.mtcnn import MTCNN
cap = cv2.VideoCapture(0)
path = os.path.abspath(__file__)[:-11] #
here, not_here = 0, 0 #
time_here, time_not_here = 0, 0 #
switch = True #
min_time_here = 300 # , ( )
min_time_not_here = 120 # ( )
detector = MTCNN()
try:
while cap.isOpened():
_, img = cap.read()
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
faces = detector.detect_faces(img)
show_face_frame()
audio_message(path, here)
if faces and switch:
not_here = 0
switch = False
if here == 0:
here = time.time()
print(' ' + time.strftime("%H:%M:%S", time.localtime(here)))
elif not faces and not switch:
not_here = time.time()
switch = True
if not_here != 0:
time_not_here = time.time() - not_here
if here != 0 and not switch:
time_here = time.time() - here
if time_here > min_time_here and time_not_here > min_time_not_here: # min_time_here
write_excel(path, here)
print(' ' + time.strftime('%H:%M:%S', time.gmtime(time.time() - here)))
time_here, time_not_here = 0, 0
here, not_here = 0, 0
elif time_not_here > min_time_not_here and time_here < min_time_here: # min_time_here,
print(' ')
time_here, time_not_here = 0, 0
here, not_here = 0, 0
cv2.waitKey(300)
except KeyboardInterrupt:
if time_here > min_time_here: # min_time_here
write_excel(path, here)
cap.release()
cv2.destroyAllWindows()
如果用户要关闭计算机,则首先需要中断程序(ctrl + c),然后将记录当前工作的时间。为此使用异常处理程序。
将数据写入Excel文档
对于使用excel,出色的openpyxl库将提供帮助,该库可以同时读取和写入数据。
程序每天都会使用当前日期创建一个新表。
在一张纸上,记录每天的信息,以及哪一天在计算机上花费了多少时间。write_excel
函数可打开文档,写入数据并立即将其关闭。 如果用户已经打开了文档,则无法通过openpyxl对其进行修改。在这种情况下添加了一个例外。
def write_excel(path_excel, time_start):
wb = openpyxl.load_workbook(path_excel + r'\dnevnik.xlsx')
today = time.strftime("%d.%m.%Y", time.localtime(time.time()))
if today not in wb.sheetnames: # ,
wb.create_sheet(title=today)
sheet = wb[today]
sheet.column_dimensions['A'].width = 20
sheet.column_dimensions['B'].width = 20
sheet.column_dimensions['C'].width = 20
sheet.column_dimensions['D'].width = 31
sheet['A1'] = ' '
sheet['B1'] = ' '
sheet['C1'] = ' '
sheet['D1'] = ' :'
sheet['D2'] = ' :'
sheet = wb[today]
row = 2
all_time = 0
else: #
sheet = wb[today]
row = sheet['E1'].value # excel
all_time = sheet['E2'].value #
all_time = all_time.split(':')
all_time = int(all_time[0]) * 3600 + int(all_time[1]) * 60 + int(all_time[2]) #
row = row + 2 #
sheet['A' + str(row)] = time.strftime("%H:%M:%S", time.localtime(time_start)) #
sheet['C' + str(row)] = time.strftime("%H:%M:%S", time.localtime(time.time())) # -
seconds = time.time() - time_start #
sheet['B' + str(row)] = time.strftime('%H:%M:%S', time.gmtime(seconds))
sheet['E1'] = row - 1 #
all_time = all_time + seconds
all_time = time.strftime('%H:%M:%S', time.gmtime(all_time))
sheet['E2'] = all_time
#
sheet_0 = wb.worksheets[0]
sheet_0['A' + str(len(wb.sheetnames))] = today
sheet_0['B' + str(len(wb.sheetnames))] = all_time
while True: #
try:
wb.save(path_excel + r'\dnevnik.xlsx')
except PermissionError:
input(' excel enter')
else:
break
声音警报
为了进行更改,我们使用语音合成器生成了8个音频文件,这些文件在工作一个小时后便会随机运行。在您休息之前,不会有重复的音频警报。
def audio_message(path, here):
if here == 0:
pass
elif time.strftime('%H:%M:%S', time.gmtime(time.time()-here)) == "01:00:00":
wav = random.choice(os.listdir(path + r'\audio'))
winsound.PlaySound(path + r'\audio\\' + wav, winsound.SND_FILENAME)
打开PC时的启动脚本
为了使程序与Windows一起加载,您可以创建一个运行python脚本的批处理文件。批处理文件应位于以下目录中:
C:\ Users \%用户名%\ AppData \ Roaming \ Microsoft \ Windows \“开始”菜单\“程序” \“启动”
由于批处理文件和源文件存储在不同的目录中,因此无法使用os.getcwd( ),因为它将返回批处理文件的路径。我们正在使用os.path.abspath(__文件__)[:-11]
UPD: ak545建议一个更好的选择os.path.dirname(os.path.abspath(__ file__))
在未来
我希望程序能随心所欲,而不是坐在计算机旁的每个人都可以。为此,将使用能够进行面部识别的FaceNet。
还计划开发一个漂亮的小部件,而不是一个丑陋的黑色控制台,这样,当计算机关闭时,录制会自动完成,而不会使用中断。
感谢您的关注。如有疑问,请在评论中或在https://www.linkedin.com/in/evg-voronov/