Main Content

检测交通视频中的汽车

此示例说明如何使用 Image Processing Toolbox™ 可视化和分析视频或图像序列。此示例使用 VideoReader (MATLAB®)、implay 和其他 Image Processing Toolbox 函数来检测交通视频中的浅色汽车。请注意,VideoReader 的有些功能特定于平台,可能无法在某些平台上读取提供的 Motion JPEG2000 视频。

步骤 1:使用 VideoReader 访问视频

VideoReader 函数构造一个多媒体读取器对象,可以从多媒体文件中读取视频数据。有关您的平台支持哪些格式的信息,请参阅VideoReader

使用 VideoReader 访问视频并获取相关基本信息。

trafficVid = VideoReader('traffic.mj2')
trafficVid = 

  VideoReader with properties:

   General Properties:
            Name: 'traffic.mj2'
            Path: '/mathworks/devel/bat/filer/batfs1904-0/Bdoc24a.2528353/build/matlab/toolbox/images/imdata'
        Duration: 8
     CurrentTime: 0
       NumFrames: 120

   Video Properties:
           Width: 160
          Height: 120
       FrameRate: 15
    BitsPerPixel: 24
     VideoFormat: 'RGB24'

get 方法提供有关视频的详细信息,例如视频的持续时间(以秒为单位)。

get(trafficVid)
obj = 

  VideoReader with properties:

   General Properties:
            Name: 'traffic.mj2'
            Path: '/mathworks/devel/bat/filer/batfs1904-0/Bdoc24a.2528353/build/matlab/toolbox/images/imdata'
        Duration: 8
     CurrentTime: 0
       NumFrames: 120

   Video Properties:
           Width: 160
          Height: 120
       FrameRate: 15
    BitsPerPixel: 24
     VideoFormat: 'RGB24'

步骤 2:使用 IMPLAY 浏览视频

使用 implay 浏览视频。

implay('traffic.mj2');

步骤 3:开发您的算法

处理视频数据时,可以从视频中选择一个有代表性的帧并基于该帧开发算法,这样会很有帮助。然后,再将该算法应用于视频中所有帧的处理。

对于此汽车标记应用,请找出一个同时包含浅色汽车和深色汽车的帧。当一个图像具有许多结构时,例如交通视频帧,在尝试检测感兴趣的对象之前尽可能简化图像很有必要。对汽车标记应用来说,实现此目的的一种方法是隐藏图像中不是浅色汽车的所有对象(深色汽车、车道、草地等)。通常,需要结合使用多种方法才能去除这些无关的对象。

从视频帧中去除深色汽车的一种方法是使用 imextendedmax 函数。此函数返回一个二值图像,该图像识别强度值高于指定阈值(称为区域最大值)的区域。图像中像素值低于此阈值的所有其他对象都将成为背景。要消除深色汽车,请确定图像中这些对象的平均像素值。(使用 im2gray 将原始视频从 RGB 转换为灰度。)您可以使用 implay 中的像素区域工具查看像素值。当您调用 imextendedmax 时,请指定平均像素值(或再稍高一些的值)作为阈值。对于此示例,将该值设置为 50。

darkCarValue = 50;
darkCar = im2gray(read(trafficVid,71));
noDarkCar = imextendedmax(darkCar, darkCarValue);
imshow(darkCar)
figure, imshow(noDarkCar)

观察处理后的图像,会发现大部分的深色汽车对象已经去除,但许多其他无关对象仍然存在,特别是车道标志。区域最大值处理不会去除车道标记,因为其像素值高于阈值。要去除这些对象,可以使用形态学函数 imopen。该函数使用形态学处理从二值图像中删除小对象,同时保留大对象。使用形态学处理时,必须决定运算中使用的结构元素的大小和形状。由于车道标志是细长的对象,因此使用半径与车道标志宽度对应的盘形结构元素。您可以在 implay 中使用像素区域工具来估计这些对象的宽度。对于此示例,将该值设置为 2。

sedisk = strel('disk',2);
noSmallStructures = imopen(noDarkCar, sedisk);
imshow(noSmallStructures)

要完成该算法,请使用 regionprops 找到 noSmallStructures 中对象(应只是浅色汽车)的质心。使用此信息将标记定位在原始视频中的浅色汽车上。

步骤 4:将算法应用于视频

汽车标记应用在循环中以一次一帧的方式处理视频。(由于典型视频一般都包含大量帧,因此一次读取和处理所有帧需要大量内存。)

小视频(如本例中的视频)可以一次性处理,并且有许多函数可以提供这种功能。有关详细信息,请参阅Process Image Sequences

为了加快处理速度,请预分配用于存储已处理视频的内存。

nframes = trafficVid.NumberOfFrames;
I = read(trafficVid, 1);
taggedCars = zeros([size(I,1) size(I,2) 3 nframes], class(I));

for k = 1 : nframes
    singleFrame = read(trafficVid, k);

    % Convert to grayscale to do morphological processing.
    I = rgb2gray(singleFrame);

    % Remove dark cars.
    noDarkCars = imextendedmax(I, darkCarValue);

    % Remove lane markings and other non-disk shaped structures.
    noSmallStructures = imopen(noDarkCars, sedisk);

    % Remove small structures.
    noSmallStructures = bwareaopen(noSmallStructures, 150);

    % Get the area and centroid of each remaining object in the frame. The
    % object with the largest area is the light-colored car.  Create a copy
    % of the original frame and tag the car by changing the centroid pixel
    % value to red.
    taggedCars(:,:,:,k) = singleFrame;

    stats = regionprops(noSmallStructures, {'Centroid','Area'});
    if ~isempty([stats.Area])
        areaArray = [stats.Area];
        [junk,idx] = max(areaArray);
        c = stats(idx).Centroid;
        c = floor(fliplr(c));
        width = 2;
        row = c(1)-width:c(1)+width;
        col = c(2)-width:c(2)+width;
        taggedCars(row,col,1,k) = 255;
        taggedCars(row,col,2,k) = 0;
        taggedCars(row,col,3,k) = 0;
    end
end

步骤 5:可视化结果

获取原始视频的帧速率,并使用它查看 taggedCars implay

frameRate = trafficVid.FrameRate;
implay(taggedCars,frameRate);

另请参阅

| | | | | |

相关主题