Создание автономных машин — популярная нынче тема и много интересного тут происходит на любительском уровне.
Самым старым и известным курсом была онлайн-степень от Udacity.
Итак, в автономных машинах есть очень модный подход — Behavioral Cloning, суть которого заключается в том, что компьютер учится вести себя как человек (за рулем), опираясь только на записанные входные и выходные данные. Грубо говоря, есть база картинок с камеры и соотвествующий им угол поворота руля.
В теории, обучив на этих данных нейросеть, мы можем дать ей порулить машиной.
Этот подход базируется на статье от Nvidia.
Существует множество реализаций, сделанных в основном студентами Udacity:
Еще более интересно применение в реальных проектах. Например, машинка Donkey Car управляется специально обученной нейросетью.
Такая насыщенная инфосфера прямо подталкивает в действиям, тем более, что мой робот-танк со времени предыдущей статьи зашел в некоторый тупик в своем развитии, и ему срочно требовались свежие идеи. Была смелая мечта — прогуляться по парку со своим танком, который, в общем-то ничем не хуже домашней собаки. Дело за малым — научить танк ездить по тротуару в парке.
Итак, что такое тротуар с точки зрения компьютера?
Некоторая область на картинке, которая отличается цветом от других областей.
Так сложилось, что в доступных мне парках тротуар оказывался наиболее серым объектом на картинке.
(Под наиболее серым имеется в виду минимальная разница между значениями RGB). Это свойство серого и будет ключевым при распознавании тротуара.
Еще одним важным параметром серого является яркость. Осенние фотографии состоят из серого чуть менее чем полностью, так что отличия дороги от обочины лишь в оттенках.
Пара самых очевидных подходов заключаются в предварительной калибровке — выставить робота так, чтобы дорога занимала большую часть экрана и
Установив такие критерии распознавания тротуара, пробегаем по картинке и получаем какое-никакое очертание дороги.
Следующим шагом надо превратить аляповатое пятно в действия — ехать прямо или повернуть направо или налево.
Прямо мы едем, если правая кромка видна и угол меньше 45 градусов от вертикали.
Налево поворачиваем, если правая кромка видна и угол отклоняется от вертикали вниз.
Направо поворачиваем, если не видим правой кромки.
Правая кромка аляповатого пятна — с помощью геометрии решать эту задачу довольно нерадостно. Пусть лучше искусственный разум ищет закономерности наклона в этих обрывках.
Вот тут то и приходят на помощь нейросети.
Оригинальные картинки размываем, сжимаем и обрезаем, выделяем распознаем серый тротуар и получаем черно-белые маски 64x64.
Эти маски раскладываем на 3 кучки — Left, Right, Straight и обучаем на них классификатор нейросети.
Сбор и подготовка данных — нуднейшая задача, на это ушла пара месяцев.
Вот образцы масок:
Налево:
Направо:
Прямо:
Для работы с нейросетью я использовал Keras + Tensorflow.
Поначалу была идея взять структуру нейросети от Nvidia, но, она очевидно, предназначена для несколько других задач и с классификацией справляется не очень. В итоге оказалось, что простейшая нейросеть из любого туториала про multi-category classification дает вполне приемлемые результаты.
Обучив первую версию сети, я уперся в ее несовместимость с Raspberry Pi. До этого я использовал Tensorflow версии 1.1, с помощью шаманства собранную одним очень умным человеком.
К сожалению, эта версия устарела и не могла читать модели из Keras.
Однако недавно люди из Гугла наконец-то снизошли и собрали TF под Raspberry Pi, правда под новую версию Raspbian — Stretch. Stretch был всем хорош, но год назад у меня под него не собрался OpenCV, поэтому танк ездил на Jessie.
Теперь же под давлением перемен пришлось переходить на Stretch. Tensorflow встал без проблем (хоть и заняло это несколько часов). OpenCV за год тоже не стоял на месте и уже вышла версия 4.0. Вот ее и удалось собрать под Stretch, так что препятствий для миграции уже не осталось.
Были сомнения, как Raspberry потянет в реалтайме такого монстра как Tensorflow, но все оказалось в целом приемлемо — несмотря на начальную загрузку сети порядка нескольких секунд, сама классификация способна отрабатывать несколько раз в секунду без значительного отжора памяти и CPU.
По итогу — большинство проблем и ошибок случаются именно на этапе распознавания дороги.
Нейросеть же промахивается очень редко, несмотря на простоту структуры.
С обновленной прошивкой танк рассекает по парку.
Вследствие перенесенных травм, робота постоянно сносит направо, так что без искуственного интеллекта он быстро уезжает на газон.
Можно теперь его выгуливать по утрам и детектировать встречных собак.
Ссылки:
Самым старым и известным курсом была онлайн-степень от Udacity.
Итак, в автономных машинах есть очень модный подход — Behavioral Cloning, суть которого заключается в том, что компьютер учится вести себя как человек (за рулем), опираясь только на записанные входные и выходные данные. Грубо говоря, есть база картинок с камеры и соотвествующий им угол поворота руля.
В теории, обучив на этих данных нейросеть, мы можем дать ей порулить машиной.
Этот подход базируется на статье от Nvidia.
Существует множество реализаций, сделанных в основном студентами Udacity:
Еще более интересно применение в реальных проектах. Например, машинка Donkey Car управляется специально обученной нейросетью.
Такая насыщенная инфосфера прямо подталкивает в действиям, тем более, что мой робот-танк со времени предыдущей статьи зашел в некоторый тупик в своем развитии, и ему срочно требовались свежие идеи. Была смелая мечта — прогуляться по парку со своим танком, который, в общем-то ничем не хуже домашней собаки. Дело за малым — научить танк ездить по тротуару в парке.
Итак, что такое тротуар с точки зрения компьютера?
Некоторая область на картинке, которая отличается цветом от других областей.
Так сложилось, что в доступных мне парках тротуар оказывался наиболее серым объектом на картинке.
(Под наиболее серым имеется в виду минимальная разница между значениями RGB). Это свойство серого и будет ключевым при распознавании тротуара.
Еще одним важным параметром серого является яркость. Осенние фотографии состоят из серого чуть менее чем полностью, так что отличия дороги от обочины лишь в оттенках.
Пара самых очевидных подходов заключаются в предварительной калибровке — выставить робота так, чтобы дорога занимала большую часть экрана и
- взять среднюю яркость (в формате HSV)
- или средний RGB кусочка, гарантированно состоящего из дороги (в таком случае это будет левый нижний угол).
Установив такие критерии распознавания тротуара, пробегаем по картинке и получаем какое-никакое очертание дороги.
Следующим шагом надо превратить аляповатое пятно в действия — ехать прямо или повернуть направо или налево.
Прямо мы едем, если правая кромка видна и угол меньше 45 градусов от вертикали.
Налево поворачиваем, если правая кромка видна и угол отклоняется от вертикали вниз.
Направо поворачиваем, если не видим правой кромки.
Правая кромка аляповатого пятна — с помощью геометрии решать эту задачу довольно нерадостно. Пусть лучше искусственный разум ищет закономерности наклона в этих обрывках.
Вот тут то и приходят на помощь нейросети.
Оригинальные картинки размываем, сжимаем и обрезаем, выделяем распознаем серый тротуар и получаем черно-белые маски 64x64.
Эти маски раскладываем на 3 кучки — Left, Right, Straight и обучаем на них классификатор нейросети.
Сбор и подготовка данных — нуднейшая задача, на это ушла пара месяцев.
Вот образцы масок:
Налево:
Направо:
Прямо:
Для работы с нейросетью я использовал Keras + Tensorflow.
Поначалу была идея взять структуру нейросети от Nvidia, но, она очевидно, предназначена для несколько других задач и с классификацией справляется не очень. В итоге оказалось, что простейшая нейросеть из любого туториала про multi-category classification дает вполне приемлемые результаты.
model = Sequential()
activation = "relu"
model.add(Conv2D(20, 5, padding="same", input_shape=input_shape))
model.add(Activation(activation))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Conv2D(50, 5, padding="same"))
model.add(Activation(activation))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Flatten())
model.add(Dense(500))
model.add(Activation(activation))
model.add(Dense(cls_n))
opt = SGD(lr=0.01)
model.add(Activation("softmax"))
model.compile(loss="categorical_crossentropy", optimizer=opt, metrics=["accuracy"])
Обучив первую версию сети, я уперся в ее несовместимость с Raspberry Pi. До этого я использовал Tensorflow версии 1.1, с помощью шаманства собранную одним очень умным человеком.
К сожалению, эта версия устарела и не могла читать модели из Keras.
Однако недавно люди из Гугла наконец-то снизошли и собрали TF под Raspberry Pi, правда под новую версию Raspbian — Stretch. Stretch был всем хорош, но год назад у меня под него не собрался OpenCV, поэтому танк ездил на Jessie.
Теперь же под давлением перемен пришлось переходить на Stretch. Tensorflow встал без проблем (хоть и заняло это несколько часов). OpenCV за год тоже не стоял на месте и уже вышла версия 4.0. Вот ее и удалось собрать под Stretch, так что препятствий для миграции уже не осталось.
Были сомнения, как Raspberry потянет в реалтайме такого монстра как Tensorflow, но все оказалось в целом приемлемо — несмотря на начальную загрузку сети порядка нескольких секунд, сама классификация способна отрабатывать несколько раз в секунду без значительного отжора памяти и CPU.
По итогу — большинство проблем и ошибок случаются именно на этапе распознавания дороги.
Нейросеть же промахивается очень редко, несмотря на простоту структуры.
С обновленной прошивкой танк рассекает по парку.
Вследствие перенесенных травм, робота постоянно сносит направо, так что без искуственного интеллекта он быстро уезжает на газон.
Можно теперь его выгуливать по утрам и детектировать встречных собак.
Ссылки:
Комментарии (22)
dkurt
12.02.2019 22:06Не пробовали запускать сеть через OpenCV?
Stantin Автор
12.02.2019 23:53Что вы имеете в виду? Распознать дорогу какой то уже обученной сетью?
lakroft
13.02.2019 06:37+1Предполагаю, речь про поддержку нейросетей в OpenCV.
Stantin Автор
13.02.2019 07:03Я понимаю. Но какую задачу решать с помощью нейросети в контексте статьи?
Сама возможность использовать готовую нейросеть в OpenCV конечно есть, в самой первой своей статье я так делал, чтобы детектировать предметы в комнате.dkurt
13.02.2019 07:49Не устанавливать TensorFlow на Raspberry Pi и, возможно, получить больше кадров в секунду с OpenCV?
Stantin Автор
13.02.2019 15:21Tensorflow может читать сети, обученные в Керасе, а это самый быстрый и простой способ. OpenCV понимает не все форматы и с этим надо разбираться. Я этого не делал, так как проблема производительности пока не стоит на первом месте.
lingvo
Не очень понятно мне вот это:
В сочетании с вот этим:
Я думал, что сбор и подготовка данных должны просто заключаться в том, что вы будете ездить по парку и записывать видео с камеры в сочетании с сигналами от джойстика. А все остальное — это чисто работа компьютера без вашего участия.
Stantin Автор
Да, в результате разъездов генерятся тысячи картинок. Далеко не все из них пригодны.
Надо проверить как на них распознается дорога. И разложить их по категориям — право, лево, прямо. На все это очень много времени уходит.
lingvo
Т.е. это ручной труд?
Stantin Автор
В основном да, к сожалению.
lingvo
Не пробовали оценить насколько данный подход по времени был выгоден/невыгоден по сравнению с алгоритмическим подходом к решению данной задачи?
Stantin Автор
Все упирается в задачу распознавания дороги, она технически гораздо сложнее, чем принятие решений на основе нейросети и зависит от условий.
Т.е чтобы подготовить данные для нейросети, нужно сначала подобрать параметры распознавания дороги для данной местности и уровня освещенности.
lingvo
ОК, но разве эта задача уже не решена другими? Я имею ввиду, что нельзя взять какую-то готовую распознавалку, которая уже обучена распознавать дорогу, подцепить к вашей камере на ровере и получить результат?
Я видел десятки человек, натаскивающие нейросети именно на это — выделяющие маркерами дороги, обочины, автомобили. Разве результат их работы закрыт/недоступен?
Stantin Автор
В прямо готовом виде я не встречал пока. Может быть плохо искал.
Вот это — «выделяющие маркерами дороги, обочины, автомобили» — как правило учебные задания, выделяющие части картинки по цвету.
В учебных картинках все получается хорошо, в реальной жизни не так гладко.
Мне приходило в голову попробовать выделить дорогу посредством сегментирования, но это тема для отдельной статьи.
lingvo
Да нет, они работали на автомобильные фирмы целыми месяцами.
Собственно, вы наверное слишком сложную задачу хотели решить — научить вездеход ездить без линий разметки. А в реальности автомобили все же на нее ориентируется.
Попробуйте упростить эксперимент — на той же парковой дороге нарисовать маркером или мелом линии разметки, чтобы камера с робота показывала примерно то же самое, что видит обычный автомобиль. А потом применить готовую нейросеть, уже обученную на это. Сработает?
Stantin Автор
>>Собственно, вы наверное слишком сложную задачу хотели решить
да, конечно, по линиям гораздо проще ориентироваться через Computer Vision.
Я обучал нейросеть на комнатных данных из
предыдущей статьи, она показывала приемлемые результаты на цветных картинках, но на роботе я ее не запускал.
roryorangepants
На самом деле, нет.
Если у вас была приличная база неразмеченных картинок, то разметить пару десятков кадров, а потом обучить Unet с псевдолейблингом до приемлемой точности — это решаемая задача.
Stantin Автор
Я пробовал скармливать в нейросеть цветные картинки (уменьшенные и размытые), но она не ловила закономерности.
Бегло почитал статью про Unet, сложилось впечатление что под сегментацией они понимают то, что в OpenCV называется нахождением контуров.
roryorangepants
Под сегментацией «они» подразумевают то, что называется задачей семантической сегментации.
Удивительно, что вы пишете про автономную езду, не зная про стандартные виды задач CV, которые повсеместно используются в этом домене.
Stantin Автор
Сегментация — очень интересная тема, но для задачи руления она не первостепенна.
roryorangepants
Вы не поверите. Self-driving cars — это тот домен, который крайне активно драйвит развитие сегментации (особенно в контексте видео).
Stantin Автор
Спасибо за информацию, буду смотреть в этом направлении тоже.