ИИ-контроль средств индивидуальной защиты (СИЗ) — уже классика среди задач прикладного компьютерного зрения. В открытых статьях на Habr уже подробно разбирают сбор датасета, разметку, сравнение YOLO, DETR и Faster R-CNN, работу с зонами и потоками камер. В научных публикациях 2024–2026 годов тоже видно то же направление: модели учатся распознавать каски, жилеты, очки, перчатки, а датасеты прямо содержат классы есть СИЗ и нет .
Зачем тогда нужна кастомная разработка? Раскроем тему на примере реального проекта.
Задача: автоматически фиксировать нарушения ношения СИЗ (каски, спасательные жилеты, костюмы-поплавки) в рабочих зонах. Место действия — открытая палуба судна. На входе RTSP-потоки судовых камер, на выходе — подтвержденные инциденты. Система должна работать анонимно, фиксируя факт нарушения, а не личность.
Обучить детектор и в прод? Не так сразу. На примере проекта четко увидели: одиночный кадр на палубе почти никогда не является доказательством нарушений.

Иллюзия идеального детектора
В промышленной системе и в реальной эксплуатации нейросеть —всего лишь сенсор, а не судья. Сенсор ошибается в силу того, что он находится не в идеальных лабораторных условиях: на объектив попали брызги, человек отвернулся, работники перекрывают друг друга в кадре. Если генерировать алерт на каждый спорный кадр, журнал инцидентов за смену превратится в свалку ложных тревог, которую оператор благополучно отправит в игнор.
На палубе одновременно действуют сразу несколько источников нестабильности, которые напрочь ломают наивную логику “нет рамки жилета = нарушение”:
-
Оптика и погода: дождь, снег, туман и морская пыль снижают контраст и плодят ложные мелкие объекты.
-
Оптические артефакты: мокрый металл и лужи дают блики, которые нейросеть радостно принимает за светлые каски или куски жилетов
-
Физика: ветер постоянно меняет форму одежды. Капюшоны, воротники и костюмы-поплавки в соседних секундах выглядят совершенно по-разному.
-
Геометрия: Качка и вибрация приводят к тому, что границы зон безопасности и траектории людей начинают непредсказуемо “плыть”.
Главная подлость палубного ракурса: для камеры визуальное перекрытие (ошибка детектора) внешне неотличимо от реального снятия экипировки (нарушения ТБ).
Разберем на практике. Матрос в полной экипировке наклоняется над тросом. Из-за ракурса каска прячется за плечом, а жилет перекрывается рукой. Физически человек защищен, но детектор на трёх кадрах подряд сигнализирует: “человек без каски”.
Система воспринимает эту оптическую потерю как факт нарушения и присылает ложный алерт. Наша логика работает иначе: система берет паузу, чтобы трекер смог заново «зацепиться» за экипировку, когда человек сменит ракурс
Разделяй и властвуй: слой событий
Чтобы не сводить операторов алертами с ума, мы разделили систему на два уровня:
1. Модель, которая отвечает только за наблюдения
2. Отдельный инженерный слой логики отвечает за события.
Пайплайн выглядит так:
-
Детектор выдает рамки людей и СИЗ.
-
Ассоциатор решает, кому именно принадлежит каска или костюм.
-
Трекер удерживает ID между кадрами при перекрытиях.
-
ReID-галерея спасает ситуацию и восстанавливает сквозной ID, если трекер всё-таки сбросил локальный номер.
-
Статусная машина ведет состояние каждого элемента экипировки у каждого человека.
-
Менеджер событий принимает итоговое решение: открыть алерт, обновить старый или убить дубль.
Почему IoU здесь не работает
Для привязки каски к человеку стандартный IoU (Intersection over Union) использовать нельзя. Каска слишком мала по отношению к рамке человека, поэтому скор всегда будет крошечным, даже если она сидит идеально. Мы считаем долю площади СИЗ, попавшую внутрь рамки человека.
Но и этого мало. На палубе тесно. Один человек наклонился, другой прошел сзади, и вот уже чужая каска попала в твою рамку. Мы ввели анатомические зоны: система ожидает каску только в верхней части рамки, а жилет — по корпусу.
В интерфейсе оператора мы отказались от пестрых цветов и настроили строгую графитовую тему, где подтвержденные статусы подсвечиваются неоново-зелеными маркерами. Это позволяет глазу мгновенно выхватывать аномалии. К слову о лимитах: если каска в кадре меньше 40 пикселей, наблюдение отбрасывается. Это физическая граница, ниже которой отсутствие детекции перестает быть доказательством.
Память трекера и фокусы с ReID
Для менеджера событий ID человека — это ключ к базе данных. Если трекер меняет номер матроса каждый раз, когда люди проходят друг за другом, таймеры обнуляются и плодятся дубли алертов.
Поэтому поверх обычного трекера мы прикрутили галерею эмбеддингов. На качающейся палубе, где геометрия рамки нестабильна, это дает вторую точку опоры. Чтобы галерея не сошла с ума, мы написали несколько важных правил:
-
Сквозной ID: если трекер потерял человека за оборудованием и вернул его с новым номером, ReID галерея связывает новый локальный трек со старым.
-
Анти свап: когда рамки двух людей сильно перекрываются, мы не обновляем их эмбеддинги.
-
Привязка к месту: если человек появился рядом с точкой, где он исчез, требования к ReID слегка смягчаются.
-
Подозрительные обновления: одиночный эмбеддинг, резко отличающийся от усредненного портрета, не перезаписывает галерею сразу.
Логика алертов
Внутри системы для каждого человека и каждого элемента СИЗ хранится отдельный объект состояния. Он отвечает на вопрос: какой статус у этого элемента сейчас на основе всей недавней истории.
Базовые статусы:
|
Статус |
Когда устанавливается |
|
present |
СИЗ видели недавно, кадр валиден, привязка к человеку уверенная. |
|
suspect |
СИЗ не виден, но таймер отсутствия еще не набрал порог. |
|
absent |
СИЗ не виден дольше порога, человек наблюдается достаточно долго, кадры валидны. |
|
unknown |
Человек мал, обрезан, перекрыт, кадр плохой, идет сильный дождь/снег, объектив загрязнен. |
|
recovered |
СИЗ снова виден устойчиво несколько кадров подряд. |
Разница между absent и unknown принципиальна.
Если человек далеко, каска занимает мало пикселей, а палубу заливает блик, отсутствие рамки каски не доказывает нарушение. Это unknown.
Если человек крупный, находится в рабочей зоне, голова видна, кадры валидны, а каска не появляется 15 секунд – это absent.
Если человек десять минут работает без жилета, это одно нарушение, а не 600 сообщений.
Поэтому после статусной машины стоит менеджер событий. Он отвечает не за распознавание, а за поведение журнала.
У события есть жизненный цикл:
-
статус
absentпоявился, но еще проверяем антидубли и зону -
событие записано в журнал, оператор получил уведомление, сохранены кадр и короткий клип
-
нарушение продолжается, но новые уведомления подавляются
-
если нарушение длится слишком долго, можно отправить повторное напоминание через большой интервал
-
СИЗ снова виден устойчиво или человек покинул зону по корректной траектории
-
событие похоже на дубль уже открытого нарушения или на ошибку трекера.
Если ID сбился, но в той же зоне и в той же части кадра уже есть активное событие нет жилета, система не создает новое. Она обновляет существующее событие или подавляет дубль. Если человек ушел, вернулся в СИЗ и затем снова снял его, это уже новое событие, потому что восстановление сняло флаг “уже зафиксировано”.

