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

Но иногда водители выходят на линию уже уставшими — например, весь день человек был занят на другой работе, а вечером решил “подрулить”. Что с этим делать? Как понять, что водитель заступает на смену не выспавшись? Можно, например, попробовать оценить, насколько внимательно он следит за дорогой, и определить признаки усталости, например по характеру морганий. Звучит просто? Всё сложнее, чем кажется.

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

Итак, дано: частота и длительность морганий зависят от степени усталости. Когда мы утомлены, голова менее подвижна, направление взгляда меняется реже, мы моргаем чаще и оставляем глаза закрытыми на большие промежутки времени — разница может измеряться долями секунд или несколькими градусами поворота, но она есть. Нашей задачей было сконструировать устройство, которое позволяет анализировать моргания, а также направление взгляда, зевки и движения головы, чтобы оценивать уровень внимания и усталости водителя.

Сначала мы решили: а давайте сделаем приложение для ноутбука, поставим его добровольцам из числа сотрудников, а оно будет при помощи встроенной камеры отслеживать нужные нам признаки? Так мы сразу соберём большой массив информации для анализа и быстро проверим свои гипотезы.

Спойлер: ничего не вышло! Довольно быстро стало понятно, что большинство людей при работе за компьютером постоянно смотрят на клавиатуру и наклоняют голову. То есть глаз не видно, и даже непонятно, закрыты они или открыты, моргает человек или просто переводит взгляд с экрана на клавиатуру и обратно.

Тогда мы поняли, что даже для того, чтобы сделать прототип, нам нужно какое-то устройство. Мы купили первую попавшуюся модель IP-камеры, которая работает в ИК-диапазоне.

Зачем нам ИК-диапазон? Освещение бывает разным, иногда пользователь в тени, иногда свет сзади, сверху или его вообще нет. Если мы делаем измерительный прибор, то он должен работать в любых условиях одинаково.

Для эксперимента подошла довольно популярная камера от Xiaomi — CHUANGMI.

Оказалось, что она снимает с частотой 15 кадров в секунду, а нам надо в два раза больше: моргание длится от 30 до 150 мс, при 15 кадрах в секунду мы рисковали «не увидеть» моргания короче 60–70 мс. Поэтому нам пришлось модифицировать её прошивку, чтобы принудительно включить ИК-подсветку, получить прямой доступ к видеопотоку и забирать нужные нам 30 кадров в секунду. Подключив камеру к ноутбуку и настроив получение видеопотока через RTSP-протокол, мы начали записывать первые видеоролики. Камеру расположили на 15 см ниже камеры ноутбука, и это позволяло лучше «видеть» глаза пользователя.

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

Стало понятно, что единственный путь — сделать или купить подходящую камеру и установить её в машину.

Казалось бы, всё элементарно: покупаем видеорегистратор, поворачиваем в сторону водителя, крепим в машине и раз в неделю забираем SD-карты с видеозаписями. Но и тут на деле всё оказалось не так просто.

Во-первых, крайне сложно найти видеорегистратор с ИК-подсветкой, а нам надо хорошо видеть лицо, особенно ночью.

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

В-третьих, эта затея плохо масштабируется на десять, сто и более машин. Нам ведь нужно собрать много данных от разных водителей, чтобы проанализировать их и сделать выводы. Каждую неделю или каждый день менять карты памяти на сотне машин вручную — огромная трата времени. Мы даже пробовали найти камеру, которая бы загружала видеозаписи в облако, но ничего похожего на рынке не было.

Возникла даже идея сделать «свой видеорегистратор» из Raspberry Pi, камеры с ИК-подсветкой и крепления.

Получилось не совсем то, чего мы ожидали: громоздко, невозможно установить камеру отдельно от компьютера. Дело в том, что при длине кабеля больше 50 см начинались проблемы с сигналом, да и сам по себе CSI-шлейф довольно хрупкий, слишком широкий и поэтому не очень пригоден для монтажа в машину.

Надо ехать в Гонконг, решили мы. Цель поездки была довольно абстрактная: посмотреть, что делают разные производители в области анализа поведения водителя, купить образцы изделий, если найдём, и поискать подходящие технические решения/компоненты, которые мы могли бы установить в машины.

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

