2

I have a video about traffic scene. Now, I want to calculate the percentage of vehicle area on the road area (or the percentage of foreground area on the background area). The first step for this is background extraction. I have read many document and scientific articles about it, one of them recommends to use the mean filter following this formula:

enter image description here

This is the link of that the article. The results are very good, it is exactly what I want.

I followed his formula and I tried to write my code. But It didn't work! Who can help me and give me some advice. This is my code:

clc;    % Clear the command window.
close all;  % Close all figures (except those of imtool.)

imtool close all;  % Close all imtool figures.
clear;  % Erase all existing variables.
workspace;  % Make sure the workspace panel is showing.
fontSize = 14;
%input video;
step = 10;
vob = VideoReader('NKKN.avi');
frame = vob.read(inf);
vidHeight = vob.Height;
vidWidth = vob.Width;
nFrames = vob.NumberOfFrames;
%%% First-iteration background frame
background_frame = double(frame*0);
redbackground_frame = background_frame(:,:,1);
greenbackground_frame = background_frame(:,:,2);
bluebackground_frame = background_frame(:,:,3);
%calculate background
i = 0;
for k = 1:10 %get background from 10 frame (J=10)
    thisframe = double(read(vob, k));
    %background_frame = background_frame + thisframe;
    redbackground_frame = redbackground_frame + thisframe(:,:,1);
    greenbackground_frame = greenbackground_frame + thisframe(:,:,2);
    bluebackground_frame = bluebackground_frame + thisframe(:,:,3);
    i=i+1;
    disp(i);
end

A = redbackground_frame/i;
B = greenbackground_frame/i;
C = bluebackground_frame/i;
background = cat(3,A,B,C);
imshow(background);
saastn
  • 5,717
  • 8
  • 47
  • 78
user3725204
  • 33
  • 1
  • 8
  • 3
    You'll have to be a bit more specific about "not work": do you get any errors? is the output `background` completely off? if you don't tell us what's the problem, how can we help you fix it? – Shai Jun 18 '14 at 07:27
  • BTW, if your temporal window (i.e. `j` as presented in the linked formula) is not too large, you might get better results using `median` that `mean` (L1 vs. L2 regularization that is more robust to outliers). – Shai Jun 18 '14 at 07:33
  • It is best [not to use `i` as a variable in Matlab](http://stackoverflow.com/questions/14790740/using-i-and-j-as-variables-in-matlab). – Shai Jun 18 '14 at 09:48
  • Hi Shai, I have got foreground of my video, now I want to calculate speed of each object that I have detected. but I don't know how to associating the detections corresponding to the same object over time, I found this example and it is exact what I want to, but they use computervision toolbox and I can understand how it work. can you tell me more clearly about that or you can give me a code like that but no use computer vision tool box. – user3725204 Sep 16 '14 at 10:05
  • I'm sorry Shai, I don't know about that. your answers is very helpful. I accepted that but I don't enough reputation to upvote for you. this is link for my question above. can you help me? http://www.mathworks.com/help/vision/examples/motion-based-multiple-object-tracking.html – user3725204 Sep 18 '14 at 02:48

5 Answers5

1

You can maintain a buffer of B frames for a dynamic estimation of backgound

buff = NaN( [vidHeight, vidWidth, 3, B] ); % allocate room for buffer

% process the video
for fi = 1:nFrames
    % read current frame
    thisframe = double(read(vob, k)) / 255; % convert to [0..1] range 

    % update background model
    buff(:, :, :, mod( fi, B ) + 1 ) = thisframe;
    background_L1 = nanmedian( buff, 4 ); % I think this is better than `mean` - try it!
    background_L2 = nanmean( buff, 4 );

    % do whatever processing you need with fi-th frame 
    % and the current background mode...
    % ...
end

Note that if fi < B (i.e., you processed less than B frames) the background model is not stable. I am using NaNs as default values for the buffer and these values are ignored when backgound model is estimated -- this is the reason why I use nanmedian and nanmean instead of simply median and mean.

Shai
  • 111,146
  • 38
  • 238
  • 371
  • thanks so much for your help Shai. I am sorry to have asked unclear. My code have no errors. but the results were not as i expected. the final background I have after run my code is white all. – user3725204 Jun 18 '14 at 17:33
  • I have tried your code for background update, but It not generated background. the result of your code is: background_L2 like fi-th frame, and background_L1 like (fi+1)-th frame. – user3725204 Jun 18 '14 at 17:51
  • this is result of your code: https://lh4.googleusercontent.com/-TVFGFR-mmS4/U6HVmqDINvI/AAAAAAAAMVs/MTGRFcWtmYQ/s1600/www.Aloxovn.com-result_your_code.png – user3725204 Jun 18 '14 at 18:10
  • this is the result I expected: https://lh3.googleusercontent.com/-IC9YIu9vd7k/U6HWo7LS0CI/AAAAAAAAL6k/ziQox3kUq3I/s1600/www.Aloxovn.com-result_of_background_extraction.png – user3725204 Jun 18 '14 at 18:14
  • this is result of my code: https://lh6.googleusercontent.com/-IfxCgDwnvE0/U6HXsSsfQqI/AAAAAAAAL6w/zzCYUd2eTV0/s1600/www.Aloxovn.com-my_result.png – user3725204 Jun 18 '14 at 18:18
  • @user3725204 divide your `background` by 255 to get a non-white result: when you convert images to type double you need to rescale their values in the range of [0..1] otherwise they will be saturated when displayed on screen. – Shai Jun 19 '14 at 05:36
  • @user3725204 I am a little surprised about the results you showed me: what is the buffer size `B` you are using? for how many frames have you iterated before looking at the results - it takes `B` frames for the buffer to fill and for good results to show. – Shai Jun 19 '14 at 05:37
  • in my code, I have tried several value of B such as B = 20, B=10, B=5, B = 50 but the result of L1, L2 is same at all. (I showed result in above comment), and my video have 4800 frames. I show my code that I use your recommendations in the answer below. – user3725204 Jun 24 '14 at 18:12
  • @user3725204 you are skipping frames! if you read every 20th frame and update the `mod 10` slot in the buffer you end up updating the same slot and leaving the rest of the buffer unchanged. try `B = 23` (or some other **prime** number and try to read frames skipping 19 frames (not 20!) at a time if you must. – Shai Jun 24 '14 at 20:30
  • thanks so much Shai, I understood! but I think we have a problem when we use 'nanmedian' and 'nanmean', It recalculate background from B frame of buffer in each loop so it takes so many time and It make my program too slow. may you explain for me about 'nanmedian', what is the different between 'nanmean' and 'nanmedian'. I want to write the code that I only use basic Matlab function. – user3725204 Jun 26 '14 at 17:52
  • @user3725204 you can treat `nanmedian` and `nanmean` as "basic Matlab functions" all they do is compute median/mean and discarding any `NaN` values in the data. In my example, if `B` is not full yet, empty slots have `NaN` values and therefore `nanmedian` and `nanmean` are necessary. If you really need speed `median` is always harder to compute (requires sorting) so you should use the `L2` estimate and give up on the `L1` estimate. – Shai Jun 29 '14 at 06:00
  • @user3725204 just out of curiosity, now that things seems to work for you, which background estimation looks better: the `L1` estimate (using `nanmedian`), or the `L2` estimate (using `nanmean`)? Can you see a difference between the two? – Shai Jun 29 '14 at 06:01
  • hi Shai. I often encounter "out of memory" error when I run my code. sometimes my program can run good with 19 frames in the buffer but sometimes It error with only 7 frames in the buffer. (the error is "Error using permute" and out of memory). in my video. vidHeight =700, vidWidth = 500. my computer. core i3, RAM 2GB. – user3725204 Jul 11 '14 at 05:47
  • this is my memory command: Maximum possible array: 43 MB: Memory available for all arrays: 323 MB; Memory used by MATLAB: 858 MB; Physical Memory (RAM): 1745 MB. I don't know how to fix this error, may you help me? – user3725204 Jul 11 '14 at 06:27
1
vob = VideoReader('NKKN.avi');
frame = vob.read(inf);
vidHeight = vob.Height;
vidWidth = vob.Width;
nFrames = vob.NumberOfFrames;
%allocate room for buffer of 20 frames
buff = NaN( [vidHeight, vidWidth, 3, 20] ); % allocate room for buffer
for fi = 1:20:nFrames
disp(fi);
% read current frame
thisframe = double(read(vob, fi)) / 255; % convert to [0..1] range 
% update background model
buff(:, :, :, mod( fi, 10 ) + 1 ) = thisframe;
background_L1 = nanmedian( buff, 4 );
background_L2 = nanmean( buff, 4 );



hImage = subplot(2, 2, 1);
image(thisframe);
caption = sprintf('thisframe');
title(caption, 'FontSize', fontSize);
drawnow; % Force it to refresh the window.

subplot(2,2,2);
imshow(background_L2);
title('background-L2');

subplot(2,2,3);
imshow(background_L1);
title('background-L1');

end

user3725204
  • 33
  • 1
  • 8
1

Extracting the background of this video https://www.youtube.com/watch?v=URJxS1giCA4&ab_channel=AliShahzil

clear all
close all
reader = VideoReader('C:\Users\Ali Sahzil\Desktop\Media.wmv'); // your video file location
vid = {};
while hasFrame(reader)
    vid{end+1} = im2single(readFrame(reader));
end

bg = mean( cat(4, vid{:}), 4);

x =bg;
imshow( bg );

enter image description here

Syed Ali Shahzil
  • 1,079
  • 1
  • 11
  • 17
0

Here is a very simple solution you can build upon. First you will need a sample background image of the scene with no traffic. We will call this 'bg'.

Here is a simple approach in pseudo-code:

      load in background image 'bg'
      set threshold upper value
      set threshold lower value
      loop until done for each frame
      {
        subtract 'bg' image from your first frame
        if pixel value of foreground > than threshold upper value
        {
          set foreground pixel value to 'nan'
        }
        if pixel value of foreground < than threshold lower value
        {
          set foreground pixel value to 'nan'
        }
        if pixel value of foreground == 0
        {
          set foreground pixel value to 'nan'
        }
      }

This will bracket your foreground images to only show the parts of the scene you are interested in. Note: this process can be greatly enhanced by using a stereoscopic camera to give you depth perception. However, you should be able to build upon this code to remove unwanted parts of your image.

Adam893
  • 143
  • 1
  • 3
  • 16
0

This is actually based on Shai's and user3725204's answers. I didn't use read and NumberOfFrames which are not recommended. I also adopted user3725204's suggestion, since there's no need to read all frames.

function backGrnd = getBackGrnd(filename, nTest, method)
    tic
    if nargin < 2, nTest = 20; end
    if nargin < 3, method = 'median'; end
    v = VideoReader(filename);
    nChannel = size(readFrame(v), 3);
    tTest = linspace(0, v.Duration-1/v.FrameRate , nTest);
    %allocate room for buffer
    buff = NaN([v.Height, v.Width, nChannel, nTest]);
    for fi = 1:nTest
        v.CurrentTime =tTest(fi);
        % read current frame and update model
        buff(:, :, :, mod(fi, nTest) + 1) = readFrame(v);
    end
    switch lower(method)
        case 'median'
            backGrnd = nanmedian(buff, 4);
        case 'mean'
            backGrnd = nanmean(buff, 4);
    end
    toc
end

And the result is like this:

subplot(221); imshow(uint8(TrafficVisionLab.getBackGrnd('traffic.avi', 10, 'mean')));
subplot(222); imshow(uint8(TrafficVisionLab.getBackGrnd('traffic.avi', 10, 'median')));
subplot(223); imshow(uint8(TrafficVisionLab.getBackGrnd('traffic.avi', 50, 'mean')));
subplot(224); imshow(uint8(TrafficVisionLab.getBackGrnd('traffic.avi', 50, 'median')));

enter image description here

Community
  • 1
  • 1
saastn
  • 5,717
  • 8
  • 47
  • 78