使用卡尔曼滤波器进行背景减法和前景检测

Posted

技术标签:

【中文标题】使用卡尔曼滤波器进行背景减法和前景检测【英文标题】:Background subtraction And foreground detection using Kalman Filter 【发布时间】:2016-08-02 21:55:08 【问题描述】:

我需要使用卡尔曼滤波器将视频中的背景与前景分开。有人可以给我一些资源或代码示例吗?

更新:我在这里找到了一个很好的例子Traffic detection。它非常适合流量检测,但我想重新调整它以用于人员提取。我发现了一些需要调整的变量,例如:

1. alpha = learning constant
2. K= #of guassians in the mixture
3. T = min. portion of background
4. initVariance = initial variance
5. pixelThresh = threshold condition for computing adaptive process on pixel

这里是主文件的概述(如果您只是想要一个概述)


function foregroundEstimation(movie)

%Load video into memory and prepare output video for writing

v = VideoReader(movie);
numFrames = 150;
foregroundVideo = VideoWriter('foreground.avi');
open(foregroundVideo);

%video constants

initFrame = read(v,1);
global height;
global width;
height = size(initFrame,1); 
width = size(initFrame,2);



%initialize GMM parameters: (based upon Stauffer notation)
%http://www.ai.mit.edu/projects/vsam/Publications/stauffer_cvpr98_track.pdf

% alpha = learning constant
%  K= #of guassians in the mixture
% T = min. portion of background
% initVariance = initial variance
% pixelThresh = threshold condition for computing adaptive process on pixel

alpha=0.05;  % 0.05
K=5;         % 5
global T;    % T = 0.8
T=0.8;

global initVariance;
initVariance=75; % 75
pixelThresh=45; % 45
referenceDistance = 40; % 40 %shortcut to speed up processing time. Compare current pixel to pixel referenceDistance frames back and skip adaptive process if similar. Downside is doesn't collect background evidence as well.
sideWeight = (K-1)/(1-T);
global matchThres;
matchThres = sqrt(3);
global ccThreshold;
ccThreshold = 9000;  % 5000
global deltaT;
deltaT = 1;
global numParticles;
numParticles = 100;

trackingOn = 0; % will superimpose tracking color marker on detected vehicles in output video. tackingOn should equal 1 or 0

prevCentSize = 0;


%structures to pass information between frames for detection purposes.
field = 'f';
filterValue = [];[];;
prevFilter = struct(field,filterValue);
modelValue = [];prevFilter;
prevModel = struct(field,modelValue);

%initiailze video process components
initColorBoxes();


foreFrame = zeros(height,width,3);
backFrame = zeros(height,width,3);

%map represents pixels at a given frame to perform adaptive process
pixThreshMap = ones(height,width);


%individual pixel process components
pixel = zeros(3,1);
pixMean = zeros(3,1,K);
pixVar = ones(1,K);
pixWeight = zeros(1,K);

%global pixel process components
globalWeight = (ones(height,width,K)/sideWeight);
globalWeight(:,:,1) = T;
%globalWeight = (ones(height,width,K)/K);
globalMean = zeros(height,width,3,K);
globalVar = ones(height,width,K);




%=====================================================
%Extract Foreground and Background by K-mixture model
%=====================================================
%initialize g-mixture model
globalVar = globalVar*initVariance;

for k=1:K
globalMean(:,:,1,k)=initFrame(:,:,1);
globalMean(:,:,2,k)=initFrame(:,:,2);
globalMean(:,:,3,k)=initFrame(:,:,3);
end;


distVec = zeros(numFrames,1);

%adaptive g-mixture background segmentation
for frameIndex=2:numFrames
%get current frame and the refernece frame
%tic;
frameIndex
currentFrame = double(read(v,frameIndex));



if (frameIndex<=referenceDistance)
referenceFrame= double(read(v,1));
else
referenceFrame= double(read(v,frameIndex-referenceDistance));
end;

frameDifference = abs(currentFrame - referenceFrame);

%creates map of pixel locations where we will perform adaptive process. Based
%upon threshold that detects low change regions based on previous frame in
%order to save computation.
pixThreshMap = min(sum(+(frameDifference(:,:,:)>pixelThresh),3),1);



for index=1:3
  backFrame(:,:,index)=(+(pixThreshMap(:,:)==0)).*currentFrame(:,:,index);      
end;

%extract the parts considered "stable background" from current frame

%reset foreground frame
foreFrame = ones(height,width,3)*255;

%gaussian mixture matching & model updating



[i,j]=find(pixThreshMap(:,:)==1);


