Русский
Русский
English
Статистика
Реклама

Mtcnn

Из песочницы Как не потерять ход времени работая за компьютером. Приложение по мониторингу работы и введению статистики

09.08.2020 16:21:03 | Автор: admin


Я работаю педагогом в детском технопарке Кванториум. В период самоизоляции мы так же, как и все перешли на дистанционное обучение. И в связи с тем, что дети стали еще больше времени проводить за компьютером, администрация решила сократить академический час и делать перерывы между работой (что бы сохранить зрение). Мы написали приложение, которое подсчитывает время, проведенное за компьютером, ведет статистику в excel (полезно для родителей) и выдает звуковое оповещение о том, что пора сделать перерыв.

Приложение будем полезно тем, кто теряется во времени работая за пк и хочет вогнать себя во временные рамки или следить за тем, какая часть жизни теряется в цифровом пространстве.

Ссылка на репозиторий

Под катом подробный разбор.

Для создания программы нужно решить следующие задачи:

  • детекция лица через web камеру (используем mtcnn);
  • подсчёт времени (библиотека time)
  • запись данных в excel документ (библиотека openpyxl);
  • звуковое оповещение;
  • автозагрузка скрипта при включении ПК.

Детекция лица с использованием web камеры


Мы рассматривали вариант отслеживать присутствие за компьютером по движению компьютерной мыши, возможно это проще и web камера останется свободной, но тогда мы не сможем учитывать просмотр сериалов или youtube роликов, к тому же использовать распознавание лиц гораздо интереснее.

Для детекции лица используем архитектуру mtcnn. Голова, расположенная под любым углом, в очках, при плохом освещении, даже если лицо не полностью попадает в кадр или прикрыто рукой, нейронная сеть работает исправно. Самостоятельно собирать ее не станем, подключим библиотеку с одноименным названием, которая решит нашу задачу используя несколько строчек кода.

Изначально использовали метод Виолы-Джонса. Точность намного хуже, чем у mtcnn, процессор загружает также.





Вывод результата вынесем в отдельную функцию, она нужна только для того, чтобы посмотреть, как работает распознавание.

import cv2import osfrom mtcnn.mtcnn import MTCNNdef 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 cv2import timeimport osfrom mtcnn.mtcnn import MTCNNcap = 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/
Подробнее..

Из песочницы Как не потерять ход времени, работая за компьютером. Приложение по мониторингу работы и ведению статистики

09.08.2020 20:18:26 | Автор: admin


Я работаю педагогом в детском технопарке Кванториум. В период самоизоляции мы так же, как и все перешли на дистанционное обучение. И в связи с тем, что дети стали еще больше времени проводить за компьютером, администрация решила сократить академический час и делать перерывы между работой (что бы сохранить зрение). Мы написали приложение, которое подсчитывает время, проведенное за компьютером, ведет статистику в excel (полезно для родителей) и выдает звуковое оповещение о том, что пора сделать перерыв.

Приложение будем полезно тем, кто теряется во времени работая за пк и хочет вогнать себя во временные рамки или следить за тем, какая часть жизни теряется в цифровом пространстве.

Ссылка на репозиторий

Под катом подробный разбор.

Для создания программы нужно решить следующие задачи:

  • детекция лица через web камеру (используем mtcnn);
  • подсчёт времени (библиотека time)
  • запись данных в excel документ (библиотека openpyxl);
  • звуковое оповещение;
  • автозагрузка скрипта при включении ПК.

Детекция лица с использованием web камеры


Мы рассматривали вариант отслеживать присутствие за компьютером по движению компьютерной мыши, возможно это проще и web камера останется свободной, но тогда мы не сможем учитывать просмотр сериалов или youtube роликов, к тому же использовать распознавание лиц гораздо интереснее.

Для детекции лица используем архитектуру mtcnn. Голова, расположенная под любым углом, в очках, при плохом освещении, даже если лицо не полностью попадает в кадр или прикрыто рукой, нейронная сеть работает исправно. Самостоятельно собирать ее не станем, подключим библиотеку с одноименным названием, которая решит нашу задачу используя несколько строчек кода.

Изначально использовали метод Виолы-Джонса. Точность намного хуже, чем у mtcnn, процессор загружает также.





Вывод результата вынесем в отдельную функцию, она нужна только для того, чтобы посмотреть, как работает распознавание.

import cv2import osfrom mtcnn.mtcnn import MTCNNdef 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 cv2import timeimport osfrom mtcnn.mtcnn import MTCNNcap = 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/
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru