%_______________________________________________________________________________
%
%   HighLevelAnalysis
%
%   This function implements performs high level analysis of motion blobs.
%   
%   HighLevelAnalysis
%   Input: formally, none.  Adjust the parameters under the Parameters
%       heading. iMinArea describes the minimum area required for imFeatures
%       body to be found.  iMinHeight describes the minimum height required 
%       for imFeatures body to be found.
%`  Output: An avi video with the segmentation overlayed
%
%   Author:         Isaac Gerg
%   Version:        0.01
%   Revision Date:  3.15.2005
%
%   0.02 3.15.2005  Isaac Gerg(idg) - Cleaned up code.
%   0.01 3.8.2005   Isaac Gerg(idg) - Initial release.
%_______________________________________________________________________________
function HighLevelAnalysis()

	clear; clc;
    warning off MATLAB:divideByZero
	%30, 550 for oldmain0
	% Parameters
	strInputFilename = 'oldmain0-test.avi';
	strBaselineFilename = '../video/oldmain0.avi';
	strOutputFilename = 'tmp1.avi';
    iMinArea = 550;
    iMinHeight = 30;
	
	% Read in video sequence
	movInput = aviread(strInputFilename);
	movBaseline = aviread(strBaselineFilename);
	MovieInfo = aviinfo(strInputFilename);
	
	% Specify the size of the movie we want to process.
	iVideoWidth = MovieInfo.Width;
	iVideoHeight = MovieInfo.Height;
	iNumberOfFrames = length(movInput);
	
	% Setup output movie stream
	movOutput = avifile(strOutputFilename);
        movOutput.Quality = 100;
        movOutput.FPS = 30;
        
	% Record time to determine frames/minute.
	iStart = clock;
	
	ObjectsPerFrame = [];
    HumanStruct = struct('Image', [], 'Centroid', [0 0]);
    Humans = [];
	
	for i=1:iNumberOfFrames
        i
        
        % Fetch frame of video and begin processing.
        % Convert RGB to grayscale.
        imInput = movInput(i).cdata;
        imInput = imresize(imInput, [iVideoHeight iVideoWidth]);
        imInput = double(rgb2gray(imInput));
        imBaseline = movBaseline(i).cdata;
        imBaseline= double(imresize(imBaseline, [iVideoHeight iVideoWidth]));
        imBaseline = imBaseline ./ 255;
	
        % Intialialize output frame.
        imOutput = imBaseline;
      
        % Begin blob analysis and recursion.
        objects = {};
        % Determine image features from such as area and connected
        % components.
        [imConnectedComponents, n] = bwlabel(imInput, 8);
        imFeatures = imfeature(imConnectedComponents, 'Area', 'BoundingBox', 'Image', 8);
        for x=1:length(imFeatures)
            if (imFeatures(x).Area > iMinArea)
                if (size(imFeatures(x).Image, 1) < 2 )
                    continue
                end
                % Being recursive split of each initial image blob.
                SplitImagesRaw = split(imFeatures(x), iMinArea, iMinHeight);        
                SplitImagesFiltered = {};
                % Clean up cell array formatting caused by recursion.
                for y=1:length(SplitImagesRaw)
                    if (isempty(SplitImagesRaw{y}) == 0)
                        SplitImagesFiltered(length(SplitImagesFiltered)+1) = SplitImagesRaw(y);
                    end
                end
                % Determine if any blobs from the initial blob were people.
                % If they were, save them.
                if (length(SplitImagesFiltered) > 0)
                    objects(length(objects)+1:length(objects)+length(SplitImagesFiltered)) = SplitImagesFiltered;
                end
            end
        end
        % Keep track of the number of bodies per frame.
        ObjectsPerFrame = [ObjectsPerFrame length(objects)];
        
        % Begin drawing the overlay for each object found.  Nothing technical here, just drawing
        % operations.
        for y=1:length(objects)
            tmp = objects{y};
            tmp.BoundingBox = ceil(double(tmp.BoundingBox));
            tmp.BoundingBox(3:4) = tmp.BoundingBox(3:4) - [2 2];
            centroid = ceil([tmp.BoundingBox(2)+tmp.BoundingBox(4)/2 tmp.BoundingBox(1)+tmp.BoundingBox(3)/2]);
     
            tmp.Image = imcomplement(tmp.Image);
            imOutput(tmp.BoundingBox(2):tmp.BoundingBox(2)+tmp.BoundingBox(4)+1, tmp.BoundingBox(1):tmp.BoundingBox(1)+tmp.BoundingBox(3)+1,1) = imOutput(tmp.BoundingBox(2):tmp.BoundingBox(2)+tmp.BoundingBox(4)+1, tmp.BoundingBox(1):tmp.BoundingBox(1)+tmp.BoundingBox(3)+1,1) .* tmp.Image;
        end
        
        % Write the new frame to the avi.
        movOutput = addframe(movOutput, imOutput);    
	end
	
    % Display recognition information
    plot(ObjectsPerFrame);
    title('Number of Humans Per Frame');
    
	% Display peformance attributes.
    iStop = clock;
	disp('Frames per minute:');
	iNumberOfFrames/(etime(iStop, iStart)/60)
	
	% Close movie when done and report success.
	movOutput = close(movOutput)
    disp('Success!');