Отслеживание автомобилей с помощью оптического потока
Рассматриваемая далее программа основана на демонстрационной программе «Tracking Cars Using Optical Flow» из расширения Video and Image Processing Blockset, входящего в пакет MATLAB (до R2010b, в версии R2011a расширение заменено на Computer Vision System Toolbox). Для построения векторов движения в каждом кадре видеопоследовательности используется техника оценки оптического потока. В результате выполнения пороговой обработки и морфологического замыкания формируются бинарные изображения (автомобиль-фон). Затем вокруг каждого выделенного автомобиля, прошедшего линию отсчета, строится ограничивающий прямоугольник. Количество автомобилей, пересекших линию, выводится счетчиком.
В MATLAB R2010a было введено понятие системных объектов (system objects). В руководстве по расширению Video and Image Processing Blockset сказано, что системные объекты представляют собой объектно-ориентированную реализацию алгоритмов. По сравнению с обычными матлабовскими функциями они автоматически управляют своим состоянием и хорошо подходят для потоковой обработки информации. В рассматриваемой ниже программе системные объекты используются для выделения и подсчета числа машин, изображенных на заданном видеофрагменте.
Описание работы программы требует использования специализированной терминологии. Русскоязычная терминология в области обработки видео еще не устоялась, поэтому вначале приведем краткий глоссарий. Там, где источник русскоязычного термина не указан, в качестве такового использовались словари Lingvo и книга [1].
Терминология
Вектор движения (Motion vector) — двумерный вектор, который описывает разницу между координатами декодированного изображения и координатами контрольного изображения (см. рис. 1 [2] слева вверху).

Рис. 1 [2]
Оптический поток (Optical flow) [3] — это изображение видимого движения объектов, поверхностей или краев сцены, полученное в результате относительного движения наблюдателя (глаз или камеры) и сцены. Алгоритмы, основанные на оптическом потоке, используют это относительное перемещение наблюдателя и сцены для регистрации движения, сегментации объектов и мн. др. Другой вариант определения: двумерное поле векторов мгновенных скоростей движения точек яркостной картины по плоскости изображения.
Апсемплинг (Увеличение разрешения, Upsampling) — процесс увеличения частоты дискретизации сигнала. Растровые изображения, например фотографии, являются примером исходных данных с высоким разрешением. Однако часто необходимо увидеть подробности небольшого фрагмента изображения. В этом случае могут применяться методы увеличения разрешения [4].
Большой двоичный объект, «блоб» (blob, BLOB, Binary Large Object) [5] — область соприкасающихся пикселей, находящихся в одном и том же логическом состоянии. Все пиксели изображения, принадлежащие блобу находятся на переднем плане, все остальные пиксели являются фоном. В бинарном изображении пиксели фона имеют значения, равные нулю, а каждый ненулевой пиксель является частью блоба.
Блоб-анализ (blob analysis) [5] изображения представляет собой процесс выделения блобов в заданном изображении и выполнения каких-либо операций над ними. Блоб-анализ используется, когда в изображении необходимо найти блоб с заданными пространственными характеристиками. В частности, если вычисления требуют значительных затрат времени, блоб-анализ позволяет выделить и оставить на изображении только необходимые объекты, экономя таким образом вычислительные ресурсы.
Пороговая обработка (Thresholding) [1] полутонового изображения (то есть такого, которое имеет много градаций яркости) заключается в разделении всех элементов изображения на два класса по признаку яркости, т. е. превращении изображения в бинарное. В бинарном изображении должны быть сохранены интересующие нас детали (например, очертания изображенных объектов) и исключены несущественные особенности (фон). Такое преобразование осуществляется в первую очередь для того, чтобы сократить информационную избыточность изображения, оставить в нем только ту информацию, которая нужна для решения конкретной задачи.
Инициализация
В этой части кода создаются необходимые системные объекты и задаются начальные значения переменных.
Создаем системный объект для чтения видео из мультимедиа-файла (video. MultimediaFileReader).
hbfr = video. MultimediaFileReader('viptraffic. avi');
Создаем системный объект для увеличения разрешения (upsampling) компонент цветности видео.
hcr = video. ChromaResampler(...
'Resampling', '4:2:0 (MPEG1) to 4:4:4', ...
'InterpolationFilter', 'Pixel replication');
Создаем системный объект для преобразования кадров из цветовой модели RGB в палитровое (intensity) изображение с заданной цветовой картой (палитрой). В палитровых изображениях значения пикселов являются ссылками на элементы палитры — двумерного массива, в столбцах которого расположены интенсивности цветовых составляющих одного цвета.
hcsc = video. ColorSpaceConverter('Conversion', 'RGB to intensity');
Создаем системный объект, конвертирующий значения пикселов палитрового изображения в вещественные числа одинарной точности (single).
hidtc = video. ImageDataTypeConverter('OutputDataType', 'single');
Создаем системный объект для оценки направления и скорости перемещения объекта от одного кадра к другому, используя оптический поток.
hof = video. OpticalFlow( ...
'OutputValue', 'Horizontal and vertical components in complex form', ...
'ReferenceFrameDelay', 3);
Создадим и настроим еще два системных объекта. Первый будет вычислять среднее значение скоростей движущихся на видео объектов, второй — вычислять скользящая средняя (running mean) этих скоростей.
hmean1 = video. Mean;
hmean2 = video. Mean('RunningMean', true);
Создадим двумерный медианный фильтр (2-D median filter) для фильтрации гранулированного (пятнистого) шума (speckle noise).
hmedianfilt = video. MedianFilter2D;
Очередной системный объект — морфологическое замыкание, которое будет использовано для заполнения разрывов внутри блобов.
hclose = video. MorphologicalClose('Neighborhood', strel('line',5,45));
Затем, создаем системный объект для блоб-анализа изображения. Целью анализа является выделение на видео изображений автомобилей.
hblob = video. BlobAnalysis( ...
'CentroidOutputPort', false, ...
'AreaOutputPort', true, ...
'BoundingBoxOutputPort', true, ...
'OutputDataType', 'double', ...
'NumBlobsOutputPort', false, ...
'MinimumBlobAreaSource', 'Property', ...
'MinimumBlobArea', 250, ...
'MaximumBlobAreaSource', 'Property', ...
'MaximumBlobArea', 3600, ...
'FillValues', -1, ...
'MaximumCount', 80);
Системный объект MorphologicalErode предназначается для выполнения морфологической эрозии, в результате которой фрагменты изображения, не относящиеся к автомобилям, делаются тоньше.
herode = video. MorphologicalErode('Neighborhood', strel('square',2));
Два следующих объекта предназначены для добавления к изображению новых форм: первый строит вокруг движущихся машин ограничивающие прямоугольники, второй — рисует линии, изображающие векторы движения.
hshapeins1 = video. ShapeInserter( ...
'BorderColor', 'Custom', ...
'CustomBorderColor', [0 1 0]);
hshapeins2 = video. ShapeInserter( ...
'Shape','Lines', ...
'BorderColor', 'Custom', ...
'CustomBorderColor', [255 255 0]);
Следующий системный объект предназначен для вставки в изображение текста, содержащего количество отслеженных автомобилей.
htextins = video. TextInserter( ...
'Text', '%4d', ...
'Location', [0 0], ...
'Color', [1 1 1], ...
'FontSize', 12);
Наконец, создаем объекты VideoPlayer для отображения: оригинального видео; видео с отображением векторов движения; видео, прошедшего пороговую обработку; результирующего видео со счетчиком отслеженных автомобилей.
hVideo1 = video. VideoPlayer('Name', 'Original Video');
hVideo1.Position(1) = round(0.4*hVideo1.Position(1)) ;
hVideo1.Position(2) = round(1.5*(hVideo1.Position(2))) ;
hVideo1.Position([4 3]) = [200 200];
hVideo2 = video. VideoPlayer('Name', 'Motion Vector');
hVideo2.Position(1) = hVideo1.Position(1) + 350;
hVideo2.Position(2) =round(1.5* hVideo2.Position(2));
hVideo2.Position([4 3]) = [200 200];
hVideo3 = video. VideoPlayer('Name', 'Thresholded Video');
hVideo3.Position(1) = hVideo2.Position(1) + 350;
hVideo3.Position(2) = round(1.5*(hVideo3.Position(2))) ;
hVideo3.Position([4 3]) = [200 200];
hVideo4 = video. VideoPlayer('Name', 'Results');
hVideo4.Position(1) = hVideo1.Position(1);
hVideo4.Position(2) = round(0.3*(hVideo4.Position(2))) ;
hVideo4.Position([4 3]) = [200 200];
Цикл обработки видео
Цикл обработки видео использует ранее созданные системные объекты. Выполнение цикла останавливается, когда достигается конец входного файла (это отслеживается системным объектом BinaryFileReader).
Метод системного объекта, который фактически реализует заложенный в объекте алгоритм, называется step. Говоря коротко, step — это то, что обрабатывает данные. Вначале мы создаем системный объект (алгоритм), затем, используя step, отправляем алгоритм на выполнение. Однако функции step гораздо шире. С точки зрения пользователя, step берет на себя значительную часть работы по инициализации и управлению работой алгоритма (в зависимости от состояния системного объекта), для чего раньше, скорее всего, пришлось бы писать программный код самостоятельно.
Каждый системный объект имеет свой собственный метод step, синтаксис которого описывается в документации по данному объекту.
while ~isDone(hbfr)
imrgb = step(hbfr); % Считывание кадра входного видеофайла
image = step(hidtc, imrgb); % Конвертация изображения в single
I = step(hcsc, image); % Конвертация RGB-изображения в палитровое
of = step(hof, I); % Оценка скорости оптического потока
y1 = of.* conj(of);
% Вычисление пороговых значений скорости
vel_th = 0.5 * step(hmean2, step(hmean1, y1));
% Пороговая обработка и удаление гранулированного шума
filteredout = step(hmedianfilt, y1 >= vel_th);
% Выполнение эрозии (для утоньшения участков дороги), следом
% за замыканием (для заполнения разрывов в блобах)
th_image = step(hclose, step(herode, filteredout));
% Оценка площадей и ограничивающих прямоугольников блобов
[area, bbox] = step(hblob, th_image);
% Выбор прямоугольников, лежащих за линией отсчета
Idx = bbox(1,:) > line_row;
% Исключение из кадра объектов, отличных от автомобилей.
% Если площадь блоба составляет более 40% от площади
% ограничивающего прямоугольника, блоб считается автомобилем.
% Если нет, то ограничивающий прямоугольник удаляется
ratio = zeros(1, length(Idx));
ratio(Idx) = single(area(1,Idx))./single(bbox(3,Idx).*bbox(4,Idx));
ratiob = ratio > 0.4;
count = int32(sum(ratiob));
if count > count_old
scount=scount+1; % Число машин
end
count_old = count;
bbox(:, ~ratiob) = int32(-1);
% Рисование ограничивающих прямоугольников вокруг выделенных машин
y2 = step(hshapeins1, image, bbox);
% Отображение числа машин, пересекающих линию отсчета
y2(22:23,:,:) = 1; % Белая линия
y2(1:15,1:30,:) = 0; % Фон отображения счетчика
image_out = step(htextins, y2, scount);
% Генерация координат точек для рисования векторов движения
if firstTime
[R C] = size(of); % Высота и ширина пикселей
RV = borderOffset:decimFactorRow:(R-borderOffset);
CV = borderOffset:decimFactorCol:(C-borderOffset);
[Y X] = meshgrid(CV, RV);
firstTime = false;
end
% Вычисление и рисование векторов движения
tmp = of(RV, CV) .* MotionVecGain;
lines = [X(:)';Y(:)';X(:)' + imag(tmp(:))';Y(:)' + real(tmp(:))'];
mv_video = step(hshapeins2, image, lines);
% Вывод видео
step(hVideo1, image); % Исходное видео
step(hVideo2, mv_video); % Видео с векторами движения
step(hVideo3, th_image); % Видео, прошедшее пороговую обработку
step(hVideo4, image_out); % Видео со счетчиком машин
end

а) б)

в) г)
Рис. 2
Закрытие
Вызов метода release закрывает все открытые файлы или устройства.
release(hbfr);
Источники
1. Цифровая обработка изображений в среде MATLAB. — М.: Техносфера, 2006. — 616 с.
2. http://en. wikipedia. org/wiki/Inter_frame
3. http://ru. wikipedia. org/wiki/Оптический_поток
4. http://ru. wikipedia. org/wiki/Увеличение_разрешения
5. Image Analysis and Processing — http://zone. /devzone/cda/tut/p/id/3470
6. http://ru. wikipedia. org/wiki/YUV
Основные порталы (построено редакторами)