В итоге мы купили несколько образцов камер и одноплатных компьютеров. Стало понятно, что 1) подходящих нам готовых изделий нет; 2) надо разделять компьютер и камеру, чтобы не заслонять обзор водителю. Поэтому мы взяли плату камеры с интерфейсом USB и в качестве вычислительного блока к ней одноплатный компьютер Banana Pi, а заодно и несколько Android-плееров на процессорах Amlogic.

«Почему плееры?» — спросите вы. На самом деле S912 и даже S905 — довольно мощные с точки зрения производительности и вполне себе потянут запись видео для наших целей даже с анализом изображения прямо на месте. Анализ изображения на месте нужен был для того, чтобы не слать весь видеопоток на сервер.

Давайте посчитаем: минута хорошо сжатого в H.264 видео в разрешении 640 × 480 (30 FPS) занимает не меньше 5 мегабайт. Значит, за час будет 300 мегабайт, а за стандартную 8-часовую смену — примерно 2-3 гигабайта.

Заливать каждый день при помощи LTE-модема 3 гигабайта видео — ну очень “дорого”. Поэтому мы решили периодически записывать 5-минутные ролики, а всё, что происходит в машине, анализировать прямо там и загружать на наши сервера уже в виде разобранного потока событий: набор точек лица, направление взгляда, поворот головы и т. п.

Мы вернулись с выставок в хорошем настроении, привезли кучу нужного (и ненужного) барахла и поняли, как мы будем дальше делать прототип.

USB-камера, которую мы нашли в Гонконге, нам почти идеально подходила: размер 38 × 38 мм, стандартные линзы (12 мм), возможность припаять прямо на плату ИК-диоды подсветки.

Поэтому мы сразу попросили производителя сделать нам прототип с необходимыми компонентами. Теперь мы понимали: нам нужна USB-камера с подсветкой и одноплатный ПК для обработки видео. Мы решили попробовать всё, что было представлено на рынке, и устроили сеанс шопинга на AliExpress. Мы накупили четыре десятка разных камер, десяток одноплатных ПК, Android-плееров, коллекцию 12мм линз и много других странных устройств.

Вопрос с “железом” решился. А как быть с софтом?

Довольно быстро нам удалось на основе OpenCV получить простой прототип, который пишет видео, находит лицо водителя, анализирует его, размечает на лице 68 ключевых точек, распознаёт моргания, зевки, поворот головы и т. п.

Следующей задачей было заставить наш прототип работать на одноплатном ПК. Raspberry PI отвалился сразу: мало ядер, слабый процессор, больше семи кадров в секунду из него не вытащить. А о том, чтобы одновременно писать видео, распознавать лицо и анализировать его, и речи не было. По этим же причинам нам не подошли ТВ-приставки и одноплатные компьютеры на Allwinner (H2, H3, H5), Amlogic S905 и Rockchip RK3328, хотя последний был очень близок к желаемым показателям. В итоге у нас осталось две потенциальных SoC: Amlogic S912 и Rockchip RK3399.

На Amlogic выбор устройств был небольшой: ТВ-бокс или Khadas VIM2. На ТВ-боксе и Khadas всё работало примерно одинаково, но охлаждение ТВ-приставок оставляло желать лучшего, да и настройка Linux на них — зачастую занятие не для слабонервных: заставить работать Wi-Fi, BT, сделать так, чтобы ОС видела всю память, — это долго, сложно и непредсказуемо. В итоге мы выбрали Khadas VIM2: к нему есть штатный радиатор охлаждения, и плата достаточно компактная, чтобы спрятать её за приборной панелью машины.

К этому моменту производитель платы камеры уже прислал нам пробную партию из ста штук, и мы рвались в бой: делать прототип, ставить в машину и собирать данные.

У нас была камера, был софт, был одноплатный ПК, но не было ни малейшего представления, как всё это разместить в машине и подключить к бортовому питанию.

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

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

  1. Посередине лобового стекла.
  2. У левой стойки.
  3. На зеркале заднего вида.

В тот момент нам показалось, что лучше всего прикрепить камеру прямо к зеркалу заднего вида: оно всегда направлено в лицо водителю, поэтому камера будет снимать именно то, что нам надо. К сожалению, производители зеркал заднего вида не позаботились о том, чтобы к ним можно было что-то удобно и надёжно прикрепить. Камеры плохо держались, падали и закрывали обзор.

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

Тогда мы решили крепить камеру на уровне глаз у левой стойки: меньше закрываем обзор и хороший угол для камеры, чтобы было видно водителя. Корпус пришлось переделать, поскольку крепления с шарнирами показали себя крайне ненадёжно: они разбалтываются при тряске, ломаются, а присоски отклеиваются от стекла.

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

