2015-08-15 72 views
0

我想從視頻中讀取前20幀,將這些圖像保存在一個文件夾以及通過取這20個圖像的中間值獲得的背景圖像中。然後,我試圖從視頻中的每幀中減去此背景圖像,並將輸出寫入新視頻。但最終,我只是在新視頻中獲得黑色輸出,並收到以下警告: 警告:沒有視頻幀寫入此文件。該文件可能無效。在matlab中從視頻中減去背景圖像

在VideoWriter.VideoWriter> VideoWriter.close在307 在VideoWriter.VideoWriter> VideoWriter.delete在256 在Framextraction在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); 
+0

哪條線會發生錯誤?錯誤中的行號與代碼片段中的行號不對應。只有37行,而報告的行錯誤在43行。請描述代碼中錯誤發生的位置。 – rayryeng

+0

在VW = VideoWriter('D:/ DDP/new');你沒有指定擴展名,所以你會得到一個Motion JPEG AVI。仔細檢查CDatas是否有數據,並且它在適當的範圍內 – paisanco

+0

您永遠不會回到視頻的開頭。第一次調用'hasFrame'時,它會檢查第21幀。視頻是否有21幀或更多幀? – Daniel

回答

0

在您的代碼中,錯誤來自您沒有將視頻閱讀器倒帶到第一幀的事實。您發佈的代碼似乎與您對背景圖片數據類型爲double類型的評論不一致。如果你使用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) 
+0

如果我將背景圖像轉換爲uint8類型,那麼它會變黑。所以減法不起作用,我得到與輸出相同的視頻。而如果我不將背景轉換爲int,那麼我得到所需的背景圖像,但由於readFrame(vid)是一個uint8類型,所以在減去時會顯示錯誤,因爲我無法訂閱int和double。 –

+0

啊。我懂了。 'im2double'將uint8圖像轉換爲範圍在0和1之間的雙重類型。因此,當您將其轉換回unit8時,圖像將僅包含0和1,這是黑色或非常接近黑色。只需使用'double'將圖像轉換爲雙重類型即可。查看編輯的代碼。 – user3667217

+0

其實我仍然看到黑色扣除的視頻。你可以給我你的郵件ID,以便我可以分享視頻和其他細節? –