Тема подсчета объектов поднималась не раз, например, здесь, здесь или здесь. Казалось бы, задача пусть сложная, но решаемая. Как всегда, "дьявол кроется в деталях". В нашем случае детали были таковы, что решить в лоб задачу не получалось. Во-первых, источником изображений (видео) были охранные видеокамеры на КПП, которые настроены на видеофиксацию входа на стройку. Во-вторых, нужно было определять одеты ли люди в спецодежду (строительные каски и жилеты).
"Вторая дьявольская деталь" и определила необходимость обучения собственной модели, вместо использования предобученной. Следовательно, нужно собрать набор данных, обучить модель, а потом проверить.
Для получения лучшего результата был использован соревновательный метод нескольких групп. Параллельно проверялись две технологии YOLO и FairMOT, дополнительно внутри YOLO сравнивались 7 и 8 версии, плюс различные способы трекинга объектов.
Группа, занимающаяся FairMOT, столкнулась жесточайшим дефицитом информации по этой технологии, однако исследования не прекратились. Была обучена собственная модель, но результат валидации показал необходимость увеличения размера набора данных.
Из-за небольшого преимущества и удобства использования была выбрана YOLOv8 от ultralytics. Так как охранные камеры давали лишь 10 кадров в секунду, то вполне устаивала самая малая форма модели - nano (YOLOv8n). Были протестированы различные гиперпараметры и конфигурации обучения: форма модели, количество прогонов, размер пакета, разрешение изображений, использование предобученной модели, оптимизаторы и прочее. К сожалению, самые лучшие показатели едва приближались к предобученной модели. Тогда было принято решение увеличить набор данных. Так появился датасет второй версии.
Продолжались и соревнования трекеров, в результате которого победителями стали DeepSORT и OCSORT. Тут надо сделать небольшое отступление, чтобы понять необходимость использования трекинга объектов. Для того чтобы подсчитать людей, необходимо каким-то образом их идентифицировать в разных кадрах. Этим и занимается трекинг объектов. У каждого трекера есть свои преимущества и недостатки. DeepSORT чуть лучше отслеживает (детали чуть ниже), но он использует еще одну нейросеть для идентификации графического изображения, что приводит к более медленной работе всей системы.
Казалось бы, все победители выявлены, осталось только написать программу подсчета, но тут опять в дело вступают "дьявольские детали". В какой момент считать человека вошедшим или вышедшим? Появилось два разных подхода как решить эту задачу.
Первый подход заключается в сравнении координат начала (появление человека) и конца (пропадание человека). Напомню, что все камеры настроены на фиксацию входа. Таким образом, входящие люди появляются вверху кадра (маленькое значение ординаты), а пропадают внизу (большое значение ординаты).
Второй подход подразумевает пересечение человеком воображаемой границы на уровне турникета. Если граница пересекается сверху вниз, то человек входит, наоборот - выходит. Первоначально, эта граница задавалась вручную для каждого видео, потом была обучена модель, которая получала координаты турникета, чтобы не вводить их вручную. Причем нейросеть, определяющая положение турникета, нужна только в начале видеопотока и может работать даже без GPU.
У каждого подхода есть свои недостатки и преимущества. Первый подход не требует определения границы, зато дает количество вошедших и вышедших только после окончания видео. Второй подход позволяет в процессе обработки выдавать результаты, но эти результаты могут сильно отличаться от реальных, так как человек может многократно пересекать эту границу туда-сюда.
Имелись и общие проблемы для обоих подходов. В целом, можно разделить общие проблемы на проблемы детекции (точности определения) и трекинга. Проблемы детекции в основном связаны с качеством получаемого видеоизображения вплоть до появления "призраков": был человек, а в следующем кадре вместо него размытое пятно.
Проблемы трекинга более обширны и зависят в первую очередь от трекера, но в целом их можно разбить на следующие группы:
- поздняя идентификация;
- потеря идентификатора;
- передача идентификатора другому человеку.
Поздняя идентификация в основном возникает у выходящих людей из-за расположения камеры (помните: фиксация входа). Когда человек выходит, то появляется его голова, потом туловище и только ближе к турникету камера "видит" человека целиком. Из-за этой особенности возникают и проблемы детекции человека, каски и жилета. А уж как трекеры выходящих "не любят".
Потеря идентификатора происходит в основном из-за перекрытия одним человеком другого человека (окклюзия). Основной причиной окклюзии является расположение камеры, которое не учитывает очередь из людей. У всех трекеров имеются настройки, чтобы "лечить это заболевание", но это приводит к другой проблеме: передаче идентификатора другому человеку. Также потеря идентификатора может происходить при повороте человека, при наклоне, при приседании, при изменении освещения в коридоре в результате открытия или закрытия одной из дверей.
Передача идентификатора другому человеку происходит не только из-за настроек, решающих проблему потери идентификатора, но и при близком расположении двух людей, в том числе при окклюзии.
Устранить абсолютно все ошибки не удалось даже при детальной настройке гиперпараметров трекеров, учете расположения барьера и т.д., то есть стопроцентная точность не достигается.
Основной проблемой является расположение камеры. Для точного подсчета проходящих людей камера должна быть равноудалена от входа и выхода. Стоящие друг за другом люди не должны перекрывать других людей. Но это не та проблема, с которой может справиться разработчик. Поэтому были выдвинуты некоторые гипотезы, которые помогут решить вышеуказанные проблемы.
Первая гипотеза подразумевает определение человека не во весь рост, а по плечи. Что должен дать такой подход? Во-первых, раннее определение выходящего человека. Во-вторых, более геометрически стабильный прямоугольник ограничивающей рамки человека, чем во весь рост, что решит проблему поздней идентификации. В-третьих, при частичном перекрытии одного человека другим, реже перекрывается именно верхняя часть человека. Под эту гипотезу была сделана еще одна версия набора данных с модифицированными аннотациями. Обучение этой версии датасета показало еще худший результат по сравнению с обучением предыдущей версии. Причина этого кроется в том, что площадь детектируемого объекта уменьшилась, соответственно ухудшилось точность распознавания. Так же возникла проблема определения какому человеку относится жилет. В принципе все эти проблемы могут быть решены, но из-за нехватки времени, развитие этой гипотезы не произошло.
Другой гипотезой было предположение, что разные трекеры делают разные ошибки, поэтому их сочетание может уменьшит ошибку до нуля. По факту же, комбинирование трекеров незначительно улучшало результаты, зато сильно нагружало систему.
Почему такое пристальное внимание уделялось ресурсоемкости приложения? А это третья "дьявольская" деталь - обработка видеопотока. Отличие потока видео от файла в том, что мы не знаем где будет конец этого потока, поэтому вынуждены обрабатывать "на лету". Задержки могут быть, но в целом скорость обработки не должна быть меньше скорости видепотока. Это просто вынуждает использовать GPU.
Так что, каждая задача решается по-своему (если она вообще решается), несмотря на наличие решений похожих задач. Дьявол кроется в деталях!