В этом примере показано, как выполнить автоматическое обнаружение и основанное на движении отслеживание перемещения объектов в видео. Это упрощает пример Основанное на движении Сопровождение нескольких объектов и использует
доступный в Automated Driving Toolbox™.multiObjectTracker
Обнаружение перемещения объектов и основанного на движении отслеживания является важными компонентами многих приложений компьютерного зрения, включая распознавание активности, контроль трафика и автомобильную безопасность. Проблема основанного на движении объектного отслеживания может быть разделена на две части:
Обнаружение движущихся объектов в каждой системе координат
Отслеживание движущихся объектов от системы координат до системы координат
Для обнаружения движущихся объектов используется алгоритм вычитания фона, основанный на смешанных гауссовских моделях. Морфологические операции применяются к полученной маске переднего плана для устранения шума. Наконец, анализ больших двоичных объектов обнаруживает группы связанных пикселей, которые, вероятно, соответствуют движущимся объектам.
Отслеживание перемещения объектов от системы координат до системы координат сделано multiObjectTracker
объект, который ответственен за следующее:
Присвоение обнаружений к дорожкам.
Инициализация новых треков на основе неприсвоенных обнаружений. Все дорожки инициализируются как 'Tentative'
, составление возможности, что они следовали из ложного обнаружения.
Подтверждение дорожек, если у них есть больше, чем M, присвоило обнаружения в системах координат N.
Обновление существующих дорожек на основе присвоенных обнаружений.
Курсирующий (предсказывая) существующие неприсвоенные дорожки.
Удаление дорожек, если они остались неприсвоенными (курсировало) слишком долго.
Присвоение обнаружений к тому же объекту базируется только на движении. Движение каждой дорожки оценивается Фильтром Калмана. Фильтр предсказывает местоположение дорожки в каждой системе координат и определяет вероятность каждого обнаружения, присваиваемого каждой дорожке. Чтобы инициализировать фильтр, который вы проектируете, используйте FilterInitializationFcn
свойство multiObjectTracker
.
Для получения дополнительной информации смотрите Сопровождение нескольких объектов.
Этим примером является функция с основной частью наверху и стандартными программами помощника в форме вложенных функций ниже. Дополнительную информацию см. во Вложенных функциях.
function MultipleObjectTrackingExample()
% Create objects used for reading video and displaying the results. videoObjects = setupVideoObjects('atrium.mp4'); % Create objects used for detecting objects in the foreground of the video. minBlobArea = 400; % Minimum blob size, in pixels, to be considered as a detection detectorObjects = setupDetectorObjects(minBlobArea);
При создании multiObjectTracker
, рассмотрите следующее:
FilterInitializationFcn
: Вероятное движение и модели измерения. В этом случае объекты, как ожидают, будут иметь движение постоянной скорости. initDemoFilter
функция конфигурирует линейный Фильтр Калмана, чтобы отследить движение. Смотрите раздел 'Define a Kalman filter' для деталей.
AssignmentThreshold
: Как далеко обнаружения могут упасть от дорожек. Значение по умолчанию для этого параметра равняется 30. Если существуют обнаружения, которые не присвоены дорожкам, но должны быть, увеличить это значение. Если существуют обнаружения, которые присвоены дорожкам, которые слишком далеки, уменьшают это значение.
DeletionThreshold
: Сколько времени дорожка обеспечена перед удалением. В этом случае, поскольку видео имеет 30 кадров в секунду, рыночная стоимость составляет приблизительно 0,75 секунды (22 системы координат).
ConfirmationThreshold
: Параметры, управляющие подтверждением дорожки. Дорожка инициализируется каждым неприсвоенным обнаружением. Некоторые из этих обнаружений могут быть ложными, так первоначально, всеми дорожками является 'Tentative'
. Чтобы подтвердить дорожку, это должно быть обнаружено, по крайней мере, M из систем координат N. Выбор M и N зависит от видимости объектов. Этот пример принимает видимость 6 из 10 систем координат.
tracker = multiObjectTracker(... 'FilterInitializationFcn', @initDemoFilter, ... 'AssignmentThreshold', 30, ... 'DeletionThreshold', 22, ... 'ConfirmationThreshold', [6 10] ... );
При определении фильтра отслеживания для движения завершите следующие шаги:
Шаг 1: Задайте модель движения и состояние
В этом примере используйте постоянную скоростную модель в 2D прямоугольной системе координат.
Состоянием является [x;vx;y;vy]
.
Матрицей модели изменения состояния является A = [1 dt 0 0; 0 1 0 0; 0 0 1 dt; 0 0 0 1]
.
Примите тот dt = 1
.
Шаг 2: Задайте шум процесса
Шум процесса представляет части процесса, которые не учтены в модели. Например, в постоянной скоростной модели, ускорением пропускают.
Шаг 3: Задайте модель измерения
В этом примере, только положение ([x;y]
) измеряется. Так, моделью измерения является H = [1 0 0 0; 0 0 1 0]
.
Примечание: Чтобы предварительно сконфигурировать эти параметры, задайте 'MotionModel'
свойство как '2D Constant Velocity'
.
Шаг 4: Инициализируйте вектор состояния на основе измерения датчика
В этом примере, потому что измерением является [x;y]
и состоянием является [x;vx;y;vy]
, инициализация вектора состояния является прямой. Поскольку нет никакого измерения скорости, инициализируйте vx
и vy
компоненты к 0.
Шаг 5: Задайте ковариацию начального состояния
В этом примере, измерения являются довольно шумными, поэтому задают ковариацию начального состояния, чтобы быть довольно большим: stateCov = diag([50, 50, 50, 50])
Шаг 6: Создайте правильный фильтр
В этом примере все модели линейны, так trackingKF
использования как фильтр отслеживания.
function filter = initDemoFilter(detection) % Initialize a Kalman filter for this example. % Define the initial state. state = [detection.Measurement(1); 0; detection.Measurement(2); 0]; % Define the initial state covariance. stateCov = diag([50, 50, 50, 50]); % Create the tracking filter. filter = trackingKF('MotionModel', '2D Constant Velocity', ... 'State', state, ... 'StateCovariance', stateCov, ... 'MeasurementNoise', detection.MeasurementNoise(1:2,1:2) ... ); end
Следующий цикл запускает видеоклип, обнаруживает движущиеся объекты в видео и отслеживает их через видеокадры.
% Count frames to create a sense of time. frameCount = 0; while hasFrame(videoObjects.reader) % Read a video frame and detect objects in it. frameCount = frameCount + 1; % Promote frame count frame = readFrame(videoObjects.reader); % Read frame [detections, mask] = detectObjects(detectorObjects, frame); % Detect objects in video frame % Run the tracker on the preprocessed detections. confirmedTracks = updateTracks(tracker, detections, frameCount); % Display the tracking results on the video. displayTrackingResults(videoObjects, confirmedTracks, frame, mask); end
Создайте объекты, используемые для чтения и отображения видеокадров.
function videoObjects = setupVideoObjects(filename) % Initialize video I/O % Create objects for reading a video from a file, drawing the tracked % objects in each frame, and playing the video. % Create a video file reader. videoObjects.reader = VideoReader(filename); % Create two video players: one to display the video, % and one to display the foreground mask. videoObjects.maskPlayer = vision.VideoPlayer('Position', [20, 400, 700, 400]); videoObjects.videoPlayer = vision.VideoPlayer('Position', [740, 400, 700, 400]); end
Создайте объекты, используемые для обнаружения основных объектов. Используйте minBlobArea
задавать размер блоба, в пикселях, который считается обнаружением.
Увеличьте minBlobArea
постараться не обнаруживать маленькие блобы, которые, более вероятно, будут ложными обнаружениями, или если несколько обнаружений создаются для того же объекта из-за частичного поглощения газов.
Уменьшите minBlobArea
если объекты обнаруживаются слишком поздно или нисколько.
function detectorObjects = setupDetectorObjects(minBlobArea) % Create System objects for foreground detection and blob analysis % The foreground detector segments moving objects from the % background. It outputs a binary mask, where the pixel value of 1 % corresponds to the foreground and the value of 0 corresponds to % the background. detectorObjects.detector = vision.ForegroundDetector('NumGaussians', 3, ... 'NumTrainingFrames', 40, 'MinimumBackgroundRatio', 0.7); % Connected groups of foreground pixels are likely to correspond to % moving objects. The blob analysis System object finds such % groups (called 'blobs' or 'connected components') and computes % their characteristics, such as their areas, centroids, and the % bounding boxes. detectorObjects.blobAnalyzer = vision.BlobAnalysis('BoundingBoxOutputPort', true, ... 'AreaOutputPort', true, 'CentroidOutputPort', true, ... 'MinimumBlobArea', minBlobArea); end
detectObjects
функция возвращает центроиды и ограничительные рамки обнаруженных объектов как список objectDetection
объекты. Можно предоставить этот список как вход к multiObjectTracker
. detectObjects
функционируйте также возвращает бинарную маску, которая имеет тот же размер как входной кадр. Пиксели со значением 1 соответствуют переднему плану. Пиксели со значением 0 соответствуют фону.
Функция выполняет сегментацию движения с помощью приоритетного детектора. Это затем выполняет морфологические операции на получившейся бинарной маске, чтобы удалить шумные пиксели и заполнить отверстия в остающихся блобах.
При создании objectDetection
перечислите, frameCount
служит входом времени, и центроиды обнаруженных блобов служат измерением. Список также имеет две дополнительных пары "имя-значение":
MeasurementNoise
- Обнаружение блоба является шумным, и этот пример задает большое значение шума измерения.
ObjectAttributes
- Обнаруженные ограничительные рамки, которые передаются отображению дорожки, добавляются к этому аргументу.
function [detections, mask] = detectObjects(detectorObjects, frame) % Expected uncertainty (noise) for the blob centroid. measurementNoise = 100*eye(2); % Detect foreground. mask = detectorObjects.detector.step(frame); % Apply morphological operations to remove noise and fill in holes. mask = imopen(mask, strel('rectangle', [6, 6])); mask = imclose(mask, strel('rectangle', [50, 50])); mask = imfill(mask, 'holes'); % Perform blob analysis to find connected components. [~, centroids, bboxes] = detectorObjects.blobAnalyzer.step(mask); % Formulate the detections as a list of objectDetection objects. numDetections = size(centroids, 1); detections = cell(numDetections, 1); for i = 1:numDetections detections{i} = objectDetection(frameCount, centroids(i,:), ... 'MeasurementNoise', measurementNoise, ... 'ObjectAttributes', {bboxes(i,:)}); end end
displayTrackingResults
функция чертит ограничительную рамку и метку ID для каждой дорожки на видеокадре и приоритетной маске. Это затем отображает систему координат и маску в их соответствующих видеоплеерах.
function displayTrackingResults(videoObjects, confirmedTracks, frame, mask) % Convert the frame and the mask to uint8 RGB. frame = im2uint8(frame); mask = uint8(repmat(mask, [1, 1, 3])) .* 255; if ~isempty(confirmedTracks) % Display the objects. If an object has not been detected % in this frame, display its predicted bounding box. numRelTr = numel(confirmedTracks); boxes = zeros(numRelTr, 4); ids = zeros(numRelTr, 1, 'int32'); predictedTrackInds = zeros(numRelTr, 1); for tr = 1:numRelTr % Get bounding boxes. boxes(tr, :) = confirmedTracks(tr).ObjectAttributes{1}{1}; % Get IDs. ids(tr) = confirmedTracks(tr).TrackID; if confirmedTracks(tr).IsCoasted predictedTrackInds(tr) = tr; end end predictedTrackInds = predictedTrackInds(predictedTrackInds > 0); % Create labels for objects that display the predicted rather % than the actual location. labels = cellstr(int2str(ids)); isPredicted = cell(size(labels)); isPredicted(predictedTrackInds) = {' predicted'}; labels = strcat(labels, isPredicted); % Draw the objects on the frame. frame = insertObjectAnnotation(frame, 'rectangle', boxes, labels); % Draw the objects on the mask. mask = insertObjectAnnotation(mask, 'rectangle', boxes, labels); end % Display the mask and the frame. videoObjects.maskPlayer.step(mask); videoObjects.videoPlayer.step(frame); end
end
В этом примере вы создали основанную на движении систему для обнаружения и отслеживания нескольких движущихся объектов. Попытайтесь использовать различное видео, чтобы видеть, можно ли обнаружить и отслеживаемые объекты. Попытайтесь изменить параметры multiObjectTracker
.
Отслеживание в этом примере базировалось только на движении, учитывая, что все объекты перемещаются в прямую линию с постоянной скоростью. Когда движение объекта значительно отклоняется от этой модели, пример может произвести ошибки отслеживания. Заметьте ошибку в отслеживании человека, закрытого деревом.
Можно уменьшать вероятность отслеживания ошибок при помощи более комплексной модели движения, таких как постоянное ускорение или постоянный поворот. Чтобы сделать это, попытайтесь задать различный фильтр отслеживания, такой как trackingEKF
или trackingUKF
.
trackingKF
| trackingEKF
| trackingUKF
| objectDetection
| vision.VideoPlayer
| VideoReader
| multiObjectTracker