[Python, Программирование] Как не потерять ход времени работая за компьютером. Приложение по мониторингу работы и введению статистики
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Я работаю педагогом в детском технопарке «Кванториум». В период самоизоляции мы так же, как и все перешли на дистанционное обучение. И в связи с тем, что дети стали еще больше времени проводить за компьютером, администрация решила сократить академический час и делать перерывы между работой (что бы сохранить зрение). Мы написали приложение, которое подсчитывает время, проведенное за компьютером, ведет статистику в excel (полезно для родителей) и выдает звуковое оповещение о том, что пора сделать перерыв.
Приложение будем полезно тем, кто теряется во времени работая за пк и хочет вогнать себя во временные рамки или следить за тем, какая часть жизни теряется в цифровом пространстве.
Ссылка на репозиторий
Под катом подробный разбор.
Для создания программы нужно решить следующие задачи:
- детекция лица через web камеру (используем mtcnn);
- подсчёт времени (библиотека time)
- запись данных в excel документ (библиотека openpyxl);
- звуковое оповещение;
- автозагрузка скрипта при включении ПК.
Детекция лица с использованием web камеры
Мы рассматривали вариант отслеживать присутствие за компьютером по движению компьютерной мыши, возможно это проще и web камера останется свободной, но тогда мы не сможем учитывать просмотр сериалов или youtube роликов, к тому же использовать распознавание лиц гораздо интереснее.
Для детекции лица используем архитектуру mtcnn. Голова, расположенная под любым углом, в очках, при плохом освещении, даже если лицо не полностью попадает в кадр или прикрыто рукой, нейронная сеть работает исправно. Самостоятельно собирать ее не станем, подключим библиотеку с одноименным названием, которая решит нашу задачу используя несколько строчек кода.
Изначально использовали метод Виолы-Джонса. Точность намного хуже, чем у 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 сек что-то по бырику сделать;
- вышел налить кофе или размять ноги.
Для решения этих задач в программе используется два секундомера 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, которая одновременно считывать и записывать данные.
Каждый день программа создает новый лист с текущей датой.
На 1 листе записывается посуточная информация, в какой день сколько времени провели за компьютером.
Функция 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)
Автозагрузка скрипта при включении ПК
Для того, чтобы программа загружалась вместе с виндой можно создать батник, который будет запускать python скрипт. Батник должен находиться в директории:
C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
C учетом того, что батник и исходный файл хранятся в разных директориях, нельзя использовать функцию os.getcwd() так как она вернет путь до батника. Мы используем os.path.abspath(__file__)[:-11]
В будущем
Хотелось бы, что бы программа следила за моим лицом, а не за всеми, кто садиться за компьютер. Для этого будет использоваться FaceNet которая способна распознавать лица.
Также в планах разработать красивый виджет вместо некрасивой черной консоли, и что бы при выключении компьютера запись производилась автоматически, а не с помощью прерывания.
Спасибо за внимание. Если есть вопросы пишите в комментарии или на https://www.linkedin.com/in/evg-voronov/
===========
Источник:
habr.com
===========
Похожие новости:
- [Python, Проектирование и рефакторинг] Мониторинг демон на Asyncio + Dependency Injector — руководство по применению dependency injection
- [Программирование микроконтроллеров] Подключение OLED дисплея ssd1306 к STM32 (SPI+DMA)
- [Python, Django] Шесть Python-пакетов, которые рекомендуется использовать в каждом веб-приложении на Django (перевод)
- [API, Python] Реализация offline режима для Yandex.Music
- [Программирование, Системное программирование, Rust] В поиске вопросов, или как создать новый отладчик
- Facebook представил Pysa, статический анализатор для языка Python
- [Космонавтика, DIY или Сделай сам] Целимся и общаемся со спутниками: Часть первая — целимся программно
- [Программирование, Компиляторы, История IT] Фрэнсис Аллен — первая женщина, получившая премию Тьюринга
- [Программирование, Разработка мобильных приложений, Проектирование и рефакторинг, Управление разработкой] Какие навыки можно прокачать на проекте c большой кодовой базой
- [Программирование, Java] Интеграционное тестирование в SpringBoot с TestContainers-стартером (перевод)
Теги для поиска: #_python, #_programmirovanie (Программирование), #_opencv, #_openpyxl, #_python, #_mtcnn, #_python, #_programmirovanie (
Программирование
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 23-Ноя 00:24
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Я работаю педагогом в детском технопарке «Кванториум». В период самоизоляции мы так же, как и все перешли на дистанционное обучение. И в связи с тем, что дети стали еще больше времени проводить за компьютером, администрация решила сократить академический час и делать перерывы между работой (что бы сохранить зрение). Мы написали приложение, которое подсчитывает время, проведенное за компьютером, ведет статистику в excel (полезно для родителей) и выдает звуковое оповещение о том, что пора сделать перерыв. Приложение будем полезно тем, кто теряется во времени работая за пк и хочет вогнать себя во временные рамки или следить за тем, какая часть жизни теряется в цифровом пространстве. Ссылка на репозиторий Под катом подробный разбор. Для создания программы нужно решить следующие задачи:
Детекция лица с использованием web камеры Мы рассматривали вариант отслеживать присутствие за компьютером по движению компьютерной мыши, возможно это проще и web камера останется свободной, но тогда мы не сможем учитывать просмотр сериалов или youtube роликов, к тому же использовать распознавание лиц гораздо интереснее. Для детекции лица используем архитектуру mtcnn. Голова, расположенная под любым углом, в очках, при плохом освещении, даже если лицо не полностью попадает в кадр или прикрыто рукой, нейронная сеть работает исправно. Самостоятельно собирать ее не станем, подключим библиотеку с одноименным названием, которая решит нашу задачу используя несколько строчек кода. Изначально использовали метод Виолы-Джонса. Точность намного хуже, чем у 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%. Подсчет времени Программа не должна делать записи в журнал в следующих случаях:
Для решения этих задач в программе используется два секундомера 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, которая одновременно считывать и записывать данные. Каждый день программа создает новый лист с текущей датой. На 1 листе записывается посуточная информация, в какой день сколько времени провели за компьютером. Функция 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) Автозагрузка скрипта при включении ПК Для того, чтобы программа загружалась вместе с виндой можно создать батник, который будет запускать python скрипт. Батник должен находиться в директории: C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup C учетом того, что батник и исходный файл хранятся в разных директориях, нельзя использовать функцию os.getcwd() так как она вернет путь до батника. Мы используем os.path.abspath(__file__)[:-11] В будущем Хотелось бы, что бы программа следила за моим лицом, а не за всеми, кто садиться за компьютер. Для этого будет использоваться FaceNet которая способна распознавать лица. Также в планах разработать красивый виджет вместо некрасивой черной консоли, и что бы при выключении компьютера запись производилась автоматически, а не с помощью прерывания. Спасибо за внимание. Если есть вопросы пишите в комментарии или на https://www.linkedin.com/in/evg-voronov/ =========== Источник: habr.com =========== Похожие новости:
Программирование ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 23-Ноя 00:24
Часовой пояс: UTC + 5