%% Feature Extraction
% This demo uses the Computer Vision System Toolbox(TM) System objects
% to count the spokes in a rotating wheel.

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

%% Introduction
% This demo illustrates how to use basic morphological operators to extract
% information from a video stream. In this case, the demo counts the spokes
% in a rotating wheel.

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

%%
% Read the input image, which you use to create the video frames.
I = single(imread('testpat1.png'));
Threshold = single(150); % Threshold for binary conversion

%%
% Create a GeometricRotator System object and set its AngleSource property
% to 'Input port'. This will enable you to rotate the input image with
% varying angles during the processing loop.
hRotate = vision.GeometricRotator( ...
        'OutputSize', 'Same as input image', ...
        'AngleSource', 'Input port', ...
        'MaximumAngle', pi, ...
        'SineComputation', 'Trigonometric function');

%%
% Create a ConnectedComponentLabeler System object that you use to isolate
% the wheel, which is the largest connected region in the image.
hLabel = vision.ConnectedComponentLabeler( ...
        'LabelMatrixOutputPort', true, ...
        'LabelCountOutputPort', false);

%%
% Create a Histogram System object that you use to identify the largest
% connected region in the labeled image.
hHist = vision.Histogram( ...
        'LowerLimit', 0, ...
        'UpperLimit', 101, ...
        'NumBins', 100);

%%
% Create a MorphologicalClose System object that you use to join the spokes
% at the wheel's center.
hClose = vision.MorphologicalClose('Neighborhood', strel('disk',5));

%%
% Create a MorphologicalOpen System object that you use to perform a
% top-hat morphological operation to remove the center of the wheel.
hOpen = vision.MorphologicalOpen('Neighborhood', strel('disk',9));

%%
% Create a MorphologicalOpen System object that you use to remove the rim
% of the wheel.
hOpen1 = vision.MorphologicalOpen('Neighborhood', strel('disk',4));

%%
% Create a ConnectedComponentLabeler System object to count the number of
% spokes in the wheel.
hLabelCnt = vision.ConnectedComponentLabeler( ...
     'LabelMatrixOutputPort', true, ...
     'LabelCountOutputPort', true, ...
     'OutputDataType', 'uint8', ...
     'OverflowAction', 'Use maximum value of the output data type');

%%
% Create a TextInserter System object to display the spoke count on the
% video frame.
hInsertText = vision.TextInserter( ...
        'Text', 'Cnt = %d', ...
        'Location', [2 2], ...
        'Color', 1, ...
        'FontSize', 18);

%%
% Create a VideoPlayer System object to display the output video.
hVideoOut = vision.VideoPlayer;

%% Stream Processing Loop
% Create the processing loop to count the spokes in the input video. This
% loop uses the System objects you instantiated.
for i=1:100
    Angle = single((i-1) * pi/180);  % Angle to rotate the image
    V = step(hRotate, I, Angle);            % Rotate input image
    B = (V < Threshold);                    % Convert to binary image

    L = step(hLabel, B);                    % Isolate the wheel
    H = step(hHist, L(:));                  % Find largest region
    H(1) = 0;
    [MaxVal, Idx] = max(H);
    L = (L == Idx);                         % Find the wheel

    L = step(hClose, L);                    % Join spokes at the center
    L = L & ~step(hOpen, L);                % Top-hat
    L = step(hOpen1, L);                    % Remove the wheel rim

    [Spokes, Cnt] = step(hLabelCnt, L);     % Count the spokes
    L1 = step(hInsertText, single(L), Cnt); % Display the count on image
    step(hVideoOut, L1);                    % Display output video
end

%% Summary
% The output video shows the individual spokes which were identified using
% Computer Vision System Toolbox System objects. It also displays the
% number of spokes in the wheel.


displayEndOfDemoMessage(mfilename)
