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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

"Пока суть да дело - лето пролетело."

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

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

Комментарии (27)


  1. vrangel
    13.09.2022 20:03
    +1

    Такая штука была бы полезна на гидросамолетах. Посадка с подбором для них нормальное явление, а на неподготовленных водоемах препядствия - основная проблема.


    1. tolianT Автор
      13.09.2022 20:05

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


  1. iliasam
    13.09.2022 22:13
    +1

    Не пробовали устанавливать на камеру поляризационный светофильтр?


    1. tolianT Автор
      13.09.2022 22:22

      Нет. Такого фильтра у меня нет. Вы имеете в виду, что-то вроде стёкла темных поляризационных очков? Могу только предположить, что нужный эффект не дадут: плавая на лодке в таких очках, вы все равно будете видеть рябь на воде. А математический фильтр работает с черно-белым изображением и его градиентами. Причём области градиентов можете задавать самим. Не каждый параметр степени градиента даёт нужный результат.


      1. Meklon
        13.09.2022 22:30
        +3

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


        1. tolianT Автор
          13.09.2022 22:33

          Понял. Надо экспериментировать дальше значит.


          1. Meklon
            13.09.2022 23:40
            +1

            Обычно программная фильтрация должна начинаться там, где мы уже исчерпали все возможности аппаратной. Так как мы не знаем заранее угол поляризации, то, скорее всего будет оптимально выставить угол на что-то промежуточное.


      1. iliasam
        13.09.2022 22:34
        +1

        Вот о чем речь: club.dns-shop.ru/blog/t-155-drugie-fototovaryi/24047-polyarizatsionnyie-filtryi-v-fotografii-praktika-primeneniya
        Возможно, различные переотражения и блики будут меньше мешать.


        1. tolianT Автор
          13.09.2022 22:38

          Понял о чем речь. У меня так бывает, упрусь в один какой-то аспект и упускаю другие варианты. Спасибо!


  1. Meklon
    13.09.2022 22:29
    +1

    Рад, что что-то из мыслей пригодилось.


    1. tolianT Автор
      13.09.2022 22:31

      Рад вас снова видеть! :)


  1. Meklon
    13.09.2022 23:41
    +1

    Deleted


    1. tolianT Автор
      13.09.2022 23:46

      Я правильно понимаю, что при некоторых углах поворота можем получить обратный эффект? Помехи останутся, а полезная информация скроется? Как фильтр и экран телефона, к примеру? Ещё, как по вашему, нужно менять угол фильтра если мы плыли и солнце было справа, а обратно - солнце слева?


      1. DmitriiR
        14.09.2022 04:05
        +1

        Скроются только блики


        1. tolianT Автор
          14.09.2022 08:43

          Интересно. Проверим. :)


      1. Meklon
        14.09.2022 23:19
        +1

        Нет. В худшем случае будет нулевое подавление блика. Если плоскость поляризации повернуть на 45°, то в среднем будет двукратное подавление.


        1. tolianT Автор
          14.09.2022 23:23

          Звучит здорово. Я уже почитал про фильтры и заказал на али CPL фильтр от GoPRO. Надеюсь поможет. Спасибо!


  1. Userpc0101
    14.09.2022 11:17

    А вы не думали над развитием идеи ухода от препяствий и применением камер глубины для построения воксельных карт окружающего простраства и используемых в них алгоритмах A*, D* lite?


    1. tolianT Автор
      14.09.2022 11:20

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


      1. Userpc0101
        14.09.2022 11:37

        Почему для измерения ёмкости аккумулятора не использовали шунт измеряющий падения напряжения для расчёта и интегрирования проходящнго через батарею тока?


        1. tolianT Автор
          14.09.2022 11:42

          Не умею просто. Я же программист по профессии. :) Шунт же тоже как-то надо к raspberry подключать. АЦП надо для него, я не уверен?

          Я старался сразу одним АЦП решить свою проблему.


          1. Userpc0101
            14.09.2022 11:54

            Для модельных автопилотов (pixhawk) обычно применяют именно этот вариант измерения ёмкости т.к. он довольно точный. Нужно измерять падение напряжения на шунте и зная его сопративление по закону Ома можно расчитать ток идущий через провод. А как ваша система ухода от препяствий будет работать на самолёте или колёсном дроне?


            1. tolianT Автор
              14.09.2022 12:07
              +1

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

              Сам алгоритм находит грани объектов и может применяться на других платформах. Я дополнил его возможностью адаптивной смены параметров(при множественных шумах снижаю чувствительность, если условия лучше - чувствительность повышается). Можно поставить на радиоуправляемую машинку, я катал катер на подставке по полу: препятствия видит, от собаки уворачивается. :) это если на плоскости.

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


  1. LevOrdabesov
    15.09.2022 11:17
    +1

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


    1. tolianT Автор
      15.09.2022 11:23
      +1

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

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

      Сейчас мне мешает «рыбий глаз» камеры. Можно заметить, где искажение больше, там шумы выше, они хуже поддаются фильтрации. Буду брать камеру без fish eye или исправлять картинку соответсвующим алгоритмом.


      1. Userpc0101
        15.09.2022 21:17
        +1

        В OpenCV есть встроенные алгоритмы калибровки камеры обычной и fish eye, с помощью asymmetric circle grid или chess board для получения коэффицентов дисторсии камеры с их помощью изображение с камеры можно исправить. Использование объективов без искажения хоть и уменьшает дисторсию но не избавляет от неё и в случае использования изображений для камеры глубины, калибровка небходима в любом случае. Вы также можете использовать для калибровки приложение matlab получить готовые коэффиценты которые ИМХО точнее метода калибровки OpenCV (для CircleGrid) и в дальнейшем использовать их в функции undistor для исправления изображения от камеры.


        1. tolianT Автор
          15.09.2022 22:36

          Да, все верно. Собирался калибровать шашечками как раз.

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