Code covered by the BSD License  

Highlights from
Detect & Present movements. Mammal Visual system

image thumbnail

Detect & Present movements. Mammal Visual system

by

 

24 Oct 2011 (Updated )

This function tracks and presents moving regions in real time from still camera or file.

markMovesInCamera(videoSource, moveTresh, strelOpen, strelClose)
function markMovesInCamera(videoSource, moveTresh, strelOpen, strelClose)
%% function markMovesInCamera(inVideo, moveTresh, strelOpen, strelClose)
% This function tracks and presents moving regions in a video filmed by a
%  still USB camera
%
%% Syntax
%  markMovesInCamera(inVideo);
%  markMovesInCamera(inVideo, moveTresh);
%  markMovesInCamera(inVideo, moveTresh, strelOpen);
%  markMovesInCamera(inVideo, moveTresh, strelOpen, strelClose);
%
%% Description
% This functions presents a figure with only moving regions of the datya
% filmed by a camera. The user can control several parameters, to achive
% the presentation of regions he is interested in. This function can be
% though of as a mammal vision system simulation (some mammals, like dogs,
% see only object that move).
%
%% Input arguments (defaults exist):
%   videoSource- vidoe data device (usually USB camera)
%   moveTresh- used to deetct movements. Pixels with value above this
%       treshold are assumed to include movements. 
%   strelOpen- a structuring element, and integer value used to define
%       a structuring element dimentions, or a matrix of logicals used to
%       define the presneted ROI dimentions. In other worlds defines the
%       area around detected movements to be presented. Larger value will
%       resul in larger region.
%   strelClose- a structuring element, and integer value used to define
%       a structuring element dimentions, or a matrix of logicals. Those
%       define the speed of "aging", or hsitorical data influencue on
%       current figure. It defines how the ROI of previous frame infleuemce
%       ROI of current frame. Larger value will result in fatser aging- old
%       ROI data will be removed fatser. Small value will result in slow
%       "aging"- areas with movements in previous frames, will be preserved
%       and presenetd in longer period.
%
%% Output arguments
%   None. Movements are presenetd on a figure;
%
%% Issues & Comments 
% Camera is assumed to be still.
% Sometimes, whole frame is detceted as moving. Seems like a camera
% issue...
% Function is actually a combintion of IMAQMOTION by David Tarkowski (many
% thanks and big respect to the author. See
% http://www.mathworks.com/matlabcentral/fileexchange/5470-imaqmotion-image-acquisition-motion-detection
% and my fuction markMovesInVideo.
%
%% Example
% videoSource=videoinput('winvideo', 1);
% moveTresh=30;
% strelOpen=2;
% strelClose=2;
% markMovesInCamera(videoSource, moveTresh, strelOpen, strelClose);
%
%
%% See also
% IMAQMOTION
% VIDEOINPUT
% markMovesInVideo
%
%% Revision history
% First version: Nikolay S. 2011-10-21.
% Last update:   Nikolay S. 2011-10-24.
%
% *List of Changes:*
%

%% Default parameters
if nargin<4
    strelClose=2;
    if nargin<3
        strelOpen=2;
        if nargin<2
            moveTresh=35;
            if nargin==0
                error('MATLAB:markMovesInCamera:error',...
                    'Input source definition is missing.')
            end
        end
    end
end
if isnumeric(strelOpen)
    strelOpen  = strel('disk', strelOpen , 0); 
elseif ~(strcmpi(class(strelOpen), 'strel') || islogical(strelOpen))
    error('MATLAB:markMovesInCamera:error',...
                    'Bad strelOpen input.')
end
if isnumeric(strelClose)
    strelClose  = strel('disk', strelClose , 0); 
elseif ~(strcmpi(class(strelClose), 'strel') || islogical(strelClose))
    error('MATLAB:markMovesInCamera:error',...
                    'Bad strelClose input.')
end
appTitle = 'Camera Motion Detector';

%% Almost unchanged code adopted from IMAQMOTION.
% My thanks and bif respect to the author: David Tarkowski. 
% See http://www.mathworks.com/matlabcentral/fileexchange/5470-imaqmotion-image-acquisition-motion-detection
try
    % Make sure we've stopped so we can set up the acquisition.
    stop(videoSource);
    
    % Configure the video input object to continuously acquire data.
    triggerconfig(videoSource, 'manual');
    set(videoSource, 'Tag', appTitle, 'FramesAcquiredFcnCount', 1, ...
        'TimerFcn', @localFrameCallback, 'TimerPeriod', 0.1,...
        'ReturnedColorSpace','rgb');
    % set colormap colormap('default'),'colorcube','hsv' or ycbcr2rgb for
    % YUV
    
    % Check to see if this object already has an associated figure.
    % Otherwise create a new one.
    ud = get(videoSource, 'UserData');
    if ~isempty(ud) && isstruct(ud) && isfield(ud, 'figureHandles') ...
            && ishandle(ud.figureHandles.hFigure)
        appdata.figureHandles = ud.figureHandles;
        figure(appdata.figureHandles.hFigure)
    else
        appdata.figureHandles = localCreateFigure(videoSource, appTitle);
    end

    % Store the application data the video input object needs.
    % prepare motion detectin, aging and region conenction parameters
    appdata.background = [];
    appdata.prevMoveMask=false(fliplr(get(videoSource,'VideoResolution')));
    appdata.moveTresh=moveTresh;
    appdata.strelOpen=strelOpen;
    appdata.strelClose=strelClose;
    videoSource.UserData = appdata;

    % Start the acquisition.
    start(videoSource);

    % Avoid peekdata warnings in case it takes too long to return a frame.
    warning off imaq:peekdata:tooManyFramesRequested
catch
    % Error gracefully.
    stop(videoSource);
%     delete(videoSource);
    error('MATLAB:imaqmotion:error', ...
        sprintf('IMAQMOTION is unable to run properly.\n%s', lasterr))
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function localFrameCallback(vid, event)
% Executed by the videoinput object callback 
% to update the image display.

% If the object has been deleted on us, 
% or we're no longer running, do nothing.
if ~isvalid(vid) || ~isrunning(vid)
    return;
end

% Access our application data and parameters
appdata = get(vid, 'UserData');
background = appdata.background;
moveTresh=appdata.moveTresh;
strelOpen=appdata.strelOpen;
strelClose=appdata.strelClose;
prevMoveMask=appdata.prevMoveMask;

% Peek into the video stream. Since we are only interested
% in processing the current frame, not every single image
% frame provided by the device, we can flush any frames in
% the buffer.
frame = peekdata(vid, 1);
if isempty(frame),
    return;
end
flushdata(vid);

% First time through, a background image will be needed.
if isempty(background),
    background = getsnapshot(vid);
end

I = imabsdiff(frame, background);
% set(figData.hImage, 'CData', I);

% Update the patch to the new level value.
graylevel = graythresh(I);
level = max(moveTresh, floor(100*graylevel)); 
currMoveMask=false(size(I, 1), size(I, 2)); % Init current movements mask
nClrs=size(I, 3);

% Detect movement on every color (operation on intensity/grayscale data is
% also an option)
for iClr=1:nClrs
    currMoveMask=currMoveMask | (I(:, :, iClr)>level);
end

% Apply "aging" to historical data via Morpohological Erode operator
prevMoveMask= imerode(prevMoveMask, strelClose);
% Aging is impossible if whole mask is true, prevent that.
if all(prevMoveMask)
    prevMoveMask=false(size(prevMoveMask));
end

currMoveMask= imdilate(currMoveMask, strelOpen); % Connect isolated 
% movement elemnets to larger regions via Morpohological Dilate operator
currMoveMask=currMoveMask | prevMoveMask; % Combine previous and current masks

% Crop only relevant parts of image
image2Show=0*frame;
currMoveMask3D=repmat(currMoveMask, [1, 1, nClrs]);
image2Show(currMoveMask3D)=frame(currMoveMask3D);

% While figure isn't closed...
if ~ishandle(appdata.figureHandles.hFigure),
    stop(vid);
    return;
end

% Update the figure
set(appdata.figureHandles.hImage, 'CData', image2Show);
drawnow;

% Update application data for next frame
appdata.background = frame;
appdata.prevMoveMask=currMoveMask;
set(vid, 'UserData', appdata);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function localDeleteFig(fig, event)

% Reset peekdata warnings.
warning on imaq:peekdata:tooManyFramesRequested

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function figData = localCreateFigure(vid, figTitle)
% Creates and initializes the figure.

% Create the figure and axes to plot into.
fig = figure('NumberTitle', 'off', 'MenuBar', 'none', ...
    'Name', figTitle, 'DeleteFcn', @localDeleteFig);

% Create a spot for the image object display.
nbands = get(vid, 'NumberOfBands');
res = get(vid, 'ROIPosition');
himage = imagesc(rand(res(4), res(3), nbands));

% Clean up the axes.
ax = get(himage, 'Parent');
set(ax, 'XTick', [], 'XTickLabel', [], 'YTick', [], 'YTickLabel', []);

title( sprintf('Showing areas of movement. \nTo finish close figure.'),...
    'FontSize', 17);
% Store the figure data.
figData.hFigure = fig;
figData.hImage = himage;

Contact us