%loop through every pixel location where adaptive process should be performed
for k = 1:size(i,1)

    pixel = reshape(currentFrame(i(k),j(k),:),3,1);
    pixMean = reshape(globalMean(i(k),j(k),:,:),3,1,K);
    pixVar = reshape(globalVar(i(k),j(k),:,:),1,K);
    pixWeight=reshape(globalWeight(i(k),j(k),:),1,K);

    %update gaussian mixture according to new pix value
    match=matchingCriterion(pixMean,pixVar,pixel);
    matchWeight = 0;

    if(match>0)
        %match found so update weights/normalize
        pixWeight = (1-alpha)*pixWeight;
        pixWeight(match)= pixWeight(match) + alpha;
        pixWeight = pixWeight/sum(pixWeight);
        matchWeight = pixWeight(1,match);

        %NOTE ALPHA SHOULD BE REPACED WITH SOME KIND OF RHO EVENTUALLY
        %WHERE RHO IS PRODUCT OF ALPHA AND CONDITIONAL PROBABILITY MEASURE

        %update variance
        pixVar(:,match) = (1-alpha)*pixVar(:,match) + ...
        alpha*(pixel - pixMean(:,:,match))'*(pixel-pixMean(:,:,match));

        %update mean
        pixMean(:,:,match) = (1-alpha)*pixMean(:,:,match) + alpha*pixel;



    else
        %no match currently found.
        %replace one with lowest sigma value

        rankVector = pixWeight./sqrt(pixVar(1,:));
        [mini minIndex] = min(rankVector);

        pixMean(:,:,minIndex) = pixel;  
        pixVar(:,minIndex) = initVariance;  
    end

    %rerank all pixel components
    rankCriterionVector = pixWeight./sqrt(pixVar(1,1,:)); 
    [rankSort rankIndex] = sort(rankCriterionVector);

    pixMean = pixMean(rankIndex);
    pixVar = pixVar(rankIndex);
    pixWeight = pixWeight(rankIndex);


    %repopulate global structures with updated values
    globalWeight(i(k),j(k),:) = pixWeight(:,1);
    globalMean(i(k),j(k),:,:) = pixMean(:,1,:);
    globalVar(i(k),j(k),:,:) = pixVar(:,:,:);

    %now need to perform the background segmentation based upon weight
    %threshold

    bgIndex = segmentBackground(pixWeight);
    if(ismember(matchWeight, pixWeight))
        matchIndex = find(pixWeight == matchWeight,1);
    else
        matchIndex = 0;
    end

    if((matchIndex>=bgIndex) || (matchIndex == 0))

        %also check against initFrame for match
        %NOTE CHANGE
        if(initMatch(initFrame(i(k),j(k),:),pixel) == 0)
          foreFrame(i(k),j(k),:) = pixel;   
        end 

    end


end


%Now write foreground frame to foreground estimation video
contrastFrame = foreFrame/max(abs(foreFrame(:)));

%remove all connected components associated with foreground objects that are smaller than what we expect a vehicle should be.
[cleanFrame centroids]= connectedComponentCleanup(contrastFrame);

if(trackingOn == 1)
if(size(centroids,1) > prevCentSize)
   prevModel = addModel(prevModel, centroids, height, width);
elseif (size(centroids,1) < prevCentSize)
   prevModel = removeModel(prevModel, centroids, height, width);
end


if(size(centroids,1) > 0)
    %implies there is a car in frame for tracking
    [curModel orderedCentroids] = vehicleTracking(centroids, prevModel);
    prevModel = curModel;
    trackFrame = colorBox(cleanFrame, curModel,orderedCentroids, height, width);  
else
    trackFrame = cleanFrame;
end

else
   trackFrame = cleanFrame; 
end

writeVideo(foregroundVideo,trackFrame); 
prevCentSize = size(centroids,1);
end

谢谢。

【问题讨论】:

相关例子:- mathworks.com/help/vision/examples/… 【参考方案1】:

基本上这不是卡尔曼滤波器的任务,看看opencv中的背景减法。 之后可以使用卡尔曼滤波器来跟踪帧之间的对象,您可以在这里查看示例 http://studentdavestutorials.weebly.com/kalman-filter-with-matlab-code.html

【讨论】:

是的,我想使用卡尔曼滤波器来跟踪前景中的对象,因为我正在处理视频文件... 顺便说一句,在这种情况下,您不受卡尔曼滤波器的限制,实际上它是非常基本的方法。您可以寻找视频对象跟踪挑战来寻找高级挑战votchallenge.net/challenges.html

以上是关于使用卡尔曼滤波器进行背景减法和前景检测的主要内容,如果未能解决你的问题,请参考以下文章

语音去噪基于matlab谱减法+维纳滤波+卡尔曼滤波语音去噪含Matlab源码 1881期

Opencv Python卡尔曼滤波器预测结果查询

对象跟踪中的遮挡处理

使用 Opencv C++ 中给定对象的 X,Y 进行卡尔曼滤波器跟踪

卡尔曼滤波器(目标跟踪一)(上)

OpenCV 和 Python - 如何使用卡尔曼滤波器从 OpenCV 检测到的不规则多边形中过滤噪声?