2021 год был очень насыщенный на хакатоны и ИТ-чемпионаты. Мы неоднократно писали о том,  что специализируемся на проектах по компьютерному зрению. В этом наша сила. На AgroCode Hack нам предстояло за 40 часов решить кейс с использованием компьютерного зрения и AI по сегментации и отслеживанию поросят. Рассказываем, как в очередной раз заняли призовое место на хакатоне и отследили всех хрюш. 

Привет, меня зовут Вова! И я Data Scientist в Napoleon IT. Недавно ребята из моего отдела писали статью про участие в хакатоне. Через неделю мы уже приняли участие в двух хакатонах и провели выходные в офисе тремя командами. В этот раз расскажу про участие в AgroCode Hack от Россельхозбанка. Наша команда LateDev состояла из 3 человек: я в роли Data Scientist, Ваня в роли Frontend Developer и Артур в роли Machine Learning Engineer. Таким составом мы участвовали и раньше, и даже пару раз заняли первые места на Цифровом прорыве. 

Подготовка к хакатону

Из описания на сайте хакатона мы узнали, что нужно будет сегментировать и трекать поросят и как-то оценивать их активность, но что это значит - еще было непонятно. Также было неизвестно, как будет проверяться решение и по каким критериям оцениваться. Предупрежден - значит вооружен! Для страховки мы решили подготовить код обучения высокопроизводительного сегментатора. В итоге написали скрипт обучения SOLO на фреймворке mmdetection. 

Постановка задач и ресурсы

Далее был технический созвон, на котором подробно рассказали о задаче и объяснили в каком виде эксперты ждут решение. Была возможность задать кейсосодержателю интересующие вопросы и уточнить некоторые моменты решения. Организаторы выделили всем участникам сервер с GPU nvidia tesla t4 и дали доступы. Суть задачи была в построении системы отслеживания и мониторинга активности животных в специальных “станках”. Датасет был не размечен и по факту это были просто нарезанные видео с установленной над “станком” камеры наблюдения. Животные на этих видео могли двигаться хаотично или наоборот не проявлять активности, находиться очень близко друг к другу. Всех их нужно было сегментировать.Также иногда в зону наблюдения заходил работник и его необходимо было не сегментировать как животное. Как делать сегментацию и трекинг было понятно, а вот для задачи оценки активности животных нет общепринятого решения и его нужно было придумать самим.

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

Получив все эти данные, мы приступили к решению и проверке гипотез.

Исходные данные

Обучающая выборка неразмеченных видеороликов, полученная системой машинного зрения в условиях промышленного свинокомплекса. На видеороликах сняты животные в условиях производственного станка. Число животных в станке варьируется. Съёмка производится стационарной камерой. Для обучения предоставляется 10 минутных роликов разрешением 1700×1700 пикселей и частотой следования кадров 10 fps Изображения цветные, палитра RGB. 

Техническое решение

Мы начали с задачи сегментации животных. Решили отказаться от mmdetection из-за непростой установки библиотеки и обучать Mask RCNN Inception ResNet V2 из tensorflow object detection, т.к. понимали что для запуска такой модели в дальнейшем нужно будет установить только tensorflow без каких-либо дополнительных зависимостей. Как мы уже упоминали на представленных видео не было разметки, а мы слишком ленивы, чтобы размечать самим. Но нашли выход - репозиторий, в котором решается похожая задача. Правда там оказалось всего 24 изображения в train и 6 в test. Мы сначала не поверили, что именно на этих данных обучалась модель, но решили попробовать тренировать свою, и она действительно заработала на наших данных. Но мы столкнулись с одним артефактом - сотрудники фермы, которые иногда заходили в станок, тоже распознавались как свинки!

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

Красным цветом выделена слепая зона

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

Далее перешли к трекингу. Для него просто использовали алгоритм DeepSort, c которым мы уже работали ранее. Репозиторий, который применяли, также работает на tensorflow, и нам не пришлось добавлять дополнительные зависимости. К сожалению, этот алгоритм возвращает координаты свиней в другом порядке, поэтому пришлось модифицировать код, чтобы он принимал и возвращал еще и маски. Мы обнаружили, что после трекинга возвращаются растянутые маски. Как решить эту проблему мы поняли уже после хакатона. Эта проблема возникла из-за того, что DeepSort использует фильтры Калмана и изменяет предсказанные координаты, и мы переписали код, чтобы трекер возвращал изначальный боксы.

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

Подобрали несколько порогов и выделили несколько классов активности:

  • серый: нулевая активность ( не двигается)

  • зеленый: низкий уровень активности

  • желтый: средний уровень

  • красный: высокий уровень

В итоге мы заняли 2 место :)

Презентация работы  можете найти по ссылке

А код решения посмотреть здесь