Или как я обнаружил изогнутые полосы для беспилотных автомобилей.
Для полной реализации проекта: https://github.com/aurangzaib/CarND-Advanced-Lane-Lines
Цели проекта:
- Вычислите
camera matrix
иdistortion coefficients
для набора изображений шахматной доски. - Примените коррекцию искажения к необработанным изображениям.
- Используйте
color
иgradients transforms
для создания двоичного образа. - Примените
perspective transform
к двоичному изображению с высоты птичьего полета. - Обнаружить
lane pixels
и приблизиться к границе полосы движения. - Определите
radius
кривизны полосы движения иvehicle position
относительно центра. - Деформируйте обнаруженные границы полосы движения обратно на исходное изображение.
- Визуализируйте границы полосы движения и числовую оценку кривизны полосы движения и положения автомобиля.
Калибровка камеры
Отправной точкой является подготовка «точек объекта», которые будут координатами (x, y, z) углов шахматной доски в мире.
Предположение: шахматная доска закреплена на плоскости (x, y) в точке z = 0, так что точки объекта одинаковы для каждого калибровочного изображения.
Таким образом, objp
- это просто реплицированный массив координат, и к objpoints
будет добавляться его копия каждый раз, когда я успешно обнаруживаю все углы шахматной доски на тестовом изображении. К imgpoints
будет добавлено положение в пикселях (x, y) каждого из углов в плоскости изображения при каждом успешном обнаружении шахматной доски.
Справочный файл исходного кода implementation/pre_processing.py
Метод PreProcessing.get_calibration_params()
Алгоритм следующий:
- Прочтите исходное изображение.
- Найдите
corners
изображения с помощью opencvfindChessboardCorners
() и добавьтеcorners
в точки изображения. - Найдите
camera matrix
иdistortion coefficients
с помощью opencvcalibrateCamera
(). - Сохраните параметры калибровки как файл
pickle
для дальнейшего использования.
Результаты калибровки камеры и устранения искажений:
Правая сторона: Original Image
. Левая сторона: Undistorted Image
Трубопровод
1. Коррекция искажений:
Алгоритм определения порога следующий:
- Загрузите параметры калибровки, например,
Camera Matrix
иDistortion Coefficient
из файла рассола. - Примените параметры калибровки к исходному изображению, чтобы удалить искажения, используя opencv
undistort
().
Чтобы продемонстрировать этот шаг, я применим коррекцию искажения к условиям реального мира:
Правая сторона: Original Image
. Левая сторона: Calibrated Image
2. Пороговые значения цвета и градиента:
Алгоритм определения порога следующий:
- Примените оттенки серого
Sobel X
с помощью метода opencvSobel
. - Найдите
8bit Sobel
и двоичный код Собеля, используяnp.uint8(255 * sx_abs / np.max(sx_abs))
. - Получите двоичный
R channel
из RGB с помощьюr_binary[(r>=rgb_thresh[0])&(r<=rgb_thresh[1])]=1
. - Получите двоичный файл
S channel
от HLS. - Результатом является слияние двоичного кода Собеля и двоичного
S channel
AND с двоичнымR channel
.
Порог для низкого высокого сглаживания Ядро Sobel X 20 200 9 R канал 170 255 - S канал 120 255 -
Правая сторона: Original Image
. Левая сторона: Binary Image
3. Преобразование перспективы:
- Метод реализации для получения
src
иdst
точек преобразования перспективы -get_perspective_points()
. Этот метод принимает в качестве входныхinput_image
и необязательныеoffset
значения. - Метод реализации для получения деформированного изображения с использованием
src
иdst
точек -get_wrapped_image()
. Метод принимает на входеinput_image
,source
иdestination
точек и возвращаетwarped
изображение. - Значения, которые я выбрал для
src
иdst
точек, таковы, что он перекрывает трапецию полосы как на исходном, так и на деформированном изображениях.
Это привело к появлению следующих точек отправления и назначения:
Источник Назначение 100, 720 100, 1280 585, 450 100, 0 695, 450 620, 0 1180, 720 620, 1280
Я проверил, что мое перспективное преобразование работает должным образом, нарисовав точки src
и dst
на тестовом изображении и его деформированном аналоге, чтобы убедиться, что линии выглядят параллельными на деформированном изображении.
Правая сторона: Original Image
. Левая сторона: Warped Image
4. Обнаружение полос движения с использованием гистограммы и алгоритма скользящего окна:
Алгоритм определения полос движения следующий:
- Возьмите
histogram
нижней половины изображения. - Найдите пики слева и справа от изображения. Эти пики представляют собой полосы движения.
- Определите положения
x
иy
всехnonzero
точек пикселей. - Переберите
windows
и для каждогоwindow
: - Определите границу окна.
- Найдите ненулевой пиксель в
x
иy
в границах окна и добавьте их в списокgood_indices
. - Извлеките левую и правую
xy
позицию изnonzero
пикселя, используяgood_indices
. - Примените полином 2-го порядка к позициям левого и правого пикселей. Это дает нам полиномиальную подгонку левой и правой линий.
Алгоритм обновления обнаруженных полос движения следующий:
- Поскольку на предыдущем шаге мы уже нашли полосы движения, нам не нужно выполнять слепой поиск каждый раз, вместо этого мы можем использовать информацию о ранее найденных совпадениях линий и искать в районе вокруг них.
- Получите левый и правый индексы для ненулевых пикселей.
- Получите положение левого и правого пикселей из ненулевых пикселей.
- Примените полином 2-го порядка к позициям левого и правого пикселей.
5. Радиус кривизны и расстояние автомобиля от центральной полосы движения:
Алгоритм определения радиуса кривизны следующий:
- Определите коэффициент преобразования пикселя в метр.
- Примените коэффициент преобразования для левого и правого полиномов. Это дает нам многочлены в метрах.
- Найдите радиус кривизны
R = ((1+ (f')**2)**1.5)/f''
, гдеf'
означает 1-ю производную, аf''
означает 2-ю производную.
Алгоритм определения расстояния до центральной полосы движения следующий:
- Получите
car position
, который находится в центре изображения. - Получите
lanes width
, взяв разность подходов левого и правого полинома. - Получите
lane center
, используя полиномиальные аппроксимации средней точки слева и справа. - Получите
distance from center
, взяв разницуcar position
иlane center
. - Получите расстояние в метрах, умножив
distance from center
на коэффициент преобразования.
6. Результаты:
Вот примеры:
Вот видео полного конвейера:
Https://www.youtube.com/watch?v=N2Xmli0xVmA
Обсуждение
Возможные улучшения:
- Использование данных из левой подгонки только в том случае, если правильная подгонка значительно отличается, и наоборот.
- Динанмическое пороговое значение для бинаризации.
- Подход глубокого обучения можно использовать вместе с текущей реализацией, чтобы уменьшить зависимость от перспективного преобразования и алгоритма скольжения окна.
Возможные точки отказа для текущего трубопровода:
- Различные условия освещения и тени от деревьев.
- Трубопровод наверняка выйдет из строя в снежных условиях.
- Линии полосы движения перекрыты другим транспортным средством, идущим впереди.
Для полной реализации проекта: https://github.com/aurangzaib/CarND-Advanced-Lane-Lines