Comments 71
По сути, у нас два пути — пытаться выделить объект в Lightness канале или в Hue. Второй даст неплохой эффект для пакетов и всякого яркого мусора. А вот с зеленоватыми корягами непонятно что делать.
В инфракрасном спектре не пробовал смотреть? Может быть существенная разница в поглощении поверхностью, что даст нужный контраст.
Наверное эта проблема может быть решена в купе с использованием мини эхолота.
Думал об этом, но увидит ли эхолот пакет на поверхности воды? На данном этапе актуально обнаружить видимые глазу препятствия. Скрытые препятствия это уже отдельная тема.
Да, пакет на поверхности, не факт, но мне кажется, если подкрутить чувствительность, то заросли травы должны быть видны при колебании воды. А как дела обстоят с использованием лазерного луча или ультразвука на поверхности воды?
"Островок" растительности хорошо различим визуально, по опыту испытаний могу сказать.
Лазерные и ультразвуковые дальномеры первое что пришло мне в голову, я же не собирался влазить во все эти проблемы технического зрения. Но не забывайте, мы на воде, а катер постоянно раскачивает на волнах. Ультразвук и лазер будут отражаться от волн на воде.
Вы не забывайте, что вопрос автономности тоже важен для дрона. У нас только одной проблемы нет в случае с беспилотным катером - отвод тепла. :)
Возможно, вас могло ввести в заблуждение видео с камеры GoPro. Она установлена слишком низко, на самом корпусе катера. Я планирую подключить камеру к самой Raspberry Pi и установить значительно выше, что "отодвинет" горизонт и даст возможность замечать препятствия намного раньше, а заодно уменьшить число помех от водяных капель.
Мне нравится ваша идея задействовать инфракрасный спектр, что может быть особенно полезно в сумерках. Пока же, хочу обнаруживать препятствия в видимом диапазоне: если препятствие видит человек, то должен увидеть катер.
Отдельно спасибо за ваш развернутый комментарий на мою первую статью!
В итоге, камера в видимом спектре и камера в ИК, которая дёргает кадры с низким фреймрейтом синхронно со вспышками прожектора. Это даст экономию энергии.
А может быть над катером будет летать дрон. Он будет лучше видеть панораму. Разведчик.
Конечно, крупные препятствия он увидит раньше. Но сразу снижается автономность, отказоустойчивость всего комплекса в сумме, чувствительность к погодным условиям(дождь, ветер)...
На катер можно поставить солнечные панели, с квадракоптером это проблема.
Катер может отплывать на значительные расстояния: десятки километров. Квадрокоптер привязан к оператору и дальности приёма сигнала.
У меня есть ссылка на видео в начале статьи, снимал ракурсы с квадрика как раз. У катера был значительный запас хода, а квадрик уже терял сигнал.
Детектирование оптического потока происходит (условно) при опоре частотного фильтра (детектора контуров и пятен) на несколько кадров или точек обзора (чтобы было понятно, куда сместилась граница). Цвета-оттенки там не особо нужны, навигационные алгоритмы человеков и роботов опираются на более абстрактные статистические характеристики движущейся картинки (что-то типа "движение плотности энтропии"). В общем, задачу нужно решать (гуглить) где-то вокруг этого словосочетания - Оптический Поток :).
Да, то что надо! Интересно, что я интуитивно решал эту же задачу по нахождению оптического потока :)
Гауссовское размытие и весовые коэффициенты у меня как раз используются!
Возможно, получится даже улучшить мой код теперь.
Тогда подскажу ещё одно словосочетание, которое, возможно, пригодится - Фильтр Калмана (хотя велика вероятность, что словосочетание и без меня известное :)). Я сварщик ненастоящий, моделек с компьютерным зрением сам не строил, но навскидку кажется, что при использовании в управляющей цепи этого фильтра с соответствующими параметрами можно будет даже выбросить этап стабилизации картинки (вся раскачка входных данных усреднится этим фильтром).
Очень интересно. А говорите ненастоящий сварщик. :) Возможно, быстрее меня бы построили. Я только открываю для себя все эти алгоритмы.
Оказывается есть такой интересный инструментарий, неужели никто не реализовывал их на практике(в области компьютерного зрения: обнаружения и трекинга)? Или просто не публиковали результаты?
Большое спасибо!
Ещё раз перечитал комментарии. :)
По моим внутренним ощущениям, фундаментальная проблема пока одна: мы не знаем исходных размеров препятствия, а значит не можем определить расстояние до него. А это было бы крайне полезно. На те объекты, что ближе, реагировать надо быстрее, расставлять приоритеты при маневрировании между ними.
С откалиброванной камерой должно быть можно расчитать расстояние до точки из вектора перемещения и поворота камеры и перемещения точки на изображении.
С откалиброванной стереопарой это можно было бы делать более надёжно, без необходимости знать собственное перемещение, по одному кадру. Тем более у вас стерео можно существенно облегчить, считая его только для препятствий.
P.S. Если решите экспериментировать со стерео — учтите, что камеры должны поддерживать синхронную съёмку.
Верно, нужно калибровать. Если камеры различные или находятся на разном уровне, то нужно вводить параметры.
На практике, погрешности просто дикие. При разрешении 640x480, чем ближе к линии горизонта, тем больше метров(десятков и даже сотен метров) на пиксель.
Если камеры различные или находятся на разном уровне, то нужно вводить параметры.
Даже у одной модели камеры параметры могут плавать, и идеально на одном уровне под точным прямым углом их установить невозможно, так что параметры всегда одинаковые, и их все можно откалибровать через calibrateCamera для одной или stereoCalibrate для системы из двух камер.
На практике, погрешности просто дикие. При разрешении 640x480, чем ближе к линии горизонта, тем больше метров(десятков и даже сотен метров) на пиксель.
Величина погрешности пропорциональна расстоянию, да. А на более близких препятствиях приемлемой точности не выйдет?
На близких расстояниях уже не успеваю среагировать. В моём примере камера слишком низко расположена: если препятствие далеко - погрешности большие, если близко - уже поздно маневрировать. Надо камеру выносить выше и угол настраивать, чтобы на экране было максимум полезной площади. Вот беда, не сезон сейчас, могу только теоретически предполагать.
Чем быстрее увеличивается размер препятствия, тем он ближе (при предположении статичности препятствий и их касания воды и известной или фиксированной скорости катера). Зная скорость катера по двум последовательным фотографиям можно вычислить и расстояние до препятствия (или время до столкновения).
Возможно, на картинке с камеры нужно будет выделить две линии, уходящие в горизонт, обозначающие "безопасный коридор" для катера и вертеть катер так, чтобы препятствия успевали "убираться" за эти линии (типа как на камерах парктроника :)). Можно даже сразу по 10 линий с каждой стороны провести, от самых узких "опасных", до самых широких безопасных. В зависимости от пересечения препятсвия соответствующей линией (возникновения "неправильного" оптического потока на этой линии, не соответствующего "наезду на воду") принимать решение о крутости поворота (самые близкие к центру линии должны сильнее заворачивать руль от препятствия).
Интересно...
А что будет быстрее увеличиваться: большое препятствие или малое?
Например, спичечный коробок или огромный лайнер. Как можно посчитать скорость сближения? Для простоты примем нашу скорость за 0. Пусть препятствие на нас движется. Вот этот момент меня смущает. Мы же не знаем размер объекта на горизонте. Почему он увеличивается на экране быстрее: он крупный или быстрый?
Линейное наращивание размеров проекции будет одинаковым у препятствий любых размеров (потренируйтесь на листике в клеточку). Но, в целом, все эти промежуточные рассчёты не нужны, предлагаю просто разделить экран на чувствительные зоны на манер парктроника, только вместо писка при пересечении оптическим потоком этих линий вертеть рулём.
Типо головка самонаведения, только отведения в этом случае.
Да, можно обучить голубя, клюющего препятствие на картинке :).
Я как раз упражнялся с этим. У меня другие результаты получались с размерами. Представьте плывущую баржу и бутылку рядом с ней. На горизонте баржа будет в виде пикселя 1x1, бутылку не видно ещё: 0x0
Теперь мы сблизились с ними максимально, скорость по отношению к ним у нас одна и та же. Баржа занимает весь экран: 640x480, бутылка пусть например: 4x5
Размер в проекции экрана нарастал нелинейно, или я вас неправильно понял?
Но, я с вами согласен, что можно делить экран на зоны, только я ещё вектор сближения хотел учитывать: пересекает он корпус катера или пройдёт мимо.
И ещё было упражнение у меня такое. Разместил камеру на высоте корпуса катера, а перед ней рулетку растянул и сделал фото. И результат был, что-то вроде такого: первые 50-60 см хорошо укладываются в пиксели, 1-1,5 м ещё туда-сюда, все что свыше уже сливается в одну линию на экране.
Гуглится что-то подобное:
https://razbotics.wordpress.com/2019/12/17/optical-flow-based-navigation-using-picam/amp/
Не знаю, конкретно в этой ссылке большая ли проблема заменить вертикальное движение на горизонтальное, но набор решаемых проблем, кажется, "ваш". Гуглить по этим ключевым словам.
Ага. Видел подобную статью, там с самолетом и камерой для определения скорости относительно земли, зная его высоту. К сожалению, не понял как мне это можно использовать. Если бы у меня камера висела на известной высоте, и на экране был катер и искомый объект, то задача решается просто. А у нас камера на катере в плоскости земли пишет. Другая картина получается.
Мне нравится с вами дискутировать, вижу, что здорово разбираетесь в вопросе.
Вы стремитесь решить задачу восстановления 3Д-сцены перед катером по картинке с одной камеры в общем виде, это серьёзная задача, но она для управления катером, кажется, не требуется. Кажется, достаточно просто разметить в картинке с камеры "на воде" пару зон, появление объектов в которых (не важно, на каком расстоянии от камеры, главное, что они попали в проекцию) будет вызывать отклонение руля в противоположную сторону. Если же вы хотите, чтобы автопилот принимал более серьёзные решения (например, по изображению заранее планировал маршруты объезда препятстви, восстанавливал курс после объезда, следовал за объектами и т.д.), то, наверное, придётся лезть в нервосетки. Вот к примеру: https://github.com/gengshan-y/expansion . Но тут уже возникнет другой вопрос - как обработать эти полученные 3Д-данные, как превратить их таки в управляющие (и, вероятно, вы поверх всей этой так сложно восстановленной 3Д-сцены проведёте те самые пару полосок, и получите ту же самую схему "парктроника").
Тут сложно уже на словах прикинуть, какая схема сработает и насколько хорошо, надо пробовать, экспериментировать, подтюнивать и подшаманивать. И прочувствовать боль Илона Маска с его Теслой, который не за один год прошёл путь от лидаров до "голых" камер в своём автопилоте, и не одну тыщу километров накатал для обучения всего этого :).
Честно говоря, именно это я пытался сделать изначально: построить 3д сцену. Искал характеристики камеры, вводил near, far, FOV...
Все что смог посчитать: угол. Понял, что с одной камерой больше не получится ничего сделать. Хотя мне очень, очень хотелось узнать расстояние и скорость объекта на экране.
В результате, пришёл к таким же выводам: задача компромиссная, буду рисовать границы приближающегося объекта и избегать их. Это уже значительно повысит "живучесть" дрона во время движения по маршруту.
Вообще, ваша аналогия с парктроником очень точная.
Ещё я понял, что скорости объектов мне не особо и нужны. Испытываю катер я в безлюдном месте, что логично для механизма, который в любой момент может стать неуправляемым. Препятствия или находятся на месте(растительность) или являются тихоходными (дрейфуют по течению). Тут по аналогии с мотоциклистом в потоке машин, когда он, фактически принимает их за стоячие, несмотря на то, что они все-таки движутся.
Безумно интересно узнать о дальнейших развития этого проекта.
www.sciencedirect.com/science/article/pii/S1350449519300465
![image](https://habrastorage.org/getpro/habr/comment_images/d29/5ba/95b/d295ba95ba8fd907e674fbd20af23e9d.jpg)
Спасибо. Нормальная такая статья. Тоже обратите внимание, с чб изображением работают.
Само по себе определение препятствий у меня уже работает. Отдельно был вопрос оптимизации, алгоритм должен быть шустрым.
Тоже читал разные статьи. Вот по определению линии горизонта только 3-4 солидных таких же видел. На практике они не сработали. При одном ракурсе камеры есть горизонт, на другом уже не видит.
Все верно, именно так и будет.
Но пока катер стоит "на приколе" нужно с чем-то работать. Пока горизонт получаю из визуальной картинки. Кстати, это отдельная интересная задачка. Все найденные мной алгоритмы, лажали с определением. :/ не хочу хвастаться, у меня уверенно определяет горизонт даже в условиях водных брызг и частичной видимости.
Про производительность:
Какое расширение видео использовали?
Какую модель Raspberry pi?
Если собирали библиотеку сами, то можно было при сборке включить использование openMP — библиотеку распараллеливания.
Попробуйте написать на C++. Там использование функций и классов openCV почти такое же, но есть возможность скомпилировать с максимальной оптимизацией.
Благодарю! Не думал, что такая специфичная область заинтересует столько людей. Хотя вот меня затянула чуть больше чем полностью. :)
Если интересно, именно по запуску катера, можете посмотреть мой же видео отчет: https://m.youtube.com/watch?v=5ZUPO3FEQQ0
Это не реклама, канал без монетизации, чисто любительский. В конце видео есть подбивка: около 300$ весь проект. При том, что вы можете снять Raspberry Pi и у вас снова будет та же самая игрушка из магазина.
Тоже были сомнения, получится ли детектировать препятствия. Но... пока получается. :) Raspberry Pi 4 достаточно мощный девайс, а библиотека OpenCV неплохо оптимизирована.
Но в любом случае, или все получится, или провалится. И я напишу по какой причине не получилось. :)
Солидарен с вами, читать удобнее. Так уж получилось, что сначала это была просто rc игрушка, потом подключил raspberry только из любопытства: разобраться с управлением. Камеру поставил, опять же из любопытства, посмотреть "глазами" капитана этого судна. :) дальше решил научиться монтировать видео, чтобы оставить его себе на память.
Писать статью про запуск катера с raspberry мне показалось неуместным, именно потому, что, как вы пишите, роботомашинки набили всем оскомину. Полностью поддерживаю.
А вот детектирование абстрактных объектов на пути и их отслеживание, та тема по которой мало материала или вообще отсутствует. И так появилась эта дебютная статья. Вдруг в этом сезоне получится реализовать задумку и не потерять катер.
Советами не пренебрегаю, за все идеи читателям благодарен! Значит не зря писал. А все комментарии мотивируют довести дело до конца, появилась ответственность перед вами.
По идее достаточно отделить «шум» на поверхности воды и трекать его.
Интересно как в итоге вы решите задачу.
В список задач нужно еще один пункт добавить, коррекцию сферических искажений. а то горизонт дугой изгибается, рано или поздно этот фактор начнет критически влияеть на результат.
Вот попалась статья, наглядно показывает о чем речь.
https://habr.com/ru/post/341160/
Горизонт я бы искал с помощью преобразования Хафа. По факту гироскопы дают дрейф. Результаты с них можно объединить.
Для всего что ниже горизонта можно сделать нормализацию. Возможно нелинейную.
Определение мусора. Пробегаемся граф-сегментатором. Например таким
https://www.cc.gatech.edu/cpl/projects/videosegmentation/
Граф-сегментаторы очень хорошо реагируют на трешхолд.
Пробуем определить вектор движения сегмента и его размер. Или используем более сложные ии классификаторы.
Что бы не гонять классификатор на каждом фрейме используем оптимизацию на подобее описаной в моем патенте https://patents.google.com/patent/US9002056B2 но с учётом того что мы движемся в 3D пространстве.
Если не хватает производительности, смело уменьшайте разрешение для тяжёлых участков. Вплоть до 320х240. На такой скорости фреймрейт важне.
Спасибо. Дайте время изучить.
Пока могу сказать по предварительным результатам:
1. фрейм рейт действительно важен
2. камеру необходимо поднять выше над корпусом судна, чтобы раньше замечать препятствия и отстроиться от волн( в плоскости горизонта они мешают сильнее, чем если смотрим на волную поверхность сверху).
Классификаторов у меня нет, я ищу абстрактные препятствия. Просто любой объект, больше некоторого предела "опасности" что ли...
В камере за оббъективом должен стоять ИК фильтр.
Можно его снять (если он не на метрице конечно) и открыть совсем иные картинки.
Кстати было Красим беззеркалку в инфракрасный цвет / Хабр (habr.com)
Спасибо за идею!
В первой версии будет стоять самая обычная камера для raspberry pi:
![](https://habrastorage.org/getpro/habr/upload_files/296/7f7/30b/2967f730b3894aa6e94ddc928e53f456.jpeg)
Не совсем понял как за объективом поставить? Или с такой не получится?
Фильтр между объективом и матрицей.
Поковыряйте.. )
А, понял. Фильтр уже стоит, его надо снять. Камеру жалко скальпировать, она у меня одна :/ а руки - крюки...
Надо запасную завести, чтобы не жалко испортить.
Ещё, кстати, забыл написать про возможность использовать стерео пару ( 2 камеры сразу) Она может дать глубину всей сцены. Видел, правда, примеры, выглядели они, мягко говоря, убого. Вряд ли получится точно определять расстояние до объекта.
А не могли бы вы поделиться исходниками к данной статье?!
Код на python для "посвечивания" объектов:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 100, 300)
dilated = cv2.dilate(edges, np.ones((2, 2), 'uint8'), iterations=2)
contours, hierarchy = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
for cnt in contours:
cv2.drawContours(frame, [cnt], -1, (0, 255, 0), 1)
frame это картинка, которая может быть текущим фреймом вашего видео или просто статичной картинкой
Полный код с трекингом выложу чуть позже, планирую его переработать с учетом замечаний и предложений, которые были предложены в комментариях.
Обнаружение препятствий на OpenCV