%% Video reading and writing
%
% Table of Contents
% Read video files
% Write video files
%     Specify Profile for Uncompressed AVI and Write Video
%     Specify Profile for Motion JPEG AVI
%     Make a new video by figures
% EXERCISE 1:  generate a new video (sequence of frames) filtering out the odd frames
% Face Detection in a Video
%     EXERCISE 2: Extract a video clip from BraveHeart.mp4 video from sec 45 to sec 100
%     Apply the Viola-Jones algorithm to detect a face in the video
% Slider Effect Creation in a Video
%     EXERCISE 1: Do the same Slider Effect horizontally
%
%% Read video files
% Read frames from a video starting at a specific time or frame index, read frames within a specified interval, or read all the frames in the video.
%
% Read part of a video file starting T second from the beginning of the file. Then, read the video starting from frame index 100 to the end of the video file.

% Construct a VideoReader object
vidObj = VideoReader('xylophone.mp4');

% object displays video frames
% This player is capable of displaying high definition video at high frame rates
depVideoPlayer = vision.DeployableVideoPlayer;

% reading begins at 0.5 second from the beginning
vidObj.CurrentTime = 0.5;

get(vidObj)      % display all information about video

% Read video frames until the end of the file
while hasFrame(vidObj)
    vidFrame = readFrame(vidObj);
    depVideoPlayer(vidFrame)
    pause(1/vidObj.FrameRate);
end

%
% Read Frames Within Specified Interval
% Read the video frames between 0.6 and 0.9 seconds. First, create a structure array to hold the frames.
% Specify that reading should begin 0.6 second from the beginning of the file by setting the CurrentTime property.
% Read one frame at a time until CurrentTime reaches 0.9 second
% Append data from each video frame to the structure array.
% For information on displaying the frames in the structure s as a movie, see the movie function reference page.

% Construct a VideoReader object
vidObj = VideoReader('xylophone.mp4');

% structure array to hold the frames
s = struct('cdata',zeros(vidObj.Height,vidObj.Width,3,'uint8'),'colormap',[]);

% specify that reading should begin 0.6
vidObj.CurrentTime = 0.6;

% Read one frame at a time until CurrentTime reaches 0.9 second
k = 1;
while vidObj.CurrentTime <= 0.9
    s(k).cdata = readFrame(vidObj);
    k = k+1;
end

%% Alternatively, you can read all the frames by using indices. 
frames = read(vidObj,[18 27]);

whos s
whos frames

%
%% Write video files
%
% The VideoWriter object contains properties that control the output video. You can create a VideoWriter object with properties tailored to a specific format, such as 'Uncompressed AVI' or 'MPEG-4', by using the VideoWriter function with a predefined profile.
%
%% Specify Profile for Uncompressed AVI and Write Video
% Create a video object with a specified profile, make an array containing an RGB image, and then write the array into a video file. Create a VideoWriter object for a new uncompressed AVI file for RGB24 video.
% v = VideoWriter('newfile.avi','Uncompressed AVI');
%% Specify Profile for Motion JPEG AVI
% For example, you can create a VideoWriter object with a MPEG-4 profile and assign a value to the Quality property.
% v = VideoWriter('newfile.avi','MPEG-4');
% v.Quality = 95;
% Open the file for writing
% open(v)
% Create an array containing data from the sample still image, peppers.png. Write the image in A to the video file.
% A = imread('peppers.png');
% writeVideo(v,A)
% Close the file.
% close(v)
%% Make a new video by figures
% Generate a set of frames, get the frame from the figure, and then write each frame to the file.

figure
Z = peaks(50); % A sample function of two variables
surf(Z)
axis tight manual
ax = gca;
ax.NextPlot = 'replaceChildren';

% create VideoWriter objects
v_avi = VideoWriter('peaks.avi','Uncompressed AVI');
v_mp4 = VideoWriter('peaks.mp4','MPEG-4');
v_mp4.Quality = 50;
open(v_avi);
open(v_mp4);

    
% Generate a set of frames, get the frame from the figure, 
% and then write each frame to the file
loops = 100;
F(loops) = struct('cdata',[],'colormap',[]);
for j = 1:loops
    X = sin(j*pi/10)*Z;
    surf(X,Z)
    drawnow
    F(j) = getframe;
    writeVideo(v_avi,F(j));
    writeVideo(v_mp4,F(j));
end
get(v_avi)      % display all information about video
get(v_mp4)      % display all information about video
close(v_mp4);
close(v_avi);
implay('peaks.avi',10);
implay('peaks.mp4',10);

%
%
%% EXERCISE 1:  generate a new video (sequence of frames) filtering out the odd frames
%
% TODO:
% Read a video and extract only the odd frames
% Write the frames extracted in a new video
% Hints:
% to select frames use their index by calling the method I = read(movieObj, iFrame)
%

% object displays video frames

% TODO...

%
%
%% Face Detection in a Video
%
% Using the Viola-Jones algorithm to detect a face in the video
%
%% EXERCISE 2: Extract a video clip from BraveHeart.mp4 video from sec 45 to sec 100

% TODO...

%
%% Apply the Viola-Jones algorithm to detect a face in the video
%

% Read a video into MATLAB
vidObj = VideoReader('BH_clip.avi');
depVideoPlayer = vision.DeployableVideoPlayer;

% Initialize the Detector
faceDetector = vision.CascadeObjectDetector();

%% Detect faces in each frame
while hasFrame(vidObj)
    videoFrame = readFrame(vidObj);
    % Detect the face
    bbox = faceDetector(videoFrame);
    % Insert a box around the detected face
    videoFrame = insertShape(videoFrame, 'Rectangle', bbox);
    % Display video
    depVideoPlayer(videoFrame);
end

%
%%
%% Slider Effect Creation in a Video
%
% This example shows how to create the slider effect in a video. One part of it detects edges using the Canny Method.
% BW = edge(I) returns a binary image BW containing 1s where the function finds edges in the input image I and 0s elsewhere. By default, edge uses the Sobel edge detection method.

%% Read the video into MATLAB
vidObj = VideoReader('BraveHeart_clip.mp4');

% This value determine the speed of the sliding effect
speed = 10;

col = vidObj.width;

% Display video
depVideoPlayer = vision.DeployableVideoPlayer;
%% Process each frame
while hasFrame(vidObj)
    
    % Left to Right
    for idx = 1:speed:col
        videoFrame = readFrame(vidObj);
        
        % Detect edges in the grayscale image
        edgeFrame = edge(rgb2gray(videoFrame),'canny');
        edgeFrame = edgeFrame * 255;
        
        % Part of the Input Frame
        n1 = videoFrame(:, 1 : idx,:);
        % Part of the Edge Detected Frame
        n2 = edgeFrame(:, idx+1 : col );
        
        % Concatenating them together
        finalFrame = [n1 cat(3,n2,n2,n2)];
        depVideoPlayer(finalFrame);
    end
    
    % Right to Left
    for idx = col:-speed:1
        videoFrame = readFrame(vidObj);
        
        % Detect edges in the grayscale image
        edgeFrame = edge(rgb2gray(videoFrame),'canny');
        edgeFrame = edgeFrame * 255;
        
        % Part of the Input Frame
        n1 = videoFrame(:, 1 : idx,:);
        % Part of the Edge Detected Frame
        n2 = edgeFrame(:, idx+1 : col );
        
        % Concatenating them together
        finalFrame = [n1 cat(3,n2,n2,n2)];
        depVideoPlayer(finalFrame);
    end
end

%
%% EXERCISE 3: Do the same Slider Effect horizontally
%