Из-за проблем с производительностью мы решили поменять SoC на более мощную, поэтому выбрали одноплатный ПК NanoPI M4 на процессоре Rockchip RK3399.

По сравнению с Khadas VIM2 он примерно на треть производительнее, у него есть аппаратное сжатие и декодирование видео, и он намного стабильнее ведёт себя в сложных температурных условиях. Да, мы пробовали запускать камеры и платы в морозильнике, грели их в духовке и проводили множество других нечеловеческих испытаний.

Поскольку мы записываем видео не просто так, а в динамике в течение дня, было важно, чтобы системное время на устройстве было точным. К сожалению, большинство одноплатных компьютеров не оборудованы часами с автономным питанием. Нам повезло, что на нашем NanoPI был разъём для подключения батарейки.

Пришлось спроектировать корпус для компьютера, который защищал бы его физически и выступал в качестве держателя для антенн WiFi и BT. Там же мы предусмотрели место для монтажа батарейки часов с держателем.

Далее мы планировали оборудовать прототипами сто машин, которые будут записывать видео и в режиме онлайн передавать нам в облако всю телеметрию: есть ли водитель, как часто и долго он моргает, зевает, отвлекается от дороги, поворачивает голову и т. п. Все эти (и не только) параметры позволяют нам обучать модель, которая оценивает, насколько сконцентрирован на дороге водитель, не отвлекается ли он и не устал ли. Чтобы всё это делать прямо на устройстве в машине, нам пришлось полностью переписать код, сделать аппаратное сжатие видео, ротацию логов и видеозаписей, регулярную отправку на сервер, удалённое обновление ПО и многое другое.

В это же время нам стало понятно, что наши расчёты и алгоритмы будут работать намного лучше при более точном базовом анализе лица. В первых прототипах мы использовали встроенный в OpenCV детектор лиц на основе haar-каскадной модели и модель для разметки 68 точек лица на основе библиотеки dlib. Положение головы мы вычисляли сами путём расчёта проекции точек лица на фокальную плоскость. Open-source решения по распознаванию и разметке лиц хорошо работают на кадрах, где лицо снято в анфас или профиль, но на промежуточных состояниях часто ошибаются.

Поэтому мы решили лицензировать хорошее стороннее решение по распознаванию и разметке лица — SDK от компании VisionLabs. По сравнению с предыдущими алгоритмами оно более ресурсоёмкое, но даёт заметный прирост качества распознавания и разметки лица, что приводит к более точному извлечению факторов для машинного обучения. С помощью коллег из VisionLabs нам удалось быстро перейти на их SDK и получить нужную нам производительность: 30 кадров/сек. при разрешении 640х480.

SDK VisionLabs использует нейронные сети для распознавания лиц. Технология обрабатывает каждый кадр, находит на нем лицо водителя и выдает координаты расположения глаз, носа, рта и других ключевых точек. Полученные данные используются для создания нормализованного кадра размером 250х250, где лицо находится строго по центру. Этот кадр уже можно использовать для вычисления положения головы в градусах по трём осям: yaw, pitch и roll. Чтобы отследить статус глаз водителя, система анализирует изображение глаз и для каждого глаза принимает решение: закрыт он или открыт. Система умеет при помощи технологии IR Liveness определять, живой человек перед камерой, или водитель прикрепил фотографию. Для анализа используется нормализованный кадр, а на выходе мы получаем результат alive или notalive.

Заключение

Пока мы переписывали и отлаживали ПО, наши 3D-принтеры днями и ночами печатали корпусы для камер и одноплатных ПК. На печать комплекта (корпус камеры + корпус ПК) уходило примерно 3–4 часа работы принтера, поэтому нам пришлось расширить производственные мощности: задействовали четыре принтера. Но мы всё успели сделать в запланированные сроки.

За две недели мы полностью оборудовали первую сотню машин в нескольких таксопарках — партнёрах Яндекс.Такси. Сейчас с их помощью мы собираем видеозаписи, анализируем поведение водителя, признаки усталости, улучшаем алгоритмы и обучаем модели, оценивающие уровень внимания и усталости. И только после этого (с учётом всех данных, отзывов водителей и пассажиров) мы будем готовы перейти к следующему этапу – массовому производству и внедрению.

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