帧间差分法是对时间上连续的两帧图像进行差分运算,得到差分图像。
做帧差:采集前一帧图像,第二帧图像,先对其进行灰度化处理。然后前后做差,将差分后的图像二值化后进行边缘检测
如图所示运动的球体被识别(黄框),上图为原视频,下图为识别结果。
附代码:
主函数(帧差及图像处理)
clc;
clear;
pathname='C:\Users\Administrator\Desktop\work\data\';%二值化图像路径
videopath='C:\Users\Administrator\Desktop\work\video\';%视频帧路径
videoObj = VideoReader('sample.avi');%读视频文件
nframes = get(videoObj, 'NumFrames');%获取视频文件帧个数
lenth=nframes-2;%处理后帧数
level=0.1;%二值化阈值
for k = 1 : lenth
currentFrame1 = read(videoObj, k);%读取第i帧
currentFrame2 = read(videoObj, k+1);
grayFrame1 = rgb2gray(currentFrame1);%灰度化
grayFrame2 = rgb2gray(currentFrame2);
difgrayFrame= grayFrame2 - grayFrame1;%邻帧差
k1=num2str(k);
filename=[k1,'.jpg'];
imwrite(currentFrame1,[videopath,filename]);
bw=im2bw(difgrayFrame,level);%二值化
se = strel('disk',20);%构造闭运算算子
closeBW=imclose(bw,se);%闭运算
imwrite(closeBW,[pathname,filename]);% 将每步处理后的图像到某个目录下
[xMax,xMin,yMax,yMin]=draw([pathname,filename]);
data = imread([videopath, filename]);
pt=[xMin,yMin];
wSize=[xMax-xMin,yMax-yMin];
des = drawRect(data,pt,wSize,5 );
subplot(2,1,1)
imshow(data)
subplot(2,1,2)
imshow(des)
imwrite(des,[videopath,filename]);
end
cd(videopath); %读取所有的jpg图片
allnames = struct2cell(dir('*.jpg'));
[difgrayFrame,len]=size(allnames);
aviobj = VideoWriter('C:\Users\Administrator\Desktop\work\save_video2.avi');%视频存储位置
aviobj.FrameRate = 25; %设置帧率
open(aviobj) %制作视频
for i = 1:lenth
name = [num2str(i),'.jpg'];
frame = imread(name);
writeVideo(aviobj,frame);
end
close(aviobj)
求方框
function[xMax,xMin,yMax,yMin]=draw(c)
img = imread(c);
imgTh = im2uint8(img);
angle = 0;
imgRotated = double(imrotate(imgTh,angle,'bicubic','loose'));
[row, col] = size(imgRotated);
%%%判断最小外接矩形的边界
for i = 1 : row
if sum(imgRotated(i, :)) > col
break;
end
end
yMinTest = i;
for i = row : -1 : 1
if sum(imgRotated(i, :)) > col
break;
end
end
yMaxTest = i;
for i = 1 : col
if sum(imgRotated(:, i)) > row
break;
end
end
xMinTest = i;
for i = col : -1 : 1
if sum(imgRotated(:, i)) > row
break;
end
end
xMaxTest = i;
%%%判断最小外接矩形的边界
if angle == 0 || nowSize < typicalSize
xMin = xMinTest;
yMin = yMinTest;
xMax = xMaxTest;
yMax = yMaxTest;
end
画方框
function [ dest ] = drawRect( src, pt, wSize, lineSize, color )
%----------------------------------------------------------------------
%输入:
% src: 原始图像,可以为灰度图,可为彩色图
% pt: 左上角坐标 [x1, y1]
% wSize: 框的大小 [wx, wy]
% lineSize: 线的宽度
% color: 线的颜色 [r, g, b]
%----------------------------------------------------------------------
%输出:
% dest: 画好了的图像
%----------------------------------------------------------------------
%判断输入参数个数
if nargin < 5
color = [255 255 0];
end
if nargin < 4
lineSize = 1;
end
if nargin < 3
disp('输入参数不够 !!!');
return;
end
%判断框的边界问题
[yA, xA, z] = size(src);
x1 = pt(1);
y1 = pt(2);
wx = wSize(1);
wy = wSize(2);
if x1>xA || ...
y1>yA||...
(x1+wx)>xA||...
(y1+wy)>yA
disp('画的框将超过图像 !!!');
return;
end
%如果是单通道的灰度图,转成3通道的图像
if 1==z
dest(:, : ,1) = src;
dest(:, : ,2) = src;
dest(:, : ,3) = src;
else
dest = src;
end
%开始画框图
for c = 1 : 3 %3个通道,r,g,b分别画
for dl = 1 : lineSize %线的宽度,线条是向外面扩展的
d = dl - 1;
dest( y1-d , (x1-d):(x1+wx+d) , c ) = color(c); %上方线条
dest( y1+wy+d , (x1-d):(x1+wx+d) , c ) = color(c); %下方线条
dest( (y1-d):(y1+wy+d) , x1-d , c ) = color(c); %左方线条
dest( (y1-d):(y1+wy+d) , x1+wx+d , c ) = color(c); %左方线条
end
end %主循环尾
end %函数尾
实例视频与结果
sample
save_video2