检测交通视频中的汽车
此示例说明如何使用 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);
另请参阅
视频查看器 | VideoReader
| rgb2gray
| imextendedmax
| imopen
| regionprops
| bwareaopen