clear, close all, clc
%% Step 1: Detect a face to track
% Before you begin tracking a face, you need to first detect it. 
% Use the vision.CascadeObjectDetector to detect the location of 
% a face in a video frame. The cascade object detector uses the 
% Viola-Jones detection algorithm and a trained classification 
% model for detection. By default, the detector is configured to 
% detect faces, but it can be configured for other object types.
%
% Create a cascade detector object.
faceDetector = vision.CascadeObjectDetector();

% Read a video frame and run the detector.
%videoFileReader = vision.VideoFileReader('visionface.avi');
%videoFileReader = vision.VideoFileReader('tilted_face.avi');
videoFileReader = vision.VideoFileReader('varios_rostros_2.mp4');
videoFrame      = step(videoFileReader);
bbox            = step(faceDetector, videoFrame);

% Draw the returned bounding box around the detected face.
videoOut = insertObjectAnnotation(videoFrame,'rectangle',...
    bbox,'Face');
figure, imshow(videoOut), title('Detected face');

%% Step 2: Identify Facial Features To Track
% You can use the cascade object detector to track a face across 
% successive video frames. However, when the face tilts or the 
% person turns their head, you may lose tracking. This limitation 
% is due to the type of trained classification model used for 
% detection. To avoid this issue, and because performing face 
% detection for every video frame is computationally intensive, 
% this example uses a simple facial feature for tracking.
%
% Get the skin tone information by extracting the Hue from the 
% video frame converted to the HSV color space.
[hueChannel,~,~] = rgb2hsv(videoFrame);

% Display the Hue Channel data and draw the bounding box around 
% the face.
figure, imshow(hueChannel), title('Hue channel data');
rectangle('Position',bbox(1,:),'LineWidth',2,'EdgeColor',[1 1 0])

%% Step 3: Track the Face
% With the skin tone selected as the feature to track, you can 
% now use the vision.HistogramBasedTracker for tracking. The 
% histogram based tracker uses the CAMShift algorithm, which 
% provides the capability to track an object using a histogram 
% of pixel values. In this example, the Hue channel pixels are 
% extracted from the nose region of the detected face. These 
% pixels are used to initialize the histogram for the tracker. 
% The example tracks the object over successive video frames 
% using this histogram.
%
% Detect the nose within the face region. The nose provides a 
% more accurate measure of the skin tone because it does not 
% contain any background pixels.
noseDetector = vision.CascadeObjectDetector('Nose');
faceImage    = imcrop(videoFrame,bbox(1,:));
noseBBox     = step(noseDetector,faceImage);

% The nose bounding box is defined relative to the cropped face 
% image. Adjust the nose bounding box so that it is relative to 
% the original video frame.
noseBBox(1,1:2) = noseBBox(1,1:2) + bbox(1,1:2);

% Create a tracker object.
tracker = vision.HistogramBasedTracker;

% Initialize the tracker histogram using the Hue channel pixels 
% from the nose.
initializeObject(tracker, hueChannel, noseBBox(1,:));

% Create a video player object for displaying video frames.
videoInfo    = info(videoFileReader);
%videoPlayer  = vision.VideoPlayer('Position',...
    %[50 50 videoInfo.VideoSize+100]);
videoPlayer  = vision.VideoPlayer('Position',...
    [100 100 0.2*videoInfo.VideoSize]);

% Track the face over successive video frames until the video 
% is finished.

while ~isDone(videoFileReader)

    % Extract the next video frame
    videoFrame = step(videoFileReader);

    % RGB -> HSV
    [hueChannel,~,~] = rgb2hsv(videoFrame);

    % Track using the Hue channel data
    bbox = step(tracker, hueChannel);

    % Insert a bounding box around the object being tracked
    videoOut = insertObjectAnnotation(videoFrame,'rectangle',...
        bbox,'Face');

    % Display the annotated video frame using the video player 
    % object
    step(videoPlayer, videoOut);

end

% Release resources
release(videoFileReader);
release(videoPlayer);