IT-инфраструктура для бизнеса и творчества
Разработка
Selectel

Сделай сам: трекер, который напомнит, что пора отвлечься от дел и передохнуть

Автоматизируем напоминания о перерывах на работе.

В серии DIY-статей «Пространство для изобретений» мы пробуем в домашних условиях разработать необычные гаджеты и оставляем все необходимые инструкции, чтобы любой желающий мог повторить наш опыт. Серию статей поддерживает Selectel — провайдер ИТ-инфраструктуры, которая помогает в решении рабочих задач и разработке личных проектов. Посмотреть, что интересного есть у провайдера, и выбрать для себя подходящие решения можно на сайте.

В этом материале Станислав Грицинов, разработчик электронных устройств, собирает трекер, который наблюдает за пользователем во время работы и присылает уведомление в Telegram, если тот засиживается без перерыва больше трёх часов. А к сообщению прикрепляет видеотренировку — чтобы перерыв прошёл с пользой.

Список компонентов

По задумке трекер — это устройство с камерой, которая снимает сидящего за монитором человека, фиксируясь на его лице. Если лицо не пропадает из кадра больше трёх часов подряд, то трекер сигнализирует сообщением — в нашем случае в Telegram.

Устройство мы будем собирать на основе микрокомпьютера Raspberry Pi 4 (1–8 Gb RAM) с картой microSD. Карту стоит подобрать ресурсоёмкую (рассчитанную на большое количество циклов перезаписи), с объёмом больше 16 Гб. Помимо этого нам потребуются:

  • радиатор;
  • вентилятор [5V];
  • блок питания [5V, 2A];
  • кабель micro HDMI;
  • монитор;
  • USB-клавиатура;
  • USB-мышь;
  • USB-веб-камера.

Установка пакетов: Python 3, OpenCV, telegram-send, facial_recognition

После установки системы на SD-карту, запустив Terminal, вводим по очереди команды для обновления системы перед установкой пакетов:

sudo apt update sudo apt upgrade

Затем устанавливаем Python 3:

sudo apt install python3 sudo apt install python3-pip

И проверяем установленные версии:

python3 --version pip3 --version

Переходим к установке OpenCV: это свободно распространяемая библиотека компьютерного зрения и машинного обучения, реализованная на С/С++ и предназначенная для обработки изображений в реальном времени в различных операционных системах.

Устанавливаем OpenCV, face_recognition и imutils (некоторые команды исполняются несколько минут):

sudo apt install cmake build-essential pkg-config git sudo apt install libjpeg-dev libtiff-dev libjasper-dev libpng-dev libwebp-dev libopenexr-dev sudo apt install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev libdc1394-22-dev libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev sudo apt install libgtk-3-dev libqtgui4 libqtwebkit4 libqt4-test python3-pyqt5 sudo apt install libatlas-base-dev liblapacke-dev gfortran sudo apt install libhdf5-dev libhdf5-103 sudo apt install python3-dev python3-numpy

Увеличим размер swap для успешной компиляции OpenCV (если swap небольшой — возможны зависания). Правильный расчёт размера файла подкачки выглядит следующим образом: 2 × RAM. В нашем примере «малинка» имеет 1 Гб оперативной памяти, поэтому размер файла подкачки будет составлять 2 Гб, то есть 2048 Мб. Внесите это значение в конфигурационный файл.

Откройте файл подкачки:

sudo nano /etc/dphys-swapfile

Измените размер swap CONF_SWAPSIZE=100 на CONF_SWAPSIZE=2048.

Затем выйдите по комбинации клавиш Ctrl + X и в ответ на запрос программы нажмите Y + Enter (сохранить файл).

Перезапускаем демона, управляющего файлом подкачки:

sudo systemctl restart dphys-swapfile

Я буду использовать версию OpenCV: 4.5.3. Скачиваем и распаковываем архивы с исходниками:

wget -O opencv.zip https://github.com/opencv/opencv/archive/refs/tags/4.5.3.zip unzip opencv.zip wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/refs/tags/4.5.3.zip unzip opencv_contrib.zip mkdir ~/opencv-4.5.3/build cd ~/opencv-4.5.3/build

Настройка сборки, оптимизированной для Raspberry Pi:

cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib-4.5.3/modules -D ENABLE_NEON=ON -D ENABLE_VFPV3=ON -D BUILD_TESTS=OFF -D INSTALL_PYTHON_EXAMPLES=OFF -D OPENCV_ENABLE_NONFREE=ON -D CMAKE_SHARED_LINKER_FLAGS=-latomic -D BUILD_EXAMPLES=OFF ..

Сборка и установка:

make -j$(nproc) sudo make install sudo ldconfig

Команда make -j$(nproc) при использовании всех ядер процессора будет выполняться около часа. После успешной установки OpenCV вернём размер swap к исходному (для сохранения ресурса SD-карты):

sudo nano /etc/dphys-swapfile

Меняем размер swap CONF_SWAPSIZE=2048 на CONF_SWAPSIZE=100.

Снова применяем комбинацию клавиш «Выход» — Ctrl + X, а затем сохраняем файл — Y + Enter. Перезапускаем демона:

sudo systemctl restart dphys-swapfile pip3 install face_recognition pip3 install imutils

Устанавливаем Telegram-send:

sudo pip3 install telegram-send

А затем — пакет для распознавания лиц facial_recognition:

cd && git clone https://github.com/carolinedunn/facial_recognition

Настройка облачного хранилища Selectel

Я решил не ограничиваться только уведомлениями «Вы работаете без перерыва три часа». Чтобы трекер стал полезнее, я добавил в него видео с тренировкой для глаз, массажем шеи, короткой медитацией и зарядкой — какое именно, бот будет выбирать случайным образом. Видеозаписи нашёл в сети, но для корпоративного пользования подготовил бы их самостоятельно — чтобы все ролики были с хорошей картинкой и звуком, без лишних предисловий.

Чтобы не слишком забивать роликами по 5–10 минут локальное хранилище, выношу их в облако Selectel. Регистрируюсь в панели управления, оплачиваю объектное хранилище, нахожу «Облачное хранилище» в панели управления и перехожу в пункт меню «Пользователи». Создаю нового пользователя и контейнер в хранилище Selectel. Название хранилища стоит вводить без пробелов — иначе в ссылках, которые бот отправит в Telegram, нужно будет заменять пробелы на URL-код %20.

Тип хранилища — «Публичный», класс — «Стандартное хранение». В настройках контейнера выбираем «Управление доступом» и для указанного пользователя ставим «Чтение и запись».

Ниже список видео, которые присылает мой бот (их можно скачать и использовать для вашей разработки):

Загружаем файлы в контейнер, по ссылке — описание API для работы с хранилищем Selectel.

Настройка telegram-бота

Создаём бота через BotFather — находим его через поиск и начинаем диалог с помощью /newbot. Выбираем название и пользовательское имя бота, в ответ BotFather отправит вам токен.

Вводим команду в Terminal:

telegram-send --configure

Затем вводим токен из сообщения BotFather (Use this token to access the HTTP API):

Получаем пароль — его нужно отправить боту после сообщения /start. Теперь он готов принимать сообщения-напоминания со ссылками видео.

Настройка распознавания лиц facial_recognition

Чтобы устройство отличало пользователя от кота или фикуса на окне, обучим его распознавать лицо:

  • Откройте в File Manager папку /home/pi/facial_recognition/dataset/.
  • Создайте папку с именем пользователя, время работы которого планируете отслеживать. В проекте пользователя я назвал «USER».
  • Скопируйте в папку готовый набор фото в разных ракурсах с хорошим освещением (10 снимков вполне хватит).

Вместо готового набора фото можно создать набор с помощью веб-камеры. Для этого можно использовать, например, Text Editor: меняем в строке 3 файла headshots.py: 'Caroline' — на нужное имя и запускаем файл headshots.py из папки /home/pi/facial_recognition в Terminal:

cd facial_recognition python3 headshots.py

Запускаем файл train_model.py для обучения:

python3 train_model.py

Обработанные данные сохраняются в файле encodings.pickle.

Для проверки распознавания можно запустить файл facial_req.py:

python3 facial_req.py

Нажмите Ctrl + C для остановки работы тестовой программы распознавания.

Запуск python-программы

Распаковываем архив Work_Time_Python в новую папку и открываем Thonny Python IDE. Переходим в меню системы Raspberry, затем в меню Thonny Python IDE. Открываем файл cURL_request_def.py. Вводим в строках:

Строка 8: номер вашего аккаунта.

Строка 9: имя пользователя с доступом к контейнеру видеофайлов.

Строка 10: пароль аккаунта Selectel.

Строка 11: название контейнера с файлами.

Сохраняем файл cURL_request_def.py (его можно закрыть).

Открываем файл Work_time_tracker.py. Запускаем его кнопкой RUN (круглая зелёная).

Появляется окно Facial Recognition, отображающее кадры с веб-камеры и прямоугольник распознавания лица с заданным именем (USER или другое выбранное вами имя).

Чтобы остановить работу программы нужно нажать красную кнопку STOP.

Во время работы программы Work_time_tracker.py (распознан продюсер vc.ru)

С появлением пользователя в кадре и его распознавания начинается отсчёт: если человек не покидает рамок камеры три часа, то получит напоминание об этом в Telegram, а ещё — случайно выбранное видео из хранилища Selectel.

Время непрерывной работы задаётся в строке 15 файла Work_time_tracker.py: detection_interval (10 800 с. = 3 часа). Если пользователь продолжает работать, второе сообщение придёт через ещё один интервал (3 часа) detection_interval, и так далее.

При этом даже если в течение интервала detection_interval пользователь отвлекался от работы на незначительное время (например, отворачивался и камера его не распознавала), отсчёт не прерывается. Для этого в строке 16 задано absent_interval, 30 секунд. Если камера теряет его больше чем на полминуты — отсчёт прерывается и возобновляется, когда пользователь найден. Количество секунд можно настроить под себя так, чтобы трекер не засчитывал за отдых, например, выходы в туалет — в примере мы считаем их как перерыв. Интервал детектирования пользователя в кадре задаётся в строке 17: detection_interval (1 секунда).

Чтобы распознавание пользователя в кадре было корректным, в комнате должно быть достаточно рассеянного света (любителям ночной работы придётся немного поиграть с освещением и программой).

{ "author_name": "Selectel", "author_type": "editor", "tags": ["selecteldiy"], "comments": 14, "likes": 14, "favorites": 22, "is_advertisement": false, "subsite_label": "dev", "id": 288561, "is_wide": true, "is_ugc": false, "date": "Wed, 15 Sep 2021 10:48:53 +0300", "is_special": false }
(function () { let cdnUrl = `https://specialsf378ef5-a.akamaihd.net/SelectelBranding/images/` let previousArticleNumber = null let currentArticleNumber = 0 let platform = 'Desktop' let articles = [ // { // name: 'camera', // url: `${cdnUrl}CameraCat`, // text: 'умную камеру для\u00A0наблюдения за\u00A0котиками', // link: '1', // }, { name: 'chill', url: `${cdnUrl}ChillCat`, text: 'трекер, который подскажет, когда пора отдохнуть', link: 'https://vc.ru/promo/288561-eye-tracker', }, // { // name: 'cloud', // url: `${cdnUrl}CloudCat`, // text: 'котика: даёшь ему «пять», а\u00A0он делает бэкап в облако', // link: '3', // } ] let buttonCycle = document.querySelector('.button--cycle') let textField = document.querySelector('.selectel-footer-subtitle') let imageAgent = document.querySelector('.image--agent') let banner = document.querySelector('.selectel-footer') buttonCycle.addEventListener('click', cycleClick) let media = window.matchMedia("(max-width: 570px)") media.addEventListener('change', matchMedia) function matchMedia() { if (media.matches) { platform = 'Mobile' } else { platform = 'Desktop' } update() } matchMedia() function cycleClick(event) { if (event) { event.preventDefault() event.stopPropagation() } window.open('https://vc.ru/tag/selectelDIY', '_blank') //cycle(event) } function cycle(event) { // incrementArticleNumber() textField.innerHTML = generatedText() imageAgent.src = articles[currentArticleNumber].url + platform + '.svg?5' imageAgent.setAttribute("class", "") imageAgent.classList.add('image--agent', articles[currentArticleNumber].name) banner.href = articles[currentArticleNumber].link } function update() { banner.href = articles[currentArticleNumber].link imageAgent.src = articles[currentArticleNumber].url + platform + '.svg?5' textField.innerHTML = generatedText() } function incrementArticleNumber() { previousArticleNumber = currentArticleNumber if (currentArticleNumber >= articles.length - 1) { currentArticleNumber = 0 } else { currentArticleNumber++ } } function generatedText() { let defaultText if (platform === 'Desktop') { defaultText = `Мы тут собрали %text%. Хотите почитать?` } else { defaultText = `Мы тут собрали %text%.` } return defaultText.replace('%text%', articles[currentArticleNumber].text) } function getRandom(min, max) { min = Math.ceil(min) max = Math.floor(max) return Math.floor(Math.random() * (max - min + 1)) + min } (function create() { currentArticleNumber = getRandom(0, articles.length - 1) cycle() let page = document.querySelector('.page--entry') if (page) { function insertAfter() { let parents = page.querySelectorAll('[data-id="7"]') let referenceNode = parents[0] referenceNode.parentNode.insertBefore(banner, referenceNode.nextSibling); loaded() } setTimeout(() => insertAfter(), 0) } }()) function loaded() { banner.classList.add('loaded') } loadImages([ `${cdnUrl}CameraCatDesktop.svg`, `${cdnUrl}ChillCatDesktop.svg`, `${cdnUrl}CloudCatDesktop.svg`, `${cdnUrl}CameraCatMobile.svg`, `${cdnUrl}ChillCatMobile.svg`, `${cdnUrl}CloudCatMobile.svg`, ]) function loadImages(urls) { return Promise.all(urls.map(function (url) { return new Promise(function (resolve) { var img = document.createElement('img'); img.onload = resolve; img.onerror = resolve; img.src = url; }); })); } }())
0
14 комментариев
Популярные
По порядку
Написать комментарий...

Это точно vc, а  не хабр?

а вообще есть обратная фигня которая бы помогала заняться делами и отвлечься от ерунды?

7

Хабр все, каждый день там пробив дна и неадекватная аудитория из школьников и псевдоинтеллектуальных задротов.

4

увы, но на счет хабра и неадекватной аудитории — вы правы.

0

Если лицо не пропадает из кадра более 3 часов, то подаем ток на баттплаг. ред.

2

А купить дешёвый китайский браслет и сделать под него прошивку не вариант?

0

это слишком скучно, речь-то про diy.

1

Вы так надуетесь писать прошивку что посинеете от китайской документации 🥲

1

Вот это мой diy дозиметр, даже чип от TI, но это очень плохой ble чип cc2541  ред.

2

Почему на сбм 20 а не бета-1, или бета-2?

0

Так они огромные)

0

За то с них толку больше.
СБМ20 и медленный и не чувствительный по сравнению с бетами. Хотя там вроде сборки на сбм20 когда их 4или 8шт разом неплохие. 

0

Неее, мы же говорим, чтоб с удовольствием что-то собрать, а не задолбаться от такой дичи)))

0

Кому-то однозначно полезно будет, но лично мне удобнее интуитивно управлять временем работы и отдыха, чем по напоминалкам  

0

Вы бы ещё завод построили для такой задачи. 

0
Читать все 14 комментариев
Как мы проводили командную ретроспективу в Minecraft

Рассказываем историю, на что стоит обратить внимание при проведении командного мероприятия в игре Minecraft, какие грабли могут быть, как организовать онлайн- и офлайн-участие.

Компонент в Figma с нулевыми размерами. Приёмы и фишки

Как сделать компонент с размерами 0 на 0 пикселей, и где это можно применить.

Как я дистанционно оформляла сим-карту в МТС

Всем привет! Я уже больше 10 лет являюсь абонентом этого оператора и не хочу его как-то очернять, потому что, в целом, меня все устраивает. Но квест с оформлением симки через личный кабинет и дистанционным подписанием договора стоит отдельного поста. Особенно, с учетом того что он закончился безрезультатно, с потерей денег и времени.
Мне…

Как традиционному малому бизнесу превратиться в стартап: план действий

Сейчас в России предприниматели переходят из традиционного малого бизнеса в стартапы очень редко — меньше чем в 0,02% случаев. Это не больше 1 000 стартапов из около 6 млн предприятий малого бизнеса. Поговорим о том, что мешает предпринимателям и как действовать, если есть желание создать стартап.

Готовы выбрать победителя премии «Экспортер года eBay — 2021»?
Как я украл у Яндекса идею чеклист бота

на самом деле нет, но ведь должна же была кому-то из сотрудников Яндекса когда-то прийти такая идея :D

За 100 лет до МММ: как рязанский банкир построил финансовую пирамиду в 19 веке и обманул вкладчиков на 12 млн рублей Статьи редакции

Когда в скопинском банке оказалось недостаточно денег, чтобы выплачивать проценты по вкладам, директор Иван Рыков «нарисовал» баланс и привлёк новых вкладчиков. На их деньги он отдавал проценты — так и зародилась первая в России финансовая пирамида, которая просуществовала 15 лет.

Здание Скопинского банка Архив Скопинского исторического общества
Переход бизнеса на Apple: нет причин отказывать себе в удовольствии

Работать на устройствах Apple – это просто, удобно, приятно, современно. А еще, как продолжают считать некоторые – дорого и не для всех. Однако это не так: хотя «яблочные» устройства и работают в каждой международной корпорации из Fortune 500, сегодня они доступны практически любой SMB-компании, стартапу, и даже общеобразовательной школе. Причина кроется как в самих технологиях Apple, так и в выстроенных вокруг них сервисных программах.

Сервис аренды электросамокатов Whoosh добавил электровелосипеды — пока в тестовом режиме Статьи редакции

От 6 рублей за минуту.

Нужны ли в России сити-фермы

И появятся ли грядки на крышах пятиэтажек.

re-thinkingthefuture.com
Я задолбался искать нормальную девушку и создал Lovely Bot

Как Tinder, только знакомит на основе взаимных увлечений

null