Привет, Хабр! Меня зовут Владимир, я студент 4го курса КубГТУ (к сожалению).


Некоторое время назад я наткнулся на статью о разработке CV-системы для обнаружения рабочего персонала без касок, и решил поделиться собственным опытом в данной области, полученным в ходе стажировки в одной промышленной компании летом 2017 года. Теория и практика OpenCV и TensorFlow в контексте задачи обнаружения людей и касок — сразу под катом.



КДПВ, снятая в реальном времени с камеры видеонаблюдения


Дано: доступ к камерам видеонаблюдения промышленных объектов работодателя, 2-4 студента-стажера (в ходе разработки число занятых проектом менялось).


Задача: разработать прототип системы, в реальном времени обнаруживающей сотрудников без касок. Выбор технологий — на свое усмотрение. Наш выбор пал на Python, как на язык, позволяющий с минимальными трудозатратами реализовать первый рабочий прототип, и — поначалу — OpenCV, как библиотеку машинного зрения, о которой мы были наиболее наслышаны.


OpenCV представляет собой библиотеку, реализующую преимущественно классические методы машинного зрения, такие как каскадные классификаторы. Суть данного подхода заключается в создании т.н. ансамбля слабых классификаторов, т.е. таких, что их соотношение верно классифицированных ими объектов к общему количеству положительных срабатываний было хотя бы незначительно больше 0.5. Один подобный классификатор не способен дать какого-либо результата, однако объединение тысяч таких классификаторов может дать крайне точный результат.



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


Очевидно, что задача обнаружения человека без каски сводится к задачам обнаружения человека как такового и… каски! Или же ее отсутствия. Доступ к видеокамерам позволил достаточно быстро собрать первый датасет из обрезанных фото касок и самих людей, как в касках, так и без (достаточно быстро нашлись и такие), и в дальнейшем довести его объем до 2к+ фотографий.



Разметка изображений для обучения


На этом этапе была найдена первая неприятная особенность OpenCV — официальная документация была разрознена и местами просто ссылалась на книгу одного из ведущих разработчиков библиотеки. Для многих параметров значения приходилось подбирать экспериментально.


Первый же запуск классификатора, обученного на касках, обнаруживал их с точностью около 60% при единичных случаях ложноположительных срабатываний! Мы чувствовали, что находимся на верном пути. Задача обнаружения людей оказалась куда сложнее: в отличие от касок, люди появлялись в кадре под большим количеством ракурсов и в целом требовали от классификатора куда более продвинутых способностей к обобщению. Пока я занимался доработкой классификатора, обученного на касках, в качестве альтернативы тестировалось CV-классическое обнаружение объектов, базирующееся на алгоритме выделения контуров Canny и подсчете движущихся объектов.


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


И тут возникла новая проблема: подавляющее большинство кадров сохранялись из-за ошибок распознавания, а не персонала без касок.  Обучение на свежих данных несколько улучшило результат распознавания, однако каски распознавались в ~75% случаев (при единичных ложных срабатываниях), а перекрывающие друг друга в кадре фигуры людей правильно подсчитывались лишь в чуть более чем половине случаев. Я убедил менеджера проекта выделить мне неделю на разработку нейросетевого детектора.


Одной из фич, делающих работу с НС удобной — как минимум по сравнению с классификаторами — является end-to-end подход: в процессе обучения классификатора помимо размеченных изображений касок/людей требовались изображения фона и изображения для валидации классификатора, которые требовалось конвертировать в специальный формат, при этом процесс конвертации управляется множеством различных нетривиальных параметров, не говоря уже о параметрах самого классификатора! В случае же работы с алгоритмами подсчета движущихся объектов и прочими процесс становится еще более сложным, к изображениям предварительно применяются фильтры, удаляется фон и т.д. End-to-end learning требует от разработчика "всего лишь" размеченный датасет и параметры обучаемой модели.


ML-фреймворк TensorFlow и недавно появившийся на тот момент репозиторий tensorflow/models удовлетворял моим требованиям — он был достаточно хорошо задокументирован, с его помощью можно было быстро написать работающий прототип (самые популярные архитектуры работают практически "из коробки"), в то же время его функционал полностью подходил для дальнейшей разработки, если прототип окажется успешным. После адаптации имеющегося туториала под имеющийся датасет с использованием 101-слойного резнета (принципы сверточных нейронных сетей уже неоднократно освещались на Хабре, я лишь позволю себе сослаться на статьи [1], [2]), обученного на датасете COCO (который включает в себя и фото людей), я сходу получил более чем 90% точности! Это было убедительным аргументом для начала разработки детектора касок на основе СНС.



