实现目标及说明
MATLAB——编程实现基于平均背景法的视频运动目标检测,并且要不断更新背景。
网上找到的很多关于运动目标检测的,多数是用OpenCV或者Python来解决的,奈何我都不会,我不是这个研究方向的,只能在网上不断摸索找到用Matlab解决这个问题的办法。
代码及说明
这个代码需要完善,检测结果不那么完美,只提供一个参考,完整代码如下
% 基于平均背景法的视频运动目标检测(会更新背景) %
clc;
clear;
video_det = VideoReader('visiontraffic.avi'); %读取视频
vidHeight = video_det.Height; %视频高度
vidWidth = video_det.Width; %视频宽度
nFrames = video_det.NumberOfFrames; %视频总帧数
s = read(video_det,[1,250]); %读取视频帧,不可以用readFrame函数,会冲突
%s就是个大小为视频总帧数的4维数据,s(:,:,:,1)存放的第一帧的图
rate = video_det.FrameRate; %视频帧速
fileName = 'result_'; %每一帧图片名称前缀
N = 30; %当背景的帧数
%平均背景法均值与标准差
tbg.cdata = 0;
tdg.cdata = 0;
%标准差系数
b = 0.5;
c = 0.2;
b1 = 1/b;
c1 = 1/c;
%背景更新系数
a = 0.65;
a1 = 1/a;
a2 = 1/(1-a);
for k=1:250 %循环次数为读取的视频帧数
im11 = s(:,:,:,k); %读取每一帧
mov(k).cdata = im2double(rgb2gray(im11)); %转化为灰度图
if(k<=N) %取前N帧作为背景
bg(k).cdata = im2double(rgb2gray(im11));
tbg.cdata = tbg.cdata + bg(k).cdata;
tdg.cdata = tdg.cdata + bg(k).cdata.^2;
if(k == N) %平均背景法
ttbg.cdata = tbg.cdata/N;
ttdg.cdata = tdg.cdata/N - ttbg.cdata.^2;
end
else
% tttdg.cdata = sqrt(ttdg.cdata);
reg_im = (mov(k).cdata >= ttbg.cdata - ttdg.cdata/b1)&(mov(k).cdata <= ttbg.cdata + ttdg.cdata/c1); %前景检测策略
%背景更新
ttbg.cdata = ttbg.cdata/a2 + mov(k).cdata/a1;
ttdg.cdata = ttdg.cdata/a2 + ((mov(k).cdata - ttbg.cdata).^2)/a1;
%显示目标检测框
SE = ones(5,5);
%bwmorph对二值图像进行形态学操作,
%bwmorph(BW,operation,n)应用形态学操作n次
%'dilate'利用结构ones(3)执行膨胀操作
%imerode实现图像腐蚀。Imerode(X,SE),X是待处理的图像,SE是结构元素对象
i3= bwmorph(reg_im,'dilate',9);
i3 = imerode(i3, SE);
noSmall = bwareaopen(i3, 1500); %删除小面积
[L, nm] = bwlabel(noSmall,8); %找出8连通域并标记
imshow(im11);
% 画矩形框
for i = 1:nm
[r,c] = find(L == i);
left = min(c);
right = max(c);
top = min(r);
buttom = max(r);
width = right - left + 1;
height = buttom -top + 1;
rectangle('Position', [left, top, width, height],'EdgeColor',[1,0,0]);
end
frame=getframe(gcf);
result=frame2im(frame);
strtem = strcat(fileName,int2str(k),'.','bmp');
imwrite(result,strtem);
end
end
% 生成视频
dn='C:\Users\Weijian Lu\Desktop\Visual_FPGA\Work8';
picname=fullfile( dn, strcat('*.','bmp'));
picname=dir(picname);
aviname='detect_vedio.avi';
aviobj = VideoWriter(aviname);
open(aviobj);
for i=1:length(picname)
picdata=imread( fullfile(dn, (picname(i,1).name)));
if ~isempty( aviobj.Height)
if size(picdata,1) ~= aviobj.Height || size(picdata,2) ~= aviobj.Width
close(aviobj);
delete( aviname )
error('所有图片的尺寸要相同!!');
end
end
writeVideo(aviobj,picdata);
end
close(aviobj);
结果部分截图如下图
完整文件获取
完整文件包括Matlab代码以及测试的视频
链接:https://pan.baidu.com/s/1kfdLntbjgBVwXTfvgvdE_w
提取码:7bsp