Я работаю над обнаружением движения в реальном времени и отслеживанием объектов в OpenCV / C ++ и в настоящее время застрял в части отслеживания.
Matlab-пример того, что я хочу сделать: http://www.mathworks.de/de/help/vision/examples/motion-based-multiple-object-tracking.html (Я обеспокоен частью отслеживания и как перенести ее на C ++ / OpenCV)
Моя часть движений работает с OpenCVs BackgroundSubtractor MOG2, который позволяет найти контуры и отфильтровать меньшие контуры.
Для отслеживания я в настоящее время пытаюсь использовать KalmanFilter (с аналогичной реализацией этот) который сейчас вызывается в каждом кадре, если был найден движущийся объект, и рисует линию на своем пути.
Мое обнаружение & Отслеживающая часть выглядит примерно так:
BackgroundSubtractorMOG2 bg;
bg.operator()(frame, threshold);
bg.getBackgroundImage(background);
... //morphological operations to remove noise etc.
findContours(threshold, ...);
... //filtering to reject contours which are too smalle/too big
for(int i = 0; i < contours.size(); i++){
approxPolyDP(...);
boundRect = boundingRect(...);
x = boundRect.x + boundRect.width/2;
y = boundRect.y + boundRect.height/2;}
kalmanFilter.track(x,y);
kalmanFilter.draw(frame);
Текущая проблема:
У меня есть сцена с 0 движущимися объектами, затем 1 объект движется, обнаруживается по контурам и отслеживается. Затем второй объект перемещается в поле зрения, обнаруживается и заставляет трекер прыгать на него вместо того, чтобы следовать за первым или маркировка как индивидуально (который я хочу).
Текущий трекер берет х & y координаты найденного объекта. Таким образом, как только другой объект обнаружен, трекер по-прежнему предполагает, что это тот же объект но с другими координатами, чем ожидалось.
Как видите, есть нет функции для назначения «треков» определенному объекту что, вероятно, самая большая проблема. Я читал о венгерском алгоритме, но не совсем уверен, как реализовать его в своих функциях.
Что может быть хорошим способом заставить отслеживание работать для нескольких объектов?
Моя идея состояла в том, что если бы я имел каждый объект уникально идентифицирован Я мог бы проверить, если идентификатор все тот же, а если нет пусть трекер знает, что это новый объект отслеживать отдельно от других. Не уверен, если это необходимо или даже полезно, хотя и если да, то как это сделать.
попробуйте что-то вроде этого:
for each contour:
if its already tracked with ID 'A': kalmanFilter_with_id_A.track(x,y);
else createNewKalmanFilterWithID A
вам нужен какой-то механизм, чтобы решить, отслеживается ли он уже. В простом отслеживании вы просто решаете, измеряя расстояния до контуров в последнем кадре и, если он достаточно близок, это старый объект. Это довольно ошибочно, поэтому вы можете взглянуть на лучшие методы отслеживания, например, вероятностное отслеживание.
такой простой режим:
for each contour 'currentFrameC':
for each contour 'lastFrameC'
if distance(currentFrameC, lastFrameC) is smallest and < threshold
currentFrameC is the same object as lastFrameC so give it the same ID
if no shortest contour with dist < thres was found, create a new object with a new ID and create a new KalmanFilter with this same ID for that object
call kalmanFilter with ID for each found contour ID
Как предложил Мика, вам нужно иметь свой собственный алгоритм, чтобы отличать tracked_object от new_detection.
Самое простое решение — сравнить расстояние между центроидами.
Другие аплодисменты включают,
(В конце я предоставил ссылки на код и статьи.)
Метод BoundingBoxOverlapRatio:
меры
bbox_frame1_obj1
, bbox_frame1_obj2
…Frame_2: определение BLOB-объектов -> рисовать boundingRectangles bbox_frame2_obj1
-> сравнить наложение bbox_frame2_obj1
с bbox_frame1_obj1
,bbox_frame1_obj2
так далее..
Степень совпадения указывает на вероятность того, что это один и тот же объект, в зависимости от того, какие позиции объекта могут быть обновлены.
Но этот метод подходит для сценариев, которые включают медленно движущиеся объекты, такие как обнаружение пешеходов, иначе они могут вообще не перекрываться.
Венгерский алгоритм
Этот 5-6-ступенчатый алгоритм служит простым, но в то же время надежным решением для такого рода задач присваивания.
Это работает как показано ниже.
Создать матрицу с Ряды как prev_position
объектов и Колонны как new_detections
Если у нас в памяти 3 объекта, а в новом кадре 4 капли, это приводит к матрице 3х4, где каждый элемент представляет собой расстояние между объектами и обнаружениями.
Элемент (1,1) -> расстояние между центром тяжести obj_1
и обнаружил detection_1
Элемент (1,2) -> расстояние между центроидами obj_1
и обнаружил detection_2
…
Пример матрицы (единицы в пикселях):
5 15 30 20
20 30 3 40
12 4 15 50
Ситуация здесь проста и понятна, что приводит к выводу
obj_1 -> detection_1 (5px between obj_1 and detection_1)
obj_2 -> detection_3 (3px between obj_2 and detection_3)
obj_3 -> detection_2 (4px between obj_3 and detection_2)
Таким образом, Detection_4 должен быть новым объектом, и должен быть назначен новый трек и идентификатор.
После этого obj_4 должен отслеживаться, а следующая матрица имеет 4 строки…
Но с большим количеством объектов задача становится более сложной. И венгерский алгоритм помогает решать более сложные и огромные матрицы для оптимального назначения обнаружений для объектов.
Ниже приведены некоторые полезные ресурсы для отслеживания нескольких объектов и венгерского алгоритма.
Документация Matlab
C ++ реализация MATLABs Multi-Object трекер (Включает венгерский алгоритм)
Метод BoundingBoxOverlapRatio:
Венгерский алгоритм: