Машина с автономным обнаружением линии на Raspberry Pi и OpenCV (часть 2)


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

Внешний вид второй части проекта машины с автономным обнаружением линии на Raspberry Pi и OpenCV

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

Подготовка к реализации проекта

Для обнаружения линий и обработки изображений в нашем проекте мы будем использовать библиотеку OpenCV. Поэтому убедитесь в том, что библиотека OpenCV установлена на вашу плату Raspberry Pi. Также подайте питание на плату с помощью адаптера 2A и подключите ее к монитору чтобы упростить процесс отладки проекта.

Перед реализацией данного проекта рекомендуем прочитать основы работы с библиотекой OpenCV в плате Raspberry Pi. Также можете посмотреть все проекты на нашем сайте, в которых использовалась библиотека OpenCV.

Написание программы для Raspberry Pi для автономного обнаружения линии

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

1. Перспективное преобразование (Perspective Transformation). На первом шаге нам необходимо получить перспективный (необходимый нам) вид кадра. Этот шаг позволит нам преобразовать изображение (видео) к виду, с помощью которого мы будем лучше понимать его суть. Для получения перспективного вида изображения нам необходимо определить точки на нем, в которых мы будем собирать информацию, и точки выходного изображения, внутри которых мы будем показывать наше изображение.

2. Пороговая классификация изображения (Image Thresholding) и определение его краев (Canny Edge Detection). Пороговая классификация изображения – это достаточно популярная технология сегментации, используемая для выделения интересующего нас фрагмента изображения с фона изображения. В нашем случае мы будем использовать ее для обнаружения линий на разметке. А технология Canny Edge detection будет использоваться для определения краев изображения.

3. Трансформация линии (Hough Line Transform). Данная технология используется для обнаружения любой формы (форма может быть представлена в математическом виде) на изображении или видео. В нашем проекте мы будем использовать данную технологию для обнаружения линий на дороге. Но перед тем как использовать данную технологию желательно произвести обнаружение краев изображения.

Рассмотрим содержание данных шагов более подробно.

Перспективная трансформация (Perspective Transformation)

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

Исходное изображение дороги для нашего проекта

Теперь, как указывалось ранее, для получения перспективного вида изображения нам необходимо в этом исходном изображении определить точки, в которых мы будем собирать информацию, и точки выходного кадра, в пределах которых мы хотим показывать наше изображение. Мы будем сохранять эти точки в массивах NumPy и затем передавать их в функцию перспективной трансформации (Perspective Transformation).

После определения точек мы будем получать перспективную трансформацию из двух наборов точек и интегрировать ее в исходное изображение с помощью функций cv2.getPerspectiveTransform() и cv2.warpPerspective(). Далее представлен синтаксис этих функций.

где: src – координаты области, перспективный вид которой вы хотите получить;

dst – координаты выходного кадра, внутри которого вы хотите показывать изображение.

где: src – исходное изображение;

dst – выходное изображение, которое имеет такой же тип, как и исходное изображение;

dsize – размер выходного изображения.

Вид дороги после перспективной трансформации

Пороговая классификация изображения (Image Thresholding) и определение его краев (Canny Edge Detection)

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

Пороговая классификация изображения (Image Thresholding) используется для выделения основного интересующего нас объекта с фона изображения. Мы будем производить ее с помощью функции:

где: src – массив входного изображения (оно должно быть "серым" (Grayscale));

lowerb – нижняя граница области;

upperb – верхняя граница области.

В нашем случае:

Вид дороги после пороговой классификации изображения

На следующем шаге мы будем производить обнаружение краев. Существует достаточно много способов сделать это, самый простой и популярный способ – это использование метода canny edge из библиотеки OpenCV. В нашем случае он реализуется с помощью функции:

А синтаксис в общем виде этой функции выглядит следующим образом - cv2.Canny(src, thresholdValue 1, thresholdValue 2), где Threshold Value 1 и Threshold Value 2 – это минимальная и максимальная значения границы, а src – это входное изображение.

Вид дороги после обнаружения краев с помощью метода canny edge

Трансформация линии (Hough Line Transform)

После осуществления двух предыдущих шагов на этом шаге мы будем использовать технологию трансформации линии (Hough Line Transform) чтобы обнаружить линии на дороге. Начнем этот метод мы с определения центра кадра используя точки перспективного изображения, которые мы определили ранее.

После нахождения центра кадра мы будем использовать метод Hough Line Transform чтобы обнаружить линии на дороге. Синтаксис данной функции выглядит следующим образом:

где: image – входное изображение, должно быть бинарным изображением, поэтому перед этим к нему нужно применить процедуру определения краев;

lines – вектор с параметрами (r, Φ) линий;

rho – разрешение параметра r в пикселах;

theta – разрешение параметра Φ в радианах;

threshold – минимальное число пересечений для обнаружения линии.

В нашем случае мы будем использовать эту функцию со следующими параметрами:

Вид дороги после процедуры трансформации линии

После обнаружения линий следующим шагом будем нахождение центра обоих линий используя координаты, которые мы получили из функции hough line transform. После определения центров линий мы будем использовать функции left.append и right.append чтобы произвести необходимые настройки местоположения линий.

Корректировка положения линий

Движение машины

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

Тестирование работы проекта

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

Сконструированный трек для тестирования работы нашего проекта

Машина достаточно уверенно едет прямо и замедляется на поворотах.

Тестирование движения машины между линиями

Изменение параметров движения машины в окне терминала

Но машине приходится "тяжеловато" когда она встречает крутой поворот. Это происходит из-за того, что на крутых поворотах одна из линий уходит за границы кадра и поэтому мы уже не можем найти центр между двумя линиями. Также автор проекта (ссылка на оригинал приведена в конце статьи) обнаружил, что машина иногда "рыскает" вправо или влево между линиями иногда выходит за границы линии. Это вызвано различными углами поворота, вычисляемыми для текущего и последующего кадра.

Тестирование движения машины на крутом повороте

Изменение параметров движения машины в окне терминала во время крутого поворота

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

Исходный код программы на Python

Код файла houghline.py

Код файла motors.py

Источник статьи

(Проголосуй первым!)
Загрузка...
640 просмотров

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *