Saturday, May 22, 2010

High complexity background subtraction using mixture of guassian

The mean u of each Gaussian function, can be thought of as an educated guess of the pixel value in the next framewe assume here that pixels are usually background. The weight and standard deviations of each component are measures of our confidence in that guess (higher weight & lower σ = higher confidence). There are typically 3-5 Gaussian components per pixel—the number typically depending on memory limitations.

In the image, the left images show the startup where all pixels are assumed to be background.through out the course of the video the background will be constructed. in contrast to median filter where it estimates and clears up the background.



Code:

% ----------------------- frame size variables -----------------------

fr = source(1).cdata; % read in 1st frame as background frame
fr_bw = rgb2gray(fr); % convert background to greyscale
fr_size = size(fr);
width = fr_size(2);
height = fr_size(1);
fg = zeros(height, width);
bg_bw = zeros(height, width);

% --------------------- mog variables -----------------------------------

C = 3; % number of gaussian components (typically 3-5)
M = 3; % number of background components
D = 2.5; % positive deviation threshold
alpha = 0.01; % learning rate (between 0 and 1) (from paper 0.01)
thresh = 0.25; % foreground threshold (0.25 or 0.75 in paper)
sd_init = 6; % initial standard deviation (for new components) var = 36 in paper
w = zeros(height,width,C); % initialize weights array
mean = zeros(height,width,C); % pixel means
sd = zeros(height,width,C); % pixel standard deviations
u_diff = zeros(height,width,C); % difference of each pixel from mean
p = alpha/(1/C); % initial p variable (used to update mean and sd)
rank = zeros(1,C); % rank of components (w/sd)


% --------------------- initialize component means and weights -----------

pixel_depth = 8; % 8-bit resolution
pixel_range = 2^pixel_depth -1; % pixel range (# of possible values)

for i=1:height
for j=1:width
for k=1:C

mean(i,j,k) = rand*pixel_range; % means random (0-255)
w(i,j,k) = 1/C; % weights uniformly dist
sd(i,j,k) = sd_init; % initialize to sd_init

end
end
end

%--------------------- process frames -----------------------------------

for n = 1:length(source)

fr = source(n).cdata; % read in frame
fr_bw = rgb2gray(fr); % convert frame to grayscale

% calculate difference of pixel values from mean
for m=1:C
u_diff(:,:,m) = abs(double(fr_bw) - double(mean(:,:,m)));
end

% update gaussian components for each pixel
for i=1:height
for j=1:width

match = 0;
for k=1:C
if (abs(u_diff(i,j,k)) <= D*sd(i,j,k)) % pixel matches component

match = 1; % variable to signal component match

% update weights, mean, sd, p
w(i,j,k) = (1-alpha)*w(i,j,k) + alpha;
p = alpha/w(i,j,k);
mean(i,j,k) = (1-p)*mean(i,j,k) + p*double(fr_bw(i,j));
sd(i,j,k) = sqrt((1-p)*(sd(i,j,k)^2) + p*((double(fr_bw(i,j)) - mean(i,j,k)))^2);
else % pixel doesn't match component
w(i,j,k) = (1-alpha)*w(i,j,k); % weight slighly decreases

end
end

w(i,j,:) = w(i,j,:)./sum(w(i,j,:));

bg_bw(i,j)=0;
for k=1:C
bg_bw(i,j) = bg_bw(i,j)+ mean(i,j,k)*w(i,j,k);
end

% if no components match, create new component
if (match == 0)
[min_w, min_w_index] = min(w(i,j,:));
mean(i,j,min_w_index) = double(fr_bw(i,j));
sd(i,j,min_w_index) = sd_init;
end

rank = w(i,j,:)./sd(i,j,:); % calculate component rank
rank_ind = [1:1:C];

% sort rank values
for k=2:C
for m=1:(k-1)

if (rank(:,:,k) > rank(:,:,m))
% swap max values
rank_temp = rank(:,:,m);
rank(:,:,m) = rank(:,:,k);
rank(:,:,k) = rank_temp;

% swap max index values
rank_ind_temp = rank_ind(m);
rank_ind(m) = rank_ind(k);
rank_ind(k) = rank_ind_temp;

end
end
end

% calculate foreground
match = 0;
k=1;

fg(i,j) = 0;
while ((match == 0)&&(k<=M))

if (w(i,j,rank_ind(k)) >= thresh)
if (abs(u_diff(i,j,rank_ind(k))) <= D*sd(i,j,rank_ind(k)))
fg(i,j) = 0;
match = 1;
else
fg(i,j) = fr_bw(i,j);
end
end
k = k+1;
end
end
end

figure(1),subplot(3,1,1),imshow(fr)
subplot(3,1,2),imshow(uint8(bg_bw))
subplot(3,1,3),imshow(uint8(fg))
end

14 comments:

  1. hi, thank you for the code, but i have question, normally, we model each pixel as a mixture of gaussians, then, we decide which gaussians belong to the background, and which ones belong to the foreground. That's why, we order the gaussians by w/sigma, then, we select the first B distributions as the background model, the problem in this code, you compute bg_bw by selecting all gaussians, (i mean you compute the bg_bw even before sorting the gaussians without taking into account the importance of the gaussian). Only for foregound mask calculation, you select the first B distributions.
    I think it is an error since when i test the code, i still see moving parts in the background.
    I believe in your code, for background calculation, you didnot take into account only pixels that dont belong to any gaussian distribution, otherwise all gaussians are belonged to the background model.
    Am I wrong?
    I am waiting your answer and thank you in advance.
    Best regards!

    ReplyDelete
  2. Hi, can you give me name of the paper that you used to do this code???

    Thanks

    ReplyDelete
  3. Hi, can you give me name of the paper that you used to do this code???
    please

    Thanks

    ReplyDelete
  4. ??? Undefined function or method 'select' for input arguments of
    type 'uint8'.

    Error in ==> o1 at 21
    [ cmin, cmax, rmin, rmax ] = select( Image1 );

    this error occur ....how to remove this error sir..please

    ReplyDelete
  5. fr = source(1).cdata; % read in 1st frame as background frame

    i am getting error in this line
    Error in ==> dj_vid
    at 2
    fr = source(1).cdata;
    % read in 1st frame
    as background frame

    can you rectify this error

    ReplyDelete
    Replies
    1. Hi, I am still learner of GMM.
      If I am not wrong, we have yet to define what is our video source (since we are trying to access the "cdata" from the "source" structure)

      I have also found this link that has the same issue. In fact, it also shows that there is supposed to be a line that declares the source of movie file: http://www.mathworks.ch/matlabcentral/newsreader/view_thread/311154

      hope it still helps ;)

      Delete
  6. hey this code video is running very 2 slow.Is there any way to make it run video at normal speed?

    ReplyDelete
    Replies
    1. find out frame per second(fps) rate of video
      search for "pause" in the code
      then change it to pause(1/fps)

      Delete
    2. can u explain how this idea work?

      Delete
  7. سلام
    میشه لطفا بگید از چه مقاله ای استفاده کردید؟
    ممنون

    ReplyDelete
  8. سلام میشه لطفا بگید از چه مقاله استفاده کردید

    ReplyDelete
  9. سلام میشه لطفا بگید از چه مقاله استفاده کردید

    ReplyDelete
  10. this code is taking too much running time. is it? and optimization of parameters is not done here using EM algorithm.

    ReplyDelete
  11. what is the change in code for right side image? can you share?

    ReplyDelete