Обученная на стороннем датасете СНС с легкостью распознает стоящих рядом людей, но делает ошибку там, где от нее вообще не ждали распознавания :)


В ходе обучения моделей TensorFlow может генерировать чекпоинт-файлы, позволяющие компилировать и тестировать НС на разных этапах, что бывает полезно, если во время дообучения что-то пошло не так. Скомпилированная модель представляет из себя ориентированный вычислительный граф, начальные вершины которого представляют собой входные данные (в случае работы с изображениями — значения цвета каждого пикселя), а конечные — результаты распознавания.



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



Заветный график уменьшения ошибки обучения


После тестирования ряда архитектур была выбрана ResNet-50 как обеспечивающая оптимум между быстродействием и качеством распознавания. После взвешивания всех "за" и "против" было решено оставить эту обученную сеть как есть, поскольку она уже давала приемлемый результат, и обучить на касках более простую Single Shot Detector (SSD) сеть [3], которая давала меньшую точность при распознавании людей, но обеспечивала удовлетворительные 90%+ при работе с касками. Это, казалось бы, нелогичное решение было обусловлено тем, что дополнительное использование SSD незначительно увеличивало время, затрачиваемое на само распознавание, но в разы сокращало время, затрачиваемое на обучение и тестирование сети с разными параметрами и обновленным датасетом (с нескольких суток до 20-30 часов на GTX 1060 6GB), а значит, увеличивало итеративность разработки.


Таким образом, можно сделать несколько выводов: во-первых, современные НС-фреймворки обладают низким порогом вхождения (но, бесспорно, их эффективное использование требует глубоких знаний в области машинного обучения) и гораздо более удобны и функциональны при решении задач распознавания образов; во-вторых, студенты бывают полезны для быстрой разработки прототипов и тестирования технологий ;)


Буду рад ответить на вопросы и конструктивную критику в комментариях.

Комментарии (28)


  1. remzalp
    23.04.2018 11:43
    +1

    У меня возникает вопрос — не думали выделять только движущиеся объекты?


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


    1. vvsotnikov
      23.04.2018 13:57

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


  1. Sinatr
    23.04.2018 12:20

    совпадает ли количество распознанных людей и касок в кадре
    А что будет, если положить пару касок «в кадр»? =)

    Каска — внутри прямоугольника с распознаванием человека. Можно было бы распознавать человеков, если распознано хорошо (98% и выше?), то передавать прямоугольничек (а не весь кадр) в сеть, распознающую каски и если сеть не найдет (0 %), да еще и несколько кадров подряд (и еще можно с разных камер, зависит от покрытия) — только тогда генерировать событие «человек без каски», включать сирену, вызывать копов и тд.

    Человек может снять каску ненадолго, чтобы почесаться, отойдя в безопасную зону и поглядывая вверх. Это можно автоматизировать, но наверное не надо. Лучше просто слать кусок видео (10 сек до и 10 сек после) вместе с событием. Злой вахтер (или кто там контролирует безопасность) разберется.


    1. vvsotnikov
      23.04.2018 14:00

      Да, также каска может висеть на поясе, мы тоже об этом сразу подумали :)
      Можно скармливать обоим сеткам целый кадр, а затем лишь проверять, что detection boxes накладываются друг на друга (при этом каска должна находиться в "верхней части" человека). К сожалению, я занимался этим проектом ограниченное время и не успел это реализовать.


  1. vova_sam
    23.04.2018 14:23

    я правильно понял, что для определения касок Вы разбиваете картинку на квадраты размером примерно в каску и затем ищете каску в каждой картинке? Координаты каски в этом случае — это координаты квадрата?
    примерно как вот тут github.com/JustinHeaton/Vehicle-Detection


    1. vvsotnikov
      23.04.2018 15:11

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

      R-CNN использует более сложный механизм: сначала нейросеть выделяет ряд регионов, которые предположительно соответствуют искомым объектам, а затем проверяет принадлежность региона какому-либо классу объектов.


  1. edwardspec
    23.04.2018 14:47

    Заметил, что спецодежда (на фотках из статьи) имеет хорошо заметную белую полосу в центре.
    Можно ли упростить распознание человека, если искать не человека, а эту полосу?


    1. vvsotnikov
      23.04.2018 15:23

      Подобные ad-hoc решения как раз свойственны классическим CV-методам (к примеру, на самых начальных этапах разработки мы экспериментировали с поиском каски по ее оранжевому цвету), однако в южных регионах форма спецовок несколько отличается и данная фича будет неприменима. В случае же с нейросетями эффективнее будет просто увеличить и разнообразить используемый для обучения датасет (то есть следовать end-to-end подходу).


  1. topheracher
    23.04.2018 15:24

    Если ходить с шариком, то это будет каска? Поохоже на определение наличия сферической области на diff между кадрами.


    1. vvsotnikov
      23.04.2018 15:28

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


  1. impetus
    23.04.2018 19:52

    А если каски будут массово выглядеть как-то вот так:
    image
    (встречал конторы, где один себе расписал — и все начали кто во что горазд себе каску красить — в т.ч. очень-очень прилично.


    1. vvsotnikov
      23.04.2018 20:20

      Это является нарушением ГОСТа, регламентирующего цвет каски в зависимости от должности работника, и на площадках работодателя ни разу не встречалось :)


      1. Germanets
        24.04.2018 08:46

        Для тех, кто заинтересуется цветовой дифференциацией касок
        ГОСТ 12.4.087-84 ССБТ. Строительство. Каски строительные. Технические условия», пункт 2.3:
        Белый цвет каски = Руководящий состав, начальники участков и цехов, инспекторы по ТБ;
        Красный цвет = мастера, прорабы, ИТР, Главный механик, Главный энергетик
        Желтый и Оранжевый цвет касок = рабочие


        1. EShin
          24.04.2018 14:00

          Бывал на многих стройках и не видел чтобы ГОСТ соблюдали. Вместо красного часто используют синий, ИТР почти всегда в белых касках. Если задерживают зарплату, то очень часто оранжевые каски начинают носить абсолютна все.


          1. vvsotnikov Автор
            24.04.2018 14:07

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

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


      1. impetus
        25.04.2018 10:31

        ну вот вам красные каски:
        image
        image
        image
        я вообще-то вам задал вопрос про возможности вашей системы, а не про юридические тонкости толкования в ГОСТе понятия «цвет». Не проверяли на таких наборах — ок, не попалось, просто имейте в виду, что такое бывает.


        1. vvsotnikov Автор
          25.04.2018 11:15

          Помимо слов про ГОСТ я ответил вам, что это

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


  1. AVI-crak
    24.04.2018 09:05

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


    1. avf1906
      24.04.2018 10:10

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


      1. Sly_tom_cat
        24.04.2018 12:16

        Ну так что — тест пройден :)!

        Я по работе довольно много в каске ходил и таки она много раз выручала…


  1. ev3658
    24.04.2018 14:08

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


    1. vvsotnikov Автор
      24.04.2018 14:15

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


      1. impetus
        25.04.2018 10:37

        Там и «окупается» она лишь за счёт того, что этот труд сортировщиков-граждан не учитывается и не оплачивается. В Германии давно идёт вялотекущая общественная дискуссия, что по-хорошему этот труд надо бы как-то участь-посчитать — даже не столько с целью оплатить, сколько что бы просто самим себе честно понимать-представлять, во сколько человеко-часов стране/нации это дело реально обходится.


  1. YetAnotherSlava
    24.04.2018 15:16

    А в чём конечная цель проекта? Штрафики собирать с работников, за то что каску не надели?


    1. Scf
      24.04.2018 16:57

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


  1. VladVin
    24.04.2018 22:34

    Спасибо за статью.
    Интересная задача, хотел бы тоже поиграть с ней.
    А данные какие-нибудь есть? В особенности интересуют размеченные каски


    1. vvsotnikov Автор
      25.04.2018 11:18

      Не уверен, что вправе их предоставить, извините.


  1. reinvent
    25.04.2018 14:56

    Статья интересная, только вопрос такой: каков должен быть размер изображения, чтобы распознать каску? Нередко на всю стройплощадку висит 2-3 камеры, а по площадке гуляют рабочие.
    Вообще, насколько реально довести до ума такую систему?