faceDetector = vision.CascadeObjectDetector();

pt = vision.PointTracker('MaxBidirectionalError', 2);

camera = webcam();

vF = snapshot(camera);
fS = size(vF);

vP = vision.VideoPlayer('Position', [100 100 [fS(2), fS(1)]+30]);

runLoop = true;
numPts = 0;
frameCount = 0;

while runLoop && frameCount < 400

    
    vF = snapshot(camera);
    videoFrameGray = rgb2gray(vF);
    frameCount = frameCount + 1;

    if numPts < 5
        
        bbox = faceDetector.step(videoFrameGray);

        if ~isempty(bbox)
            
            points = detectMinEigenFeatures(videoFrameGray, 'ROI', bbox(1, :));

            
            xyPoints = points.Location;
            numPts = size(xyPoints,1);
            release(pt);
            initialize(pt, xyPoints, videoFrameGray);

            
            oldPoints = xyPoints;

           
            bboxPoints = bbox2points(bbox(1, :));

            bboxPolygon = reshape(bboxPoints', 1, []);

            
            vF = insertShape(vF, 'Polygon', bboxPolygon, 'LineWidth', 3);

            
            vF = insertMarker(vF, xyPoints, '+', 'Color', 'white');
        end

    else
      
        [xyPoints, isFound] = step(pt, videoFrameGray);
        visiblePoints = xyPoints(isFound, :);
        oldInliers = oldPoints(isFound, :);

        numPts = size(visiblePoints, 1);

        if numPts >= 5
           
            [xform, oldInliers, visiblePoints] = estimateGeometricTransform(...
                oldInliers, visiblePoints, 'similarity', 'MaxDistance', 4);

           
            bboxPoints = transformPointsForward(xform, bboxPoints);

           
            bboxPolygon = reshape(bboxPoints', 1, []);

           
            vF = insertShape(vF, 'Polygon', bboxPolygon, 'LineWidth', 3);

        
            vF = insertMarker(vF, visiblePoints, '#', 'Color', 'red');

            
            oldPoints = visiblePoints;
            setPoints(pt, oldPoints);
        end

    end

  
    step(vP, vF);

    
    runLoop = isOpen(vP);
end


clear cam;
release(vP);
release(pt);
release(faceDetector);