Как не утонуть в ложных срабатываниях при шторме
Первая мысль, что делать при плохой погоде — задрать threshold (порог уверенности модели). Но так мы просто пропустим реальные нарушения.
Мы пошли другим путем: мы оцениваем качество самого кадра перед обновлением статусов (размытие, пересветы, капли на объективе). Слой оценки не пытается распознать “дождь”, он просто отвечает на вопрос: годится ли этот кадр как улика? Если нет — статус переходит в unknown. Сильный ливень не генерирует ложные нарушения, он просто ставит систему на паузу. Это честно: лучше промолчать в слепой зоне, чем обвинить матроса в том, чего он не делал.
Вывод
На этапе MVP мы осознанно зафиксировали планку Accuracy на уровне 60-70%. Мы не пытались объять необъятное. Например, система проверяет только наличие СИЗ, а не правильность его ношения. Расстегнутую куртку или надетый поверх каски капюшон мы отложили на следующие этапы, так как это требует долгого сбора краевых случаев.
Главный результат — журнал алертов стал предсказуемым. Видеоаналитика не заменяет инструктаж по ТБ, но она автоматизирует рутину, давая сильную доказательную базу. И самое главное — оператор перестал бороться с системой и начал ей доверять.
Каждый ложный алерт на производстве — это минус к доверию оператора, которое потом очень сложно вернуть. Наш подход со статусными машинами и оценкой качества кадра помог это доверие удержать.
Работали с подобной задачей? Поделитесь, как вы превращаете “сырые” детекции нейросети в осмысленные инциденты, когда камера работает в агрессивной среде? Как отсекаете визуальный мусор и фильтруете ошибки модели?
Автор: NeuroKirKorov


