На заводе камера смотрит на колбу раз в десять минут. И это не поломка

Просто выключи и включи. На нефтехимическом заводе этот совет не работает
Простой
9 мин
457
Кейс
За производством на нефтехимическом заводе следят сотни камер. Они смотрят на конвейеры с продукцией, на колбы с жидкостью, на рабочие зоны, где люди должны быть в касках. Если что-то идёт не так, у системы есть пять секунд, чтобы заметить это и сообщить оператору.
Сама камера только снимает. А замечает проблемы и рассылает уведомления программа, которая обрабатывает видео с камер. Этой программой тогда занимались мы, разработчики. И на заводе нам мало что можно.
Влезать в оборудование запрещено: производство нефтехимическое, даже датчик не поставишь. Облака тоже нет — серверы стоят в закрытом контуре, без выхода в интернет. Выключить систему на обновление нельзя: производство работает без остановки. А все вычисления идут на обычных процессорах, видеокарт у нас нет.
Меня зовут Даниил Блинов. Когда мы перестраивали систему, я был техлидом команды видеоаналитики СИБУРа. Сейчас работаю в другой команде. Про то, как мы ускорили обработку видео в 28 раз без видеокарт, я уже рассказывал на Хабре.
Эта статья — про то, как мы перестроили систему видеоаналитики под сотни камер на тех же серверах и без остановки. Глубоко в машинное обучение и компьютерное зрение погружаться не придётся, расскажу простым языком.
Камера нужна, чтобы заметить проблему раньше, чем она станет аварией. Допустим, залипает поршень, который подаёт масло в компрессор. Если этого не увидеть, масло перестанет поступать, компрессор встанет, а на нём завязано производство.
Забилось вибросито — пойдёт брак. Человек без каски зашёл в опасную зону, тут и объяснять нечего.
Заводы у нас от Твери до Амура, на каждом свои серверные, свои камеры, свои задачи. А софт на всех один — тот самый, который разрабатывала наша команда и про который эта статья.

Три ограничения, которые никуда не денутся
Три вещи на заводе изменить нельзя — можно только подстроиться. Вот они.
Первое: нельзя трогать оборудование. У нас нефтехимическое производство. Внесение изменений в конструкцию оборудования, по сути, запрещено. Если это вообще можно сделать, нужно проходить аудиты, и это занимает много месяцев. Поставить датчик уровня или температуры на оборудование — это уже изменение конструкции.
Гораздо проще и дешевле повесить камеру. Камера ничего не трогает, не вмешивается в конструкцию, её можно повесить и убрать, не останавливая производство. Так что камеры у нас не ради моды на нейросети: это единственный способ получить данные с оборудования, не влезая в него.
Второе: сколько серверов есть, столько и есть. Все вычисления идут прямо на заводе, в местной серверной. Специализированных видеокарт для нейросетей там нет, а вынести часть работы в облако не даёт закрытый контур.
Нарастить ресурсы значит закупку, доставку, монтаж, согласования. На это уйдут месяцы и дополнительные деньги. Каждый кадр, который мы берём в обработку, нагружает процессор. Если обрабатывать по максимуму все кадры со всех камер постоянно, ресурсов не хватит.
Из-за закрытого контура я не могу просто зайти на сервер и посмотреть логи своего же сервиса — коллег из бигтеха это удивляет. Доступ есть у инженеров, которые ведут заводы. Если мне нужны логи, я прошу инженера: выгрузи по такому-то сервису, поищи вот такие ключевые слова. Файл прокидывают из контура и присылают мне по почте.
Третье: пять секунд на всё. Если на производстве что-то случилось, через пять секунд оператор уже должен видеть уведомление на экране. Почему именно пять? Столько нужно человеку, чтобы заметить событие и среагировать, даже когда он неотрывно смотрит в экран.
За это время должна успеть вся цепочка: камера отдаёт кадр, модель его распознаёт, система принимает решение и показывает оператору. Отложить кадры в очередь и разобрать позже нельзя — опоздавшее уведомление никому не нужно.
При этом система работает круглосуточно, без выходных, и выключить её на обслуживание нельзя. Все обновления делаем на живую, не останавливая сервис. А если что-то ломается ночью, инженер получает уведомление и подключается удалённо.
В этих рамках мы и двигались от одного узкого места к другому.
Как всё устроено
Чтобы понять, как устроена система, заглянем в операторную. Это помещение на заводе, где сидят технологи и аппаратчики, а перед ними мониторы со всей информацией о производстве, в том числе с картинками камер. На одного оператора может приходиться до сотни камер, у каждой свой участок: где-то конвейер, где-то реактор, а где-то площадка с людьми.
Следить за всеми одновременно физически невозможно. Поэтому наша задача в том, чтобы оператору и не приходилось: система сама определяет, когда какая-то камера требует внимания, и показывает её.

