%% Object Counting
% This demo uses morphological operations to count objects in a video
% stream. 

%   Copyright 2004-2010 The MathWorks, Inc.
%   $Revision: 1.1.6.3 $ $Date: 2011/05/09 03:44:07 $

%% Introduction
% The input video stream contains images of staples. In this demo, you use
% the top-hat morphological operation to remove uneven illumination, and
% the opening morphological operation to remove gaps between the staples.
% You then convert the images to binary, using a different threshold for
% each frame. Once this threshold is applied, you count the number of
% staples and calculate the centroid of each staple.

%% Initialization
% Use these next sections of code to initialize the required variables and
% System objects.

%%
% Create a System object to read video from avi file.
filename = 'staples.avi';
hVideoSrc = vision.VideoFileReader(filename, ...
                                   'ImageColorSpace', 'Intensity',...
                                   'VideoOutputDataType', 'single');

%%
% Create a System object that you use to perform a top-hat morphological
% operation. This operation corrects for uneven illumination.
hTopHat = vision.MorphologicalTopHat('Neighborhood', strel('square',18));

%%
% Create a morphological opening System object to widen the gaps between
% the staples.
hOpening = vision.MorphologicalOpen('Neighborhood', strel('rect',[15 3]));

%%
% Create an autothresholder System object to convert the input intensity
% images to binary images.
hAutoThresh = vision.Autothresholder;

%%
% Create a blob analysis System object to count the staples and find their
% centroids.
hBlob = vision.BlobAnalysis( ...
            'AreaOutputPort', false, ...
            'BoundingBoxOutputPort', false, ...
            'OutputDataType', 'single');            

%%
% Create a System object to display the number of staples.
hTextInserter = vision.TextInserter( ...
            'Text', 'Staple count: %d', ...
            'Location', [10 280], ...
            'Color', 255, ...
            'Font', 'LucidaTypewriterRegular', ...
            'FontSize', 30);

%%
% Create System objects to mark individual staples with circles around a
% plus sign.
hDrawMarkerCircle = vision.MarkerInserter('Size', 6);

hDrawMarkerPlus = vision.MarkerInserter( ...
            'Shape', 'Plus', ...
            'Size', 5);

%%
% Create a System object to display the output video.
hVideoOut = vision.VideoPlayer('Name', 'Counted Staples');
hVideoOut.Position(3:4) = [650 350];

%% Stream Processing Loop
% Here you call the processing loop to count the staples in the input
% video. This loop uses the System objects you instantiated.
%
% The loop is stopped when you reach the end of the input file, which is
% detected by the BinaryFileReader System object.
while ~isDone(hVideoSrc)
    I = step(hVideoSrc);
    Im = step(hTopHat, I);                     % Top-hat
    Im = step(hOpening, Im);                   % Opening
    BW = step(hAutoThresh, Im);                % Autothreshold
    Centroids = step(hBlob, BW);               % Blob Analysis
    
    StaplesCount = int32(size(Centroids,1));  
    It = step(hTextInserter, I, StaplesCount);   % Display staples count
    
    Centroids(:, 2) = Centroids(1,2);            % Align markers horizontally

    It = step(hDrawMarkerCircle, It, Centroids); % Mark staples using o
    hDrawMarkerCircle.Size = 5;
    It = step(hDrawMarkerCircle, It, Centroids);
    hDrawMarkerCircle.Size = 6;
    It = step(hDrawMarkerPlus, It, Centroids);   % Mark staples using +

    step(hVideoOut, It);
end

%% Release
% Here you call the release method on the System objects to close any open
% files and devices.
release(hVideoSrc);

%% Summary
% The output video shows the individual staples marked with a circle and
% plus sign. It also displays the number of staples that appear in each
% frame.


displayEndOfDemoMessage(mfilename)
