Следуя Линии На Основе Opencv

Сейчас очень популярны курсы по созданию автопилотов для автомобилей.

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

Я тоже не смогла пройти мимо и увлеклась.

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

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

На эту тему написано множество статей, вот несколько наиболее подробных:

В них все достаточно просто и схема работы сводится к нескольким пунктам: Я наклеил на пол белую ленту и приступил к работе.



Следуя линии на основе OpenCV

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



Геометрия

Сразу начались проблемы с геометрией.

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

Однако их линии были хорошо направлены, и на снимках не было никаких обломков.

У меня сложилась совершенно другая картина.

Геометрия ленты ленты была далеко не прямой.

Яркий свет на полу создавал шум.

После использования Canny произошло вот что:

Следуя линии на основе OpenCV

И строки Хафа были:

Следуя линии на основе OpenCV

Усилив критерии, удалось исключить мусор, но почти все линии, обнаруженные на полосе, исчезли.

Было бы глупо полагаться на такие крошечные сегменты.



Следуя линии на основе OpenCV

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

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

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

Пришлось застелить его диванной подушкой).

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



Следуя линии на основе OpenCV



Свет

Вторая проблема была с освещением.

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

В результате нам пришлось реализовать динамическую обрезку на черно-белом фильтре.

Алгоритм такой: если после применения фильтра на снимке слишком много белого (более 10%), то порог следует повысить.

Если оно слишком мало (менее 3%) – опустите.

Практика показала, что в среднем за 3-4 итерации можно найти оптимальное обрезание.

Магические числа вынесены в отдельный конфиг (см.

ниже), с ними можно поиграться в поисках оптимума.

  
  
   

def balance_pic(image): global T ret = None direction = 0 for i in range(0, tconf.th_iterations): rc, gray = cv.threshold(image, T, 255, 0) crop = Roi.crop_roi(gray) nwh = cv.countNonZero(crop) perc = int(100 * nwh / Roi.get_area()) logging.debug(("balance attempt", i, T, perc)) if perc > tconf.white_max: if T > tconf.threshold_max: break if direction == -1: ret = crop break T += 10 direction = 1 elif perc < tconf.white_min: if T < tconf.threshold_min: break if direction == 1: ret = crop break T -= 10 direction = -1 else: ret = crop break return ret

Наладив машинное зрение, можно было переходить к реальному движению.

Алгоритм был такой:

  • 0,5 секунды идем прямо
  • Сфотографировать
  • найти вектор
  • если начало вектора смещено относительно центра картинки, слегка подверните в нужную сторону
  • если угол вектора отклоняется от вертикали больше, чем необходимо, мы поворачиваем в правильном направлении
  • если вдруг случится так, что полоса исчезнет из кадра, мы делаем предположение, что мы прошли поворот и начинаем поворачивать в сторону последнего поворота или наклона вектора на предыдущем шаге
Краткая версия кода (Полная — на Гитхаб ):

def check_shift_turn(angle, shift): turn_state = 0 if angle < tconf.turn_angle or angle > 180 - tconf.turn_angle: turn_state = np.sign(90 - angle) shift_state = 0 if abs(shift) > tconf.shift_max: shift_state = np.sign(shift) return turn_state, shift_state def get_turn(turn_state, shift_state): turn_dir = 0 turn_val = 0 if shift_state != 0: turn_dir = shift_state turn_val = tconf.shift_step if shift_state != turn_state else tconf.turn_step elif turn_state != 0: turn_dir = turn_state turn_val = tconf.turn_step return turn_dir, turn_val def follow(iterations): tanq.set_motors("ff") try: last_turn = 0 last_angle = 0 for i in range(0, iterations): a, shift = get_vector() if a is None: if last_turn != 0: a, shift = find_line(last_turn) if a is None: break elif last_angle != 0: logging.debug(("Looking for line by angle", last_angle)) turn(np.sign(90 - last_angle), tconf.turn_step) continue else: break turn_state, shift_state = check_shift_turn(a, shift) turn_dir, turn_val = get_turn(turn_state, shift_state) if turn_dir != 0: turn(turn_dir, turn_val) last_turn = turn_dir else: time.sleep(tconf.straight_run) last_turn = 0 last_angle = a finally: tanq.set_motors("ss")



Результаты

Неравномерно, но уверенно танк ползет по траектории:

Следуя линии на основе OpenCV

А вот GIF из отладочной графики:

Следуя линии на основе OpenCV



Настройки алгоритма



## Picture settings # initial grayscale threshold threshold = 120 # max grayscale threshold threshold_max = 180 #min grayscale threshold threshold_min = 40 # iterations to find balanced threshold th_iterations = 10 # min % of white in roi white_min=3 # max % of white in roi white_max=12 ## Driving settings # line angle to make a turn turn_angle = 45 # line shift to make an adjustment shift_max = 20 # turning time of shift adjustment shift_step = 0.125 # turning time of turn turn_step = 0.25 # time of straight run straight_run = 0.5 # attempts to find the line if lost find_turn_attempts = 5 # turn step to find the line if lost find_turn_step = 0.2 # max # of iterations of the whole tracking max_steps = 100

Код для Гитхаб .

Теги: #python #роботы #Raspberry Pi #разработка Raspberry Pi #Робототехника #искусственный интеллект #Обработка изображений #искусственный интеллект #компьютерное зрение #OpenCV #робототехника #беспилотный автомобиль

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.