【问题标题】:Subtract background image from video in matlab在matlab中从视频中减去背景图像
【发布时间】:2015-08-15 12:50:56
【问题描述】:

我正在尝试从视频中读取前 20 帧,将这些图像与我通过取这 20 个图像的中值获得的背景图像一起保存在一个文件夹中。然后我试图从视频中的每一帧中减去这个背景图像并将输出写入一个新视频。但最后,我只在新视频中得到黑色输出并得到以下警告: 警告:没有视频帧写入此文件。该文件可能无效。

在 VideoWriter.VideoWriter>VideoWriter.close 在 307 在 VideoWriter.VideoWriter>VideoWriter.delete 在 256 在 43 帧提取中

我该怎么办?

clear all;
clc;
thresh=100;
workingDir = 'D:/DDP/proj3';
mkdir(workingDir)
mkdir(workingDir,'images')
vid= VideoReader('D:/DDP/sample1.3gp');

for k=1:20
img = readFrame(vid);
filename = [sprintf('%01d',k-1) '.jpg'];
imwrite(img,fullfile(workingDir,'images',filename))    
end
folder = 'D:\DDP\proj3\images\';
filelist = dir( fullfile(folder,'*.jpg') );
filelist = strcat(folder, filesep, {filelist.name});

images = zeros(720,1280,3, numel(filelist), 'double');
for i=1:numel(filelist)
images(:,:,:,i) = double( imread(filelist{i}) );
end
background = uint8(median(images, 4)); 
imwrite(background,'D:\DDP\proj3\images\background.jpg','jpg')

fr_size = size(BW1);
width = fr_size(2);
height = fr_size(1);
fg = zeros(height, width);
vid.CurrentTime = 0;  % Rewind video reader
VW = VideoWriter('D:/DDP/proj3/new');
open(VW);
while hasFrame(vid)
fr = readFrame(vid);
fr_diff = abs(double(fr) - double(background));
for j=1:width
for k=1:height
if ((fr_diff(k,j) > thresh))
fg(k,j) = 255;
else
fg(k,j) = 0;
end
end
end
writeVideo(VW,double(fg)/255);

end
close(VW)
cc=  VideoReader('D:/DDP/proj3/new.avi');
cd= VideoWriter('D:/DDP/proj3/new1');
open(cd);
while hasFrame(cc);
    s=readFrame(cc);
    J = imnoise(s,'salt & pepper',0.02);
    img_filtered = J;
    for c = 1 : 3
    img_filtered(:, :, c) = medfilt2(J(:, :, c), [3, 3]);
    end
writeVideo(cd, double(img_filtered)/255);
end
close(cd);

【问题讨论】:

  • 错误到底发生在哪一行?错误中的行号与代码 sn-p 中的行号不对应。只有 37 行,而报告的行错误在第 43 行。请在代码中描述错误发生的位置。
  • 在大众 = VideoWriter('D:/DDP/new');您没有指定扩展名,因此您将获得 Motion JPEG AVI。仔细检查 CDatas 是否有数据并且在适当的范围内
  • 您永远不会回到视频的开头。第一次调用 hasFrame 时,它会检查第 21 帧。视频是否有 21 帧或更多帧?
  • 视频有 640 帧。但是从第 21 帧开始有关系吗?因为前 20 帧相当于背景图像,所以它们的减法不会给出任何结果。如果我错了,请在这里纠正我,因为我是图像处理方面的新手
  • 背景图为double型,frame为int型。所以这可能是它背后的原因。那么如何将 double 转换为 uint 呢?

标签: matlab image-processing computer-vision


【解决方案1】:

在您的代码中,错误来自您没有将视频阅读器倒回到第一帧这一事实。您发布的代码似乎与您就背景图像的数据类型为双精度类型所做的评论不符。如果你使用 imread 读取背景图片,它应该是 uint8 类型。这是我的建议:

workingDir = 'D:/DDP';
mkdir(workingDir)
mkdir(workingDir,'images')
vid= VideoReader('D:/DDP/samplee.3gp');

for k=1:20
    img = readFrame(vid);
    filename = [sprintf('%01d',kk-1) '.jpg'];
    imwrite(img,fullfile(workingDir,'images',filename))    
end
folder = 'D:\DDP\images\';
filelist = dir( fullfile(folder,'*.jpg') );
filelist = strcat(folder, filesep, {filelist.name});

images = zeros(720,1280,3, numel(filelist), 'double');
for i=1:numel(filelist)
    images(:,:,:,i) = double( imread(filelist{i}) );
end
background = uint8(median(images, 4)); % Convert background image to uint8 type
imwrite(background,'D:\DDP\images\background.jpg','jpg')

vid.CurrentTime = 0;  % Rewind video reader
VW = VideoWriter('D:/DDP/new');
open(VW);
while hasFrame(vid)
    CDatas(:,:,:) = readFrame(vid) - background;     
    writeVideo(VW,CDatas);   
end
close(VW)

【讨论】:

  • 如果我将背景图像转换为 uint8 类型,那么它会变黑。所以减法没有效果,我得到与输出相同的视频。而如果我不将背景转换为 int,那么我会得到所需的背景图像,但由于 readFrame(vid) 是 uint8 类型,因此在减去时会显示错误,因为我无法订阅 int 和 double。
  • 啊。我懂了。 im2double 将uint8 图像转换为double 类型,范围在0 和1 之间。所以当您将其转换回unit8 时,图像将只包含0 和1,即黑色或非常接近黑色。只需使用double 将图像转换为双精度类型就可以了。查看编辑后的代码。
  • 实际上我仍然得到黑色减去的视频。你能给我你的邮件ID,以便我分享视频和其他详细信息吗?
  • 如果我想减去每一帧中的每个像素,我应该怎么做?我想我应该定义一个阈值,如果背景和帧的像素值之间的差异小于该阈值,那么我将该像素值设置为零(即黑色)和 1(否则)。因此我可以获得仅由黑白组成的二进制图像,并且我也可以检测到移动的人。你怎么看?
  • 根据图像的内容,计算许多图像的中值实际上可能会导致与每个图像非常相似的结果。如果然后从每一帧中减去它,您将几乎一无所获。当然,使用阈值拒绝背景是一种有效的方法。您可以阅读:graythresh
猜你喜欢
  • 1970-01-01
  • 2016-02-27
  • 2016-01-08
  • 2014-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-24
相关资源
最近更新 更多