Сейчас очень популярны курсы по созданию автопилотов для автомобилей.
Здесь это наноградус от Udacity, пожалуй, самый известный вариант. Многие люди изучают его и публикуют свои решения.
Я тоже не смогла пройти мимо и увлеклась.
Разница в том, что курс предполагает разработку алгоритма на основе предоставленных данных, и я сделал все, чтобы твой робот .
Первая задача, с которой сталкиваются студенты курса при изучении компьютерного зрения, — следить за линией на дороге.
На эту тему написано множество статей, вот несколько наиболее подробных:
В них все достаточно просто и схема работы сводится к нескольким пунктам:- Фильтровать по цвету.
- Выбрать лица
- Отрезаем ненужные части рисунка
- Обнаружение линий с помощью Преобразование Хафа .
В упомянутых вами работах стояла задача найти еще и желтую линию, поэтому работали с цветами HLS и HSV. Поскольку линия у меня была только белая, я решил с этим не заморачиваться и ограничиться черно-белым фильтром.
Геометрия
Сразу начались проблемы с геометрией.На фотографиях учеников полоса стрелой уходит в горизонт. И все же на нем обнаруживается множество линий, которые авторам пришлось объединить.
Однако их линии были хорошо направлены, и на снимках не было никаких обломков.
У меня сложилась совершенно другая картина.
Геометрия ленты ленты была далеко не прямой.
Яркий свет на полу создавал шум.
После использования Canny произошло вот что:
И строки Хафа были:
Усилив критерии, удалось исключить мусор, но почти все линии, обнаруженные на полосе, исчезли.
Было бы глупо полагаться на такие крошечные сегменты.
В общем, результаты были крайне нестабильными, и мне пришло в голову попробовать другой подход.
Вместо линий я стал искать контуры.
Сделав предположение, что самый большой контур — это изолента, нам удалось избавиться от мусора.
(Позже выяснилось, что большой белый плинтус занял в рамке больше места, чем изолента.
Пришлось застелить его диванной подушкой).
Если взять минимальный прямоугольник, ограничивающий контур, то на роль вектора движения очень подходит средняя продольная линия.
Свет
Вторая проблема была с освещением.Одну сторону маршрута я очень удачно разложил в тени дивана и обработать фотографии всего маршрута с одинаковыми настройками было совершенно невозможно.
В результате нам пришлось реализовать динамическую обрезку на черно-белом фильтре.
Алгоритм такой: если после применения фильтра на снимке слишком много белого (более 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")
Результаты
Неравномерно, но уверенно танк ползет по траектории:А вот GIF из отладочной графики:
Настройки алгоритма
## 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 #робототехника #беспилотный автомобиль
-
3D-Моделирование В Современном Мире.
19 Oct, 24 -
Google Показала Прототип Своего Телефона
19 Oct, 24 -
Как Переместить Гору Фудзи
19 Oct, 24 -
Отчет Конференции Ivbit
19 Oct, 24