%% Cell Counting
% This demo illustrates how to use a combination of basic morphological
% operators and blob analysis to extract information from a video stream.
% In this case, the demo counts the number of E. Coli bacteria in each
% video frame. Note that the cells are of varying brightness, which makes
% the task of segmentation more challenging.

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

%% Introduction
% This demo illustrates how to use the morphological and BlobAnalysis
% System objects to segment individual cells and count them.

%% Initialization
% Use these next sections of code to initialize the required variables and
% objects.
VideoSize = [432 528];

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

%% 
% Create two morphological dilation System objects which are used to remove
% uneven illumination and to emphasize the boundaries between the cells. 
hdilate1 = vision.MorphologicalDilate('NeighborhoodSource', 'Property', ...
                   'Neighborhood', strel('square',7));
hdilate2 = vision.MorphologicalDilate('NeighborhoodSource', 'Property', ...
                   'Neighborhood', strel('square',7));

%%
% Create an Autothreshold System object to convert an intensity image to a
% binary image.
hautoth = vision.Autothresholder( ...
  'Operator', '<=', ...
  'ThresholdScaleFactor', 0.8);

%%
% Create a BlobAnalysis System object to find the centroid of the segmented
% cells in the video.
hblob = vision.BlobAnalysis( ...
                'AreaOutputPort', false, ...
                'BoundingBoxOutputPort', false, ...
                'OutputDataType', 'single', ...
                'MinimumBlobAreaSource', 'Property', ...
                'MinimumBlobArea', 7, ...
                'MaximumBlobAreaSource', 'Property', ...
                'MaximumBlobArea', 300, ...
                'MaximumCount', 1500);

%% 
% Create a System object to mark the centroids of the individual cells.
hdrawmarkers = vision.MarkerInserter( ...
                            'Shape', 'Star', ...
                            'BorderColorSource', 'Property', ...
                            'BorderColor', 'Custom', ...
                            'CustomBorderColor', [0 255 0]);

%% 
% Create a System object to count the number of cells in the video.
hcounter = dsp.Counter( ...
                'CountEventInputPort', false, ...
                'CounterSizeSource', 'Property', ...
                'CounterSize', '16 bits', ...
                'InitialCount',   1, ...
                'CountOutputPort', true, ...
                'CountOutputDataType',  'uint16', ...
                'ResetInputPort', false);

%%
% Create two System objects that insert text: one to display the number of
% frames and cells, and the other to display video source information.
hinserttext1 = vision.TextInserter( ...
    'Text', 'Frame %d, Count %d', ...
    'Location',  [10 10], ...
    'ColorSource', 'Property', ...
    'Color', 1, ...
    'FontSize', 16);

hinserttext2 = vision.TextInserter( ...
    'Text', ['Data set courtesy of Jonathan Young and Michael Elowitz, ' ...
             'California Institute of Technology'], ...
    'Location',  [1 417], ...
    'ColorSource', 'Property', ...
    'Color', 1);

%%
% Create a System object to display the video.
hVideo = vision.VideoPlayer;
hVideo.Name  = 'Results';
hVideo.Position(1) = round(hVideo.Position(1));
hVideo.Position(2) = round(hVideo.Position(2));
hVideo.Position([4 3]) = 30+VideoSize;

%%
% Initialize a figure window for plotting the cell division rate.
hPlot = videocellplots('setup');

%% Stream Processing Loop
% Create a processing loop to count the number of cells in the input video.
% This loop uses the System objects you instantiated above.

while ~isDone(hvfr)
    % Read input video frame
    image = step(hvfr);

    % Apply a combination of morphological dilation and image arithmetic
    % operations to remove uneven illumination and to emphasize the
    % boundaries between the cells.
    y1 = 2*image - step(hdilate1, image);
    y1(y1<0) = 0;
    y1(y1>1) = 1;
    y2 = step(hdilate2, y1) - y1;

    y3 = step(hautoth, y2);                   % Binarize the image.
    Centroid = step(hblob, y3);   % Calculate the centroid
    numBlobs = size(Centroid,1);  % and number of cells.
    % Display the number of frames and cells.
    image = step(hinserttext1, image, [step(hcounter); numBlobs]);
    image = step(hinserttext2, image); % Display video source information

    % Display video
    image_rgb = cat(3, image, image, image);
    image_out = step(hdrawmarkers, image_rgb, Centroid);
    step(hVideo, image_out);

    % Plot cell count
    videocellplots('plot',hPlot,numBlobs);
end

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

%% Summary
% In the Results window the original video is shown and the green markers
% indicate the centroid locations of the cells. The frame number and the
% number of cells are displayed in the upper left corner. 

%% Data Set Credits
% The data set for this demo was provided by Jonathan Young and Michael
% Elowitz from California Institute of Technology(R). It is used with
% permission. For additional information about this data, see
%
% N. Rosenfeld, J. Young, U. Alon, P. Swain, and M.B. Elowitz,
% "Gene Regulation at the Single-Cell Level, " Science 2005, 
% Vol. 307, pp. 1962-1965.

%% Appendix
% The following helper function is used in this demo.
%
% * <matlab:edit('videocellplots.m') videocellplots.m>



displayEndOfDemoMessage(mfilename)
