OpenCV (Open Source Computer Vision Library) - библиотека алгоритмов компьютерного зрения, обработки изображений и численных алгоритмов общего назначения. Она обладает большим потенциалом, который позволяет применять ее в робототехнических нуждах, так что роботы могут, подобно человеку, взаимодействовать с предметами окружающего мира - выделять и распознавать их, реагировать соответствующим образом. |
Для примера, можно рассмотреть такую возможность, как слежение за цветными объектами - пусть тележка с LEGO-пассажиром будет стремиться всегда находиться в поле зрения web-камеры:
Программа с подробными комментариями по коду, которая реализует алгоритм, работающий в этом видео, приведена в конце заметки.
С API, предоставляемым библиотекой OpenCV можно познакомиться на сайте в разделе документации отдельно. Здесь же предлагается ознакомиться с ключевыми моментами, использующихся в алгоритме слежения.
Первый момент:
Для уменьшения цветового шума, который обязательно выдает практически любая камера используется следующая конструкция:
#размытие исходной картинки для уменьшения цветового шума cv.Smooth(img, buf, cv.CV_BLUR, 3);Это приводит к примерно следующему результату:
Второй момент:
Определение зон в изображении совпадающих с заданным цветом. Причем, следует отметить, что для поиска заданного цвета изображение переводится из цветового пространства RGB (когда каждая точка изображения кодируется тремя цветами: красным, зеленым и синим) в пространство HSV (здесь тоже три компоненты, но другие: тон, насыщенность, яркость). После чего, уже и ищутся все зоны чьи точки находятся в заданном диапазоне значений.
#распознавание цвета лучше производить в пространстве #HSV(Hue, Saturation, Value), а не RGB, поэтому необходимо #переконверировть изображение. cv.CvtColor(buf, buf, cv.CV_BGR2HSV) #отфильтровать только пиксели, попадающие попадающие #под заданный диапазон cv.InRangeS(buf, (110, 140, 200), (120, 200, 255), thresholded_img)
Синий LEGO-человечек будет отмечен в результате, как следующий набор точек.
А что если нужно следить не за синим, а за другим цветом? Для этого придется взять другой диапазон значений, вычислить его самостоятельно. Другой вариант воспользоваться специальным Python скриптом. Он позволяет выбрать мышкой объект, по цвету отличающийся от остальных точек в изображении, а затем с помощью клавиш, сделать более точную настройку диапазона:
- q и w - нижняя граница диапазона для значения Hue, e и r - верхняя
- a и s - нижняя граница диапазона для значения Saturation, d и f - верхняя
- z и x - нижняя граница диапазона для значения Value, c и v - верхняя
Итоговый Python скрипт для слежения за синим объектом и удержанием его перед камерой, посредством управления моторами на LEGO Mindstorms тележке.
Программа основана на примере, взятом вот из этого источника.
import cv from nxt.locator import find_one_brick from nxt.motor import * # коэффициенты ПИД регулятора KP = 0.3 KI = 0.2 KD = 3 camera_window = "Track a Brick" #основной класс программы class BrickTracker: def __init__(self): #поиск NXT блока и инициализация синхронизированный моторов brick = find_one_brick(debug=True) left_engine = Motor(brick, PORT_B) right_engine = Motor(brick, PORT_C) self.vehicle = SynchronizedMotors(left_engine, right_engine, 0) #переменные используемые во время перемещения тележки self.flMove = False self.I = 0 self.preverr = 0 #создать основное окно программы, только в случае, если #блок успешно проинициализировался cv.NamedWindow(camera_window, 1) #инициализировать web-камеру self.capture = cv.CaptureFromCAM(0) #движение тележки вперед или назад по ПИД регулятору. #Параметр "shift" указывает, как далеко тележка от желаемой позиции def move_vehicle(self, shift): err = shift #ПИД регулятор P = err * KP self.I = err * KI + self.I D = (err - self.preverr) * KD power = P + self.I + D self.preverr = err self.I = self.I * 0.6 #ограничение скорости if power > 80: power = 80 if power < -80: power = -80 #позиционирование не происходит абсолютно точно на заданное #расположение # - достаточно просто оказаться вблизи (+/- 5 пикселей) if abs(err) > 5: self.flMove = True self.vehicle.run(power) else: if self.flMove: self.flMove = False self.stop_vehicle() #остановить моторы тележки def stop_vehicle(self): self.vehicle.idle() #основной метод класса, выполняется до тех пор, пока не нажата #клавиша ESC def run(self): x = 320 #подготовить буфера, по которым будет вестись распознавание buf = cv.CreateImage(cv.GetSize(cv.QueryFrame(self.capture)), 8, 3) thresholded_img = cv.CreateImage(cv.GetSize(buf), 8, 1) while True: #получить один кадр из камеры img = cv.QueryFrame(self.capture) #размытие исходной картинки для уменьшения цветового шума cv.Smooth(img, buf, cv.CV_BLUR, 3); #распознавание цвета лучше производить в пространстве #HSV(Hue, Saturation, Value), а не RGB, поэтому необходимо #переконверировть изображение. cv.CvtColor(buf, buf, cv.CV_BGR2HSV) #отфильтровать только пиксели, попадающие попадающие #под заданный диапазон cv.InRangeS(buf, (110, 140, 200), (120, 200, 255), thresholded_img) #определить, если группа отфильтрованные пикселей достаточно #большая, чтобы быть нужным объектом. Маленькие области #игнорируются moments = cv.Moments(cv.GetMat(thresholded_img,1), 0) area = cv.GetCentralMoment(moments, 0, 0) #только если область достаточно большая if(area > 100000): #определить центр распознанного объекта x = int(cv.GetSpatialMoment(moments, 1, 0)/area) y = int(cv.GetSpatialMoment(moments, 0, 1)/area) #поверх картинки с камеры отрисовать маркеры: # круг и горизонтальную линию cv.Circle(img, (x, y), 2, (255, 255, 255), 10) cv.Line(img, (0, y), (639, y), (255, 255, 255)) #отобразить получившееся изображение в окне программы cv.ShowImage(camera_window, img) #в зависимости от положения распознанного участка #передвинуть тележку self.move_vehicle(x - 320) #проверить нажата ли клавиша ESC ch = 0xFF & cv.WaitKey(10) if ch == 27: break #закрыть окно программы cv.DestroyAllWindows() #после завершения основного цикла программы отключить подачу #энергии на моторы self.stop_vehicle() #завершить работу с камерой del(self.capture) if __name__=="__main__": tracker = BrickTracker() tracker.run()
Скачать Python-скрипт можно здесь.
Комментариев нет:
Отправить комментарий