Видеопоток только часть данных. Сюда же стекаются показания всех информационных систем завода.

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

Три шага одинаковы для всех кейсов. А вот моделей машинного зрения уже больше сорока, и под новые задачи разрабатываются новые.
Продукту больше шести лет, я пришёл, когда многое уже было построено. Первые кейсы были устроены просто: одна камера на один сервис. ML-разработчик делал детектор — программу с нейросетью внутри, которая распознаёт на кадрах то, что нужно.
Камера считывала видеопоток, детектор обрабатывал кадры, результат уходил дальше. Если нужно было что-то поменять в настройках, сервис перезапускался целиком, и это никому не мешало: одна камера, быстрый рестарт, всё заново поднялось.
Пока камер было мало, схема работала. Потом заводы распробовали видеоаналитику: кейсов стали десятки, камер сотни, а серверы остались те же. Расти надо, а останавливаться нельзя. Тут мы и упёрлись в первое узкое место.
Когда в кадре 50 человек
Под каждую задачу ML-разработчик делал отдельный детектор, и каждый детектор выполнял всю работу сам, от начала до конца.
Вот конкретный пример. Нужно определить, у кого из сотрудников есть каска и какого она цвета — на производстве это называется контролем СИЗ, средств индивидуальной защиты. Детектор работает в два шага. Сначала находит на кадре всех людей. Потом по очереди смотрит на каждого: есть каска или нет.
Пока в кадре два человека, всё без проблем. А теперь допустим, что в кадре 50 человек. Найти всех разом детектор может, но проверять будет всё равно по одному. Это долго. А у нас пять секунд на всё.
Казалось бы, запусти второй такой же детектор, и пусть каждый проверит по 25 человек. Но детектору нельзя выдать половину работы. Он устроен как монолит: единая программа, которая всегда сама проходит весь цикл, от поиска людей до проверки последней каски. Попросить её «проверь только вот эти 25» невозможно, такой кнопки просто нет. Поэтому второй детектор не разделит работу, а повторит её: снова найдёт все 50 человек и снова проверит всех по одному.
Поэтому мы переделали детекторы: каждый шаг выделили в отдельную маленькую программу. Вместо одной большой, которая делает всё сама, стало несколько простых, и каждая делает одну вещь: один детектор только находит людей, другой только проверяет каски.
Работают они цепочкой. Первый детектор нашёл 50 человек и вырезал из кадра 50 фрагментов, по одному на человека (такие фрагменты называются кропами). Дальше эти кропы можно раздать: 25 одному детектору касок, 25 другому. Они работают параллельно, и время сокращается почти вдвое. С монолитом так было нельзя.
Была и вторая проблема — двойная работа. Допустим, по одной камере надо считать людей, а по второй следить, чтобы все были в касках. Обе задачи начинаются с одного шага: найти человека в кадре. И каждый монолитный детектор делал этот шаг сам, процессор дважды тратился на одно и то же.
Цепочки решили и это. Теперь людей может искать один общий детектор, а результат заберут обе цепочки. Это называется переиспользованием: меньше повторной работы, и на тот же сервер помещается больше камер.
Цепочки детекторов работали быстро, в пять секунд укладывались. Но чтобы один детектор обслуживал две камеры, обе должны работать в одном сервисе. А у нас каждая камера была подключена к своему отдельному сервису, ресурсы дублировались, масштабироваться дальше было некуда. Нужно было объединять.
Когда камер стало 200
На одном заводе может быть до двухсот камер, на каждой свой кейс, иногда несколько кейсов одновременно. Мы объединили камеры в один сервис.
Это сразу дало два выигрыша. Во-первых, переиспользование детекторов заработало в полную силу: цепочки теперь делятся общими звеньями не внутри одного сервиса, а сразу по всем камерам завода. Во-вторых, мы смогли управлять нагрузкой. FPS, то есть количество кадров в секунду, которые мы берём с камеры в обработку, теперь зависит от конкретного кейса.
Допустим, есть колба, в которой нужно определять уровень жидкости. Этот уровень может меняться раз в час. Нет смысла анализировать 30 кадров в секунду, достаточно смотреть раз в минуту или даже раз в десять минут.
Есть отдельный лёгкий детектор, он получает кадр с такой низкой частотой и проверяет: достигла ли жидкость определённого порога? Если нет, продолжаем в том же режиме. Но если достигла, детектор фиксирует событие. Если однотипные события повторяются за короткое время, они складываются в инцидент.
По инциденту камера повышает FPS. Вместо кадра в десять минут смотрим, допустим, три кадра в секунду, и уже второй, более тяжёлый детектор мониторит каждое отклонение.
По сути, двухступенчатая система: дешёвый «наблюдатель», который тратит минимум ресурсов, и тяжёлый «аналитик», который включается только когда есть на что реагировать.
Та же логика работает и шире. Допустим, десять камер на одном сервисе. На пяти прямо сейчас что-то происходит, а на пяти ничего не движется. Те пять, где ничего не происходит, находятся в режиме сна: мы не гоняем по ним тяжёлые модели, а только проверяем наличие движения. Детектор движения почти не потребляет мощности.
Мы решили проблему с ресурсами. Камеры в одном сервисе, детекторы переиспользуются, нагрузка управляемая. И тут к нам пришли инженеры и сказали: мы не можем это использовать.
Когда инженер нажал «сохранить»
Наши инженеры разворачивают систему на заводах и настраивают кейсы под каждую камеру, делают они это через веб-интерфейс.
Камера снимает область на заводе, но нам интересен не весь кадр, а определённый контур. Например, только конвейер, а не проход рядом с ним. Инженер обводит нужный участок в графическом редакторе и нажимает «сохранить». Обведённый контур записывается в конфигурацию, это файл с настройками, по которому работает сервис. А этот файл сервис читает один раз, при запуске. Поэтому применить новый контур можно только одним способом, перезапустить сервис целиком.
Раньше это не было проблемой. На один сервис приходилась одна камера. А теперь камер, допустим, десять, инженер отредактировал настройки одной — и перезапускается весь сервис, все камеры разом. В зависимости от загрузки сервера перезапуск может занимать от двадцати секунд. Все вычисления слетают, и оператор всё это время не видит ничего.
Мы сделали систему с распараллеливанием — цепочки, общий сервис — и она реально работала гораздо эффективнее старой. А использовать её не могли: инженерам по ходу работы надо донастраивать кейсы, и каждая настройка означала перезапуск.
Получился тупик: чтобы экономить ресурсы, камеры должны быть в одном сервисе, а чтобы успевать за пять секунд, нельзя останавливать весь сервис из-за одной настройки.
Суть решения такая. Сервис разбивается на три компонента, это те же три стадии: камера, детектор и постпроцессинг — так мы называем часть, которая превращает результат в действие. Это три изолированные штуки, а над ними контроллер, который ими управляет.
У каждого компонента есть то, что мы называем контекст. Это общее пространство объектов, из которого компонент берёт информацию или кладёт её, чтобы другие могли использовать. Границы контекста чётко очерчены: если его не трогать, можно вносить в компонент любые изменения и не ломать соседей.
Как было: у каждой камеры свой сервис и своя цепочка обработки.

