Беспилотные автомобили должны воспринимать мир, как люди, когда они едут. Люди используют свои глаза, чтобы определить, насколько быстро они едут, где проходят полосы движения и где находятся повороты. У автомобиля нет глаз, но в беспилотных автомобилях могут использоваться камеры и другие датчики, чтобы поддерживать аналогичную функцию. Итак, то, что камеры видят, когда мы едем по дороге, не совпадает с тем, что мы воспринимаем. Мы должны научить машину распознавать полосы движения и повороты. Следовательно, естественно, одно из первых действий, которое мы хотели бы сделать при разработке беспилотного автомобиля, - это автоматически определять полосы движения с помощью алгоритма.

Здесь мы используем OpenCV _A всеобъемлющую библиотеку компьютерного зрения, чтобы понимать захваченные изображения с машины и преобразовывать их в математические единицы, чтобы мы могли показать машине, где должна следовать линия полосы движения. В выбранном мной алгоритме есть несколько шагов для манипулирования каждым изображением кадра, чтобы уменьшить или, лучше сказать, устранить шумы в максимально возможной степени. Так как автомобилю не нужно видеть деревья или облака в небе для определения полос движения. В дополнение к уменьшению шума мы стараемся как можно больше выделять полосы движения, выделяя их с помощью некоторых алгоритмов обработки изображений.
Но вопрос в том, какие особенности линий полос нам нужно выделить? Что ж, мы можем использовать следующие функции, чтобы лучше идентифицировать различные линии полос на изображении:

  • цвет
  • форма
  • ориентация
  • положение изображения

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

Основы

Первым шагом в обнаружении полос движения является понимание того, как представлены изображения. 2D-изображение может быть представлено в виде прямоугольной сетки, состоящей из множества квадратных ячеек, называемых пикселями. Так же, как черные и белые квадраты на шахматной доске, пиксели красиво выровнены по прямым линиям как по горизонтали, так и по вертикали. Мы будем называть горизонтальные строки строками, а вертикальные - столбцами. Легко видеть, что на шахматной доске 8 строк и 8 столбцов. Но изображение может иметь много строк и столбцов, и мы можем выяснить это с помощью OpenCV image.shape. Это возвращает кортеж из числа строк, столбцов и каналов (если изображение цветное).

>> image = cv2.imread('kitten.jpg') >> print(image.shape) (342, 548, 3)

Если вы хотите узнать, сколько пикселей у этого изображения, вы можете использовать img.size, который возвращает количество пикселей в изображении.
Каждый пиксель изображения представлен в трехмерном пространстве в виде значений (R, G, B). Каждое из этих значений находится в диапазоне [0–255]. Итак, с этим объяснением мы увидели, что изображения в основном представляют собой тензоры с разным количеством строк, столбцов и элементов для каждого цветового канала.

Понимание математических характеристик изображения и его представления является большим подспорьем в решении задач компьютерного зрения и понимании алгоритмов обработки изображений.

Алгоритм определения полосы движения

Теперь пошагово опишем используемый алгоритм определения полос движения.
Предположим, у нас есть это изображение, снятое нашей машиной на шоссе.

Оттенки серого

Как видите, переулки на улицах белые или желтые. Итак, нам нужно идентифицировать и то, и другое. Сначала нам нужно преобразовать форму нашего изображения из тензора (A, B, C) в матрицу (A, B), чтобы иметь возможность работать только с необработанными пикселями. В данном случае желтый и белый считались одинаковыми. Для этого мы можем использовать метод OpenCV GrayScale.

def grayscale(img): return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

Фильтрация пикселей

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

Размытие по Гауссу

Теперь нам нужно применить функцию сглаживания, чтобы уменьшить шум и детализацию изображения. Это также помогает сгладить края изображения перед применением алгоритма обнаружения краев Canny, который является следующим шагом.

def gaussian_noise(img, kernel_size): 
   return cv2.GaussianBlur(img, (kernel_size, kernel_size), 0)
![alt img](./out/smooth_image.png)

Обнаружение Canny Edge

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

def canny(img, low_threshold, high_threshold): 
   return cv2.Canny(img, low_threshold, high_threshold)

Здесь, чтобы максимизировать края, я тоже набрал изображение.

Маскированное изображение

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

Преобразование Хафа

Пока мы проделали отличную работу по определению линий полос на картинке, теперь нам нужно нарисовать их, чтобы показать машине, где находятся полосы. Чтобы рисовать линии на изображениях или видеокадрах, мы используем технику под названием Преобразование Хафа, которое в основном определяет для каждого заданного пикселя в изображении, есть ли прямая линия, проходящая через пиксель. Алгоритм использует 5 параметров: rho, theta, min_votes, min_line_length и max_line_gap. Подробнее об алгоритме преобразования Хафа можно прочитать здесь.

Линии проводим отдельно для левой и правой стороны. Я немного подправил эту функцию, чтобы применить дополнительную фильтрацию к линиям и настроить наклон линий. Я собираюсь рассказать об этом в следующем разделе.

Корректировки для улучшения обнаружения полос

Фильтрация склонов

Здесь я применил некоторые улучшения, чтобы рисовать линии более эффективно. Когда я впервые применил hough transform, у меня было так много других линий, наклон которых отличался от линии полосы движения, и мне пришлось их отфильтровать. Следующая функция просматривает все преобразованные линии и отфильтровывает их на основе заданных минимальных и максимальных наклонов. Это поможет, в частности, с изогнутыми линиями, изменение наклона которых значительно.

Линейная регрессия

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

где σest - стандартная ошибка оценки, Y - фактическая оценка, Y ’- прогнозируемая оценка, а N - количество пар оценок. Числитель представляет собой сумму квадратов разностей между фактическими и прогнозируемыми оценками.

Таким образом, если у нас есть линия y = mx + c, проходящая через некоторые зашумленные точки данных, исследуя коэффициенты, мы видим, что линия должна иметь градиент примерно g1 и пересекать ось y в более или менее точках, y0. Мы можем переписать линейное уравнение в виде y = Ap, где A = [[x 1]] и p = [[m], [c]]. Теперь используйте lstsq, чтобы найти p.
На более простом языке линейная регрессия может нарисовать лучшую линию относительно заданного количества точек, чтобы минимизировать среднеквадратичную ошибку.

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

Взвешенное изображение

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

Недостатки алгоритма

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

Также нам нужно больше изображений и видео, чтобы попробовать улучшить алгоритм.

Одна вещь, которая меня действительно не устраивала, заключалась в том, что машина не могла адаптироваться к данным и принимать решения. Этот алгоритм похож на все время, говорящий машине, что нужно видеть.

Будущие улучшения

  • использовать глубокое обучение, чтобы машина могла адаптироваться к дороге.
  • рисование всей полосы вместо того, чтобы отмечать только линии полос

Первоначально опубликовано на сайте nazaninde.ghost.io 21 февраля 2017 г.