Обнаружение препятствий на OpenCV. Часть 2

С момента последней статьи прошел почти год. Спасибо читателям за комментарии, они здорово помогли, отдельная благодарность @Meklonза идею с фильтрами и в целом за участие в дискуссии. Сама эта идея за весь период времени из головы благополучно вылетела, но видимо не совсем. :) Об этом чуть позже.

Произошло немало событий, времени на мое хобби с автономным катером нашлось откровенно мало. :/

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

Аппаратная часть.

Цены уползли вверх и теперь я не могу позволить легкомысленно утопить аппаратуру катера. Как я рассуждал раньше: «Ну что там Raspberry Pi и несколько датчиков. Всегда можно взять новую «малинку», восстановить образ из бэкапа и продолжить испытания.»

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

Поэтому, я спроектировал и распечатал на 3d принтере новый герметичный корпус с аккумуляторным отсеком.

Герметичный бокс для электронной начинки.Герметичный бокс для электронной начинки.

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

Начало сборки новой конфигурации катера.Начало сборки новой конфигурации катера.

Трудно не заметить — на катере появилась камера на мачте. Этому есть объяснение: чем выше точка обзора, тем раньше мы сможем увидеть препятствие, а значит у нас будет больше времени для принятия решения. Другими словами — мы отодвигаем границу «видимого горизонта».

Картинка из Википедии.Картинка из Википедии.

После сборки получаем новую компоновку:

Катер с новой компоновкой.Катер с новой компоновкой.

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

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

Сравните размеры штатного водозаборника и нового пластикового.Сравните размеры штатного водозаборника и нового пластикового.

Программная часть — самое простое! …или нет?

Уже потираю руки — аппаратура надежно защищена, алгоритм давно придуман и проверен!

Меня напрягало пользоваться окошком терминала для запуска программы автопилота и контроля параметров беспилотника. А раз добавили камеру — логично набросать веб-интерфейс, чтобы следить за испытаниями в реальном времени.

Слева - было, справа - стало.Слева — было, справа — стало.

Включаем, понеслось…

Это просто ад какой-то!

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

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

Вывод: ничего не получилось! …или нет?

Я продел немалую работу: спроектировал и собрал техничку, провел тюнинг игрушечного катера, допилил ПО и все для того, чтобы столкнуться с фундаментальной проблемой — отражения на воде.

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

Так я видел работу автопилота изначально.Так я видел работу автопилота изначально.

Ну не получилось и не получилось, не может отличить и что ж теперь? В лепешку расшибиться?! Зато я весело провел время!

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

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

С чистого листа.

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

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

У меня уже накопилось достаточно видеоматериала с испытаний, чтобы эмпирически попытаться получить удовлетворительный результат.

Во время изысканий, настоящим откровением стал «фильтр Собеля». Метод находит градиент каждого пикселя (или заданной области пикселей). Причем направление градиента можно выбирать. Нашел я его во время опытов и только потом узнал, что он используется как простейший метод нахождения края объекта.

Пример фильтра Собеля из ВикипедииПример фильтра Собеля из Википедии

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

Сравнение старого и нового метода обнаружения препятствий:

Данный метод показал хорошие результаты и в более сложных условиях. Там где алгоритм Canny Edges попросту сходит с ума и видит практически непрерывное препятствие, фильтр Собеля успешно отстраивается от большинства помех.

Canny Edges слева, Sobel справаCanny Edges слева, Sobel справа

А как на практике?

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

Погонял автопилот на других видео и убедился, что алгоритм отлично справляется с нашей задачей.

«Пока суть да дело — лето пролетело.»

Лезть в холодную р.Волгу уже не так охота как при +30°, а значит снова придется ждать лета! Остается надеяться, что сюрпризов больше не будет и я смогу представить вам полный обзор самостоятельного путешествия катера с автопилотом и компьютерным зрением на Raspberry Pi.

Спасибо, что прочитали статью!

© Habrahabr.ru