Как стало: менеджер каждого детектора сам регулирует число воркеров по загрузке сервера. На больших кейсах эта схема ускорила обработку в 28 раз.

Раньше логика была такая: случилась ошибка, от которой сложно восстановиться, проще потушить весь сервис и дать ему перезапуститься. Теперь так нельзя, и нам пришлось разделить два сценария. Когда инженер поменял настройки, перезапускается только затронутый компонент. Когда произошёл серьёзный сбой на уровне сервера, перезапускается всё, потому что других вариантов нет.
Как вообще решиться переписывать работающую систему? Помогло то, что откатиться было куда: старая версия никуда не девалась и продолжала работать. Я уточнил у руководителя проекта, не потребуются ли в ближайшее время критические изменения и сколько времени есть на такой эксперимент. Время было — и на несколько месяцев мы приостановили внедрение крупных фичей в этот сервис.
На переписывание сервиса ушло около десяти месяцев. Самой работы, если заниматься только этим, там месяца на три, но параллельно были другие проекты. Но я рад, что мы это сделали: потом возникли кейсы, которые без новой архитектуры было бы либо слишком сложно реализовать, либо вообще невозможно.
Что получилось
Каждое следующее узкое место мы находили, только когда справлялись с предыдущим, всю цепочку заранее не увидишь.
Зато новая архитектура сняла и нашу собственную, видеоаналитиков, боль. Раньше, если один разработчик что-то менял, второму приходилось переделывать свою задачу. Теперь каждый работает в своём компоненте и никому не мешает.
Подписывайтесь на наш тг-канал. Он полезен айтишникам, которые хотят понять, что реально происходит в промышленном ИТ.
Там мы рассказываем о цифровых технологиях для производства — от IIoT и аналитики до инженерных инструментов и ИИ. Делимся кейсами, экспериментами, новостями и выкладываем вакансии.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.