📜 ⬆️ ⬇️

Work with video in Matlab

Matlab is a well-known numerical computing environment widely used by the scientific community. Works in Windows, nix-systems and on Macs. The Matlab language is optimized for working with matrices and multidimensional arrays; in addition, there are a huge number of extensions (officially called Toolboxes) for solving optimization problems, statistical calculations, signal and image processing, etc. Plus, there is a large amount of scientific code already written on Matlab, which additionally spurs its popularity.

In this article I will briefly describe the possibilities of Matlab to work with video. For those who are not familiar with the matlab syntax, a brief overview of the main features in Russian can be read here .


Video format


The first thing you need to do to work with video is to upload it to Matlab. The main difficulty that arose in me is related to codecs. By default, the list of supported video formats is small ( English documentation ) and whether a matlab will open your video depends on the codecs installed in the system. The general rule is that if your built-in player (Windows Media Player in Windows) cannot open a file, then Matlab most likely will not open it.
')
Accordingly, the ability to record video is highly dependent on the installed codecs, although Matlab will be able to create uncompressed video on any system without installed codecs.

Problems with reading and recording video, I decided to install the KLite Codec Pack Full in the version of "Lots of stuff":


Different ways to read videos


There are several ways to read videos in the lab. About two of them are described below.

Reading video using mmreader and read methods


The first way to read video is to use the mmreader method to open a file and further use the read method to read frames:

 % open file
 video = mmreader ('d: \ test \ 1.avi');

 % like this you can learn about some properties of the open video
 width = video.Width;
 height = video.Height;
 frameRate = video.FrameRate;
 numOfFrames = video.NumberOfFrames;

 % read frame
 % frames numbered from 1
 frameNo = 50;
 frame = read (video, frameNo);

 % frame can be read and like this
 frame = video.read (frameNo);

 % read frame range
 % 50 - the number of the first frame read
 % 100 - last read frame number
 framesRange = [50 100];
 frames = read (video, framesRange);

 % read all videos
 % operation will not be performed if the video is large and does not fit into memory
 entireVideo = read (video);

 % There is no special function to close the video file.
 % Correspondingly, when you finish working with video
 % no additional action is needed.


All frame reading functions return a multidimensional matrix as the execution result. For example, here is the result of executing several commands for working with video in the interactive desktop lab:

  >> video.Width

 ans =

    704

 >> video.Height

 ans =

    576

 >> frame = read (video, 5);
 >> size (frame)

 ans =

    576,704 3

 >> frames = read (video, [5 10]);
 >> size (frames)

 ans =

    576 704 3 6 


Thus, as a result of reading one frame, a matrix is ​​obtained with the size of Height x Width x 3, the elements of which are 8-bit unsigned integers. As a result of reading a range of several frames, a matrix is ​​obtained with the size of Height x Width x 3 x NumOfFrames.

Correspondingly, when you have loaded a frame, you can work with it as with an ordinary matlab matrix, and also apply various functions for image processing included in the Image Processing Toolbox to it.

Reading video with System Objects - Matlab 2010a innovations


The concept of system objects was introduced in the hardware version 2010a. The Matlab manual says that system objects provide an object-oriented implementation of algorithms. Compared to ordinary Matlab functions, they automatically control their state and are well suited for stream processing. In general, the main point is that according to the developers, it is more convenient to use them for stream processing of information. At the expense of convenience, you can argue, but the code becomes a bit shorter.

Here is an example of frame-by-frame video reading using system objects:

 % create an object to read the video
 reader = video.MultimediaFileReader ('Filename', 'd: \ test \ 1.avi');

 % read all videos frame by frame
 % step function will return a matrix with the size of Height x Width x 3
 % true the elements of this matrix will be of the single type - 4 byte floating point numbers
 while ~ isDone (reader)
    frame = step (reader);
 end

 % here as in the previous case, you do not need to perform any closing operations
 % at the end of reading the video


A significant disadvantage of this approach is that there is no random access to the video - you can only read frames sequentially. Also, in terms of subjective sensations, opening video and reading frames using system objects takes a little longer than using mmreader and read .

Playing video


Besides the fact that the video can be read and processed, it can also be played with built-in tools.

Playing with the movie function


The movie function allows you to play a video. The feature of using this function is that you need to prepare in advance the entire video that should be played. In addition, the video should be stored in memory in a format different from that obtained by reading the video. The following is an example of how this feature can be used to play the first 200 frames of video:

 %% reading video
 filename = 'd: \ test \ 1.avi';
 video = mmreader (filename);
 nFrames = 200;

 % prepare the structure in which the information will be read
 mov (1: nFrames) = struct ('cdata', [], 'colormap', []);

 % Read frame by frame
 for k = 1: nFrames
     mov (k) .cdata = read (video, k);
 end

 %% play video
 hf = figure;
 set (hf, 'position', [150 150 video.Width video.Height])
 movie (hf, mov, 1, video.FrameRate);


In this code, a movie is prepared in the mov variable. This variable stores an array of structures. Each structure has two fields: cdata and colormap . The cdata field stores the bitmap of the frame, and the colormap field needs to store a color palette for indexed video. In this case, this is a full-fledged RGB video and the colormap empty.

Playing with system objects


Compared with the previous example, the use of system objects can significantly reduce the code:

 % create an object to read the video
 reader = video.MultimediaFileReader ('Filename', 'd: \ test \ 1.avi');

 % create an object to play the video
 player = video.VideoPlayer;

 % read frame by frame and play the video
 while ~ isDone (reader)
    frame = step (reader);
    step (player, frame);
 end 


Video recording


You can also record video in several ways. Here I will analyze 3 methods: frame by frame recording, video recording in one piece and using system objects.

I will note in advance that if you are recording a video in more than one piece, you must close the video file at the end of the operation. If the file is not closed, then until you exit the lab you cannot access, delete, or overwrite it.

Record video frame by frame



 %% prepare variables
 filename = 'd: \ test \ 1.avi';
 result_file = 'd: \ test \ result.avi';
 nFrames = 200;
 video = mmreader (filename);
 % open file for writing
 % compressor set - XVID
 writer = avifile (result_file, 'compression', 'XVID');

 %% in cycle read-modify-write
 % structuring element for dilatation
 se = strel ('rectangle', [3 3]);
 for k = 1: nFrames
     % read frame
     frame = read (video, k);
     % do frame dilatation
     frame = imdilate (frame, se);
     % write frame
     writer = addframe (writer, frame);
 end
 % sure to close the writer
 writer = close (writer); 


Here I will note the way in which the arguments of the avifile function are avifile . The first argument is the name of the file, then the arguments go in pairs — first the name of the parameter, then the value. In the above example, the avifile function avifile in addition to the file name, also passes the compression parameter with the value XVID.

As the compression parameter, you can specify one of the identifiers: 'None', 'MSVC', 'RLE', 'Cinepak', 'Indeo3' or 'Indeo5'. On * nix systems, only the option 'None' is available. In addition to the above options, you can also specify the FourCC of the desired compressor (as in the example). Here everything depends on the codecs installed in the system for encoding the video. It should be noted that not all of the installed codecs are suitable for both decoding and video encoding. Only XVID earned on my system of several tested options.

Video recording in one piece


In addition to frame-by-frame recording, you can also set up an array of frames and write them all at once to a file. An array of frames should be prepared in the same way as in the example of using the movie function to play videos. More to the point: the array should consist of structures, one of the members of the structure is the cdata field that stores the bitmap of the image, and the second is the colormap field that stores the palette for the indexed color image:

 %% reading video
 filename = 'd: \ test \ 1.avi';
 video = mmreader (filename);
 nFrames = 200;

 % prepare the structure in which the information will be read
 mov (1: nFrames) = struct ('cdata', [], 'colormap', []);

 % Read and modify the first 200 frames of video
 se = strel ('rectangle', [3 3]);
 for k = 1: nFrames
     frame = read (video, k)
     mov (k) .cdata = imdilate (frame, se);
 end

 %% video recording
 movie2avi (mov, 'd: \ test \ result.avi', 'compression', 'XVID', 'fps', 25);


The compression parameter of the movie2avi function is the same as in the previous section.

Record video using system objects


The following code demonstrates the use of system objects for recording video:

 reader = video.MultimediaFileReader ('Filename', 'd: \ test \ 1.avi');
 % open the video to record
 % file name = d: \ test \ result.avi
 % audio - no, there is video
 % video codec = MJPEG
 writer = video.MultimediaFileWriter ('Filename', 'd: \ test \ result.avi', ...
     'AudioInputPort', false, 'VideoInputPort', true, ...
     'VideoCompressor', 'MJPEG Compressor');
 % structuring element for dilatation
 se = strel ('rectangle', [3 3]);
 while ~ isDone (reader)
    % read frame
    frame = step (reader);
    % do frame dilatation
    frame = imdilate (frame, se);
    % write frame
    step (writer, frame);
 end

 % sure to close the writer
 close (writer);


The arguments of the video.MultimediaFileWriter function are the pairs 'parameter name', the value of the parameter. Even the file name is transferred in this way (i.e., the pair 'Filename', 'file name' is indicated).

The possible values ​​of the VideoCompressor parameter here are already different from those that can be specified for the avifile and movie2avi . “None (uncompressed)” can be specified as VideoCompressor, “MJPEG Compressor” has also worked for me. If you omit the VideoCompressor parameter in the argument list, it will be equivalent to specifying 'None (uncompressed)'.

A free alternative in the face of GNU Octave


In general, the Matlab product is quite expensive, but there are some free alternatives that are partially compatible with it. One of them is GNU Octave .

GNU Octave is being actively developed and the syntax of the actual language is almost identical to Matlabovsky. Differences in the syntax are mainly due to the fact that some feature has already appeared in the trademark, and in Octave has not yet been added.

With a set of libraries, things are worse. There are no toolbox matlab in GNU Octave, although for some of the functions there are still substitutions.

Installing GNU Octave in Ubuntu 10.04


I worked with Octave in Ubuntu, so for those who want to repeat my experience I describe the installation instructions:

1. With the help of the package manager, you need to install the octave3.2 Linux packages; octave3.2-doc; octave3.2-headers with all dependencies.
2. Octave, in contrast to the matlab, consists only of an interpreter. Accordingly, you may need a GUI development environment. I installed QtOctave in Ubuntu 10.04 (also through the package manager).
3. If you plan to work with video, then you must install the Linux packages libavformat-dev, libavcodec-dev, libavutil-dev, libswscale-dev
4. In Octave itself there is also the concept of a package. Octave packages include a variety of features that extend Octave functionality. Download Octave packages from the Octave-Forge site.
To install the Octave package, you need to run Octave with administrative rights: sudo octave . And then in Octave run the command pkg install /path/to/package.tar.gz
Octave-packages image and video for working with images and video

Actually working with video in Octave


In general, loading and saving video in Octave is done in a similar way as it is done in the lab. The following is the code that dilates the first 25 frames of video:

 filename = '/home/alexey/octave/1.avi';
 result_file = '/home/alexey/octave/result.avi';

 % uncomment the next line to access the video properties
 % info = aviinfo (filename);
 % width = info.Width
 % height = info.Height

 % create a video recording object
 writer = avifile (result_file);
 se = ones ([3 3 3]);
 for i = 1: 25
   % read frame i from video
   frame = aviread (filename, i);
   % do frame dilatation
   frame = imdilate (frame, se);
   % write frame
   addframe (writer, frame);
 end


Here, the avifile(filename, frameNo) function reads the frame with the frameNo number from the video file with the name filename . No need to create any objects in advance and open the file. This function is also present in the trademark, but it is deprecated.

If you need to know information about the video, you can do this using the aviinfo(filename) function. As a result, the structure will be returned storing information about the size and format of the video, the number of frames, etc. In the lab, this function is deprecated.

Video is recorded using the avifile and addframe , but the syntax of these functions is slightly different in the hardware and Octave. In addition, in Octave, it is not necessary to close the object recording the video (moreover, there is not even a method that would close it).

As a result, for the above code for Octave to work in the hardware it needs to be modified as follows:

 %% reading video
 filename = 'd: \ test \ result.avi';
 result_file = 'd: \ test \ result2.avi';

 % info = aviinfo (filename);
 % width = info.Width;
 % height = info.Height;

 writer = avifile (result_file, 'compression', 'xvid');
 se = strel ('rectangle', [3 3]);
 for i = 1: 25
    frame = aviread (filename, i);
    frame.cdata = imdilate (frame.cdata, se);
    writer = addframe (writer, frame.cdata);
 end
 writer = close (writer);


Thus, in terms of video and image processing, there is currently a difference in the syntax of Matlabov functions and GNU Octave functions.

Source: https://habr.com/ru/post/97145/


All Articles