Time for action – loading, cropping, resizing, and saving a video

This is a rather straightforward procedure that will be implemented as a MATLAB function. We will write a function that accepts the filename of an existing video file, the resizing factor, the frames to be processed, and a filename for the output file. The user will be prompted at the first processed frame to crop it to the desired size and position. The function is as follows:

function CropAndResize(inFnm,resF,framesP,outFnm)
 
% Function for loading, cropping, resizing and saving a video
% Inputs:
%        inFnm   – Input video filename
%        resF    - Resizing factor (must be positive)
%        framesP – Frames to be processed ([start end])
%        outFnm  - Output video filename
% Output:   
%        No output needed!!
 
 
start = framesP(1);                 % Start frame
stop  = framesP(2);                 % End frame	

% Numeric inputs validation
validateattributes(resF,{'numeric'},{'positive'},'CropAndResize','resF')
validateattributes(framesP,{'numeric'},{'positive'},'CropAndResize','framesP')

% Error handling for frames
if stop > numF 
    error('Exceeded maximum number of frames!')
elseif start < 1 || stop < 1 || start > stop
    error('Something is wrong with your frame limits!')
end

vIn = VideoReader(inFnm);           % Open input file
numF = get(vIn, 'NumberOfFrames'),  % Get size in frames
vOut = VideoWriter(outFnm);         % Create output file
vOut.FrameRate = vIn.FrameRate;     % Equal framerates
open(vOut);                         % Open output

for i = start:stop      % See we don't exceed the frame limit
    frame = read(vIn,i);              % Read one frame
    if i == start
        disp('Please crop the image') % Prompt user for cropping
        [temp, RECT] = imcrop(frame); % Crop and keep RECT 
    end
    outF = imcrop(frame,RECT);        % Perform cropping w. RECT
    outF = imresize(outF, resF);      % Perform resizing  
    writeVideo(vOut,outF);            % Write result
end
close(vOut); % Close output file 

Now that we have written our function, it is time for us to test it:

  1. We can test the function by providing an input filename (we'll use the 2-minute long driving video from Chapter 7, Adding Motion – From Static Images to Digital Videos, car2min.avi), a resizing factor (we'll use 2 to double the size of the cropped image), the starting and ending frame numbers (we'll use 220 and 300), and an output filename (we'll name it testCar.avi). Using these inputs, we type in the following command:
    >> CropAndResize('car2min.avi',2,[20 100],'testCar.avi'),
  2. The result will be a message, prompting the user to crop the image: Please crop the image
    Time for action – loading, cropping, resizing, and saving a video
  3. Now that we have cropped the image and the video file has started being filled with frames, the output video file will be visible in the Current Folder window.
    Time for action – loading, cropping, resizing, and saving a video
  4. We can play our new video using implay:
    >> implay('testCar.avi')
    Time for action – loading, cropping, resizing, and saving a video

What just happened?

In this example, we mixed some of the techniques discussed in previous chapters to write a function that handled loading, cropping, and resizing a video file, and then saved the result in a new file.

The first few lines of the function were, as usual, the comments describing the inputs and outputs expected by the function. The next two lines of code were used for assigning the start and end frame numbers provided by the user to respective variables. Then, you got an idea about ways to use defensive programming (that is foreseeing the possible user-inflicted errors). First, the two numeric inputs, resF and framesP, were checked for validity, whether they were positive numbers. This check is performed using the function validateattributes.

Moving on, we check whether the frame numbers were correct, by means of the two blocks of the if statement. The if clause checked for a possible error in the definition of the last frame of our video. Of course it can't exceed the maximum number of frames, hence the check if stop > numF. The elseif clause checked for other errors in the declaration of the frames to be processed, for example, the frame numbers being negative or zero, and so on. If either of the error exists, the function is aborted immediately after a proper error message is displayed in the command line. This is what the function error is used for.

After the validity checks, there were five lines of code we re-used in a previous function (see section: Time for action – making an edge detection video, from Chapter 8, Acquiring and Processing Videos). These lines handled the opening of the video and getting its size in frames (for error handling), then creating and opening a new video file of equal frame rate, so that we can write on it.

Then, the main block of our code followed. In this block, we acquired one frame at a time, cropped it, resized it, and wrote it in our new video file. The highlighted if clause will be true only once (for the first frame we process) and its block will prompt the user to provide the cropping area, RECT, which will then be used for cropping all the frames (including the first one).

When all the frames were processed and written in the new video file, the file was closed.

After the function was written, we proceeded in testing its usage in steps 1 through 4. First, we used 81 frames from a video we have used in Chapter 7, Adding Motion – From Static Images to Digital Videos and generated a new, cropped video with double the size of its original area.

When the process was over and we verified the existence of the new video file in our Current Folder window, we played back the video using implay. The player informed us that the frame size of the new cropped and resized video is 472 x 706. Our original video was 288 x 360. Since we cropped it before resizing, it is natural for it to be less than double the size per dimension.

Have a go hero – adding rotation and more error-checking

Now that you have a first function to use as basis, let's try to add more functionality to it. You should try to include another input to our previous function, which will be used as the angle by which to rotate our video frames, using imrotate. This functionality is very handy when we have used our camera in portrait orientation to shoot video. This way, our video does not show up as we would expect. Has it ever happened to you?

Another addition you can try to make to the code is an error-checking clause, for cases where the resizing factor is less than or equal to zero. This will lead to a result that is not acceptable, since the result of imresize with negative resizing factors is an empty matrix. No video can be constructed using empty frames, so we really should prevent this from happening.

Filtering your video frames

Now that we have discussed how we can import an existing video file and apply basic image manipulation techniques on its frames, it is time we move on to more complex filtering. You probably have already noticed that the quality of the video we have made in the previous example is not exactly optimal. It has a very intense blocking effect (neighboring rectangular blocks in the image have very visible borders), especially due to the resizing process we have used. As you may recall, in order for imresize to accomplish adding pixels where they don't exist, it uses the cubic interpolation method by default. This is a fast, but suboptimal method and can lead to serious blocking effects.

Instead of going back to the function we have written in the previous example and use different methods of interpolation available with imresize to enhance our video, we will try to accomplish it by filtering the frames. A common way to do it is to apply a smoothing filter to each of the frames, so that the blocking effect is reduced. Let's see how we can do it, using the following example.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset