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": 26, "likes": 23, "favorites": 47, "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: 'https://vc.ru/selectel/306690', num: 3 }, { name: 'chill', url: `${cdnUrl}ChillCat`, text: 'трекер, который подскажет, когда пора отдохнуть', link: 'https://vc.ru/promo/288561-eye-tracker', num: 1 }, { name: 'cloud', url: `${cdnUrl}CloudCat`, text: 'котика: даёшь ему «пять», а\u00A0он делает бэкап в облако', link: 'https://vc.ru/dev/294799-maneki-neko', num: 2 } ] let buttonCycle = document.querySelector('.button--cycle') let buttonChoose = document.querySelector('.button--choose') let buttonMobile = document.querySelector('.button--mobile') let textField = document.querySelector('.selectel-footer-subtitle') let imageAgent = document.querySelector('.image--agent') let banner = document.querySelector('.selectel-footer') buttonCycle.addEventListener('click', cycleClick) buttonChoose.addEventListener('click', () => sendEvent(`Promo ${articles[currentArticleNumber].num} Left`, 'Click')) buttonMobile.addEventListener('click', () => sendEvent(`Promo ${articles[currentArticleNumber].num} Left`, 'Click')) 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) { sendEvent(`Promo ${articles[currentArticleNumber].num} Right`, 'Click') 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?3' 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' textField.innerHTML = generatedText() } function incrementArticleNumber() { previousArticleNumber = currentArticleNumber if (currentArticleNumber >= articles.length - 1) { currentArticleNumber = 0 } else { currentArticleNumber++ } } const sendEvent = (label, action = 'Click') => { const value = `SelectelDIY — loc: Footer — ${label} — ${action}`; if (window.dataLayer !== undefined) { window.dataLayer.push({ event: 'data_event', data_description: value, }); } }; 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?3`, ]) 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
26 комментариев
Популярные
По порядку
Написать комментарий...

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

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

12

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

6

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

1

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

1

Ага, мне так школьники карму слили за критику васянской сборки для пентеста под виндоувс)))

1

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

1

хабр мертв, совершенно. Аудитория уехала на VC и DTF

1

На python я уже не потяну.
Делал такого бота на геткурсе с помощью процесса.
Он тупо каждые полчаса спрашивал в телеге- чем занимаешься?
Как ни странно-помогало.

А вот упражнения для глаз это хорошая идея. Доработаю своего.

0

Пиздатый бот
Остался доступ?

0

Нет

0

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

Есть способы:
1. Кофе
2. Музыка

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

0

Нет, потому что читая VC ты уже занимаешься ерундой, был бы парадокс

0

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

5

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

3

можно начать курить, например ;-)

1

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

0

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

1

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

1

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

2

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

0

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

0

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

0

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

0
Розовый завод

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

0

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

0

Комментарий удален

Розовый завод

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

0
Читать все 26 комментариев
«Яндекс.Маркет»: в моем заказе вместо наушников оказалась бутылка водки

Я давно хотела беспроводные наушники и наконец заказала себе Apple AirPods. Оформила заказ 15.10.2021 через Яндекс.Маркет в магазине Superbia.ru

Кейс: как мы за 45 дней заработали 1,5 млн. рублей для центра медицинского онлайн-образования

Ниша обучения в интернете позволяет находить клиентов буквально в любой части мира. Поэтому поиск целевой аудитории в социальных сетях — наиболее оптимальное решение для масштабирования подобного бизнеса. В статье мы раскроем секреты продвижения профильного образования, а также расскажем, как для клиента добиться продаж на 1,5 млн. рублей всего…

Исследование: сотрудники хотели бы иметь комнату отдыха, бесплатный сок, а работодатели уже готовы покупать ЗОЖ-снеки

Онлайн-сервис доставки продуктов и товаров СберМаркет и исследовательское агентство Research Me спросили сотрудников, как они хотели бы питаться в офисе и что в нем видеть. В опросе приняли участие более 1500 работающих людей по всей России. Сервис также спросил работодателей – В2В-клиентов СберМаркета: что они покупают в офис, что точно никогда…

#20вопросов Ивану Юнину, директору проекта "Транспортные инновации Москвы"

Транспортная отрасль сегодня претерпевает колоссальные изменения, во многом благодаря инновациям. Стартапы с технологиями на базе AI для транспортной сферы востребованы как никогда. Согласно отчету Deloitte "Transporattion Trends 2020" глобальный рынок AI для транспортной отрасли к 2023 году может достигнуть 3,5 млрд долларов США.

«Опора России» предложила штрафовать маркетплейсы за дискриминацию товаров и продавцов Статьи редакции

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

В даркнете выставили на продажу базу данных водителей Москвы и Московской области из 50 млн строк — «Ъ» Статьи редакции

В базе есть данные с 2006 по 2019 год, бонус при покупке — файл с информацией от 2020 года.

Акции Facebook, Twitter и других зарабатывающих на интернет-рекламе компаний упали на 2-6% после отчётности Snap Статьи редакции

Snap отчиталась о выручке ниже прогнозов аналитиков из-за изменения условий конфиденциальности в iOS 15.

Цифровая трансформация банков: что это такое?
Автор: Ксения Борбачева
заместитель генерального лиректора Агентства инноваций Москвы
НДФЛ, льготы и поправки. Что нового в бухгалтерии и налогах в 2021 году

Как в бухгалтерском, так и в налоговом законодательстве в этом году появились новые правила. На примере IT-отрасли рассмотрим налоговые льготы и другие ключевые изменения, которые нужно знать специалистам (физическим лицам) и работодателям – предпринимателям или юридическим лицам.

Бизнес-филантропия и благотворительность. Почему это не затраты, а вложения? Рассказываем на примере CloudPayments

Социальная ответственность составляет важную часть ДНК компании CloudPayments. Делимся инсайтами, почему мы поддерживаем НКО, создаем благотворительные проекты и как транслируем принципы филантропии внутри команды.

«Модульбанк» запустил льготные кредиты для продавцов на маркетплейсах

Предприниматели могут получить до 10 млн рублей.

Dylan Gillis
null