Или как я обнаружил изогнутые полосы для беспилотных автомобилей.

Для полной реализации проекта: 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 изображения с помощью opencv findChessboardCorners () и добавьте corners в точки изображения.
  • Найдите camera matrix и distortion coefficients с помощью opencv calibrateCamera ().
  • Сохраните параметры калибровки как файл pickle для дальнейшего использования.

Результаты калибровки камеры и устранения искажений:

Правая сторона: Original Image. Левая сторона: Undistorted Image

Трубопровод

1. Коррекция искажений:

Алгоритм определения порога следующий:

  • Загрузите параметры калибровки, например, Camera Matrix и Distortion Coefficient из файла рассола.
  • Примените параметры калибровки к исходному изображению, чтобы удалить искажения, используя opencv undistort ().

Чтобы продемонстрировать этот шаг, я применим коррекцию искажения к условиям реального мира:

Правая сторона: Original Image. Левая сторона: Calibrated Image

2. Пороговые значения цвета и градиента:

Алгоритм определения порога следующий:

  • Примените оттенки серого Sobel X с помощью метода opencv Sobel.
  • Найдите 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