Video Files: Difference between revisions

From EMGU
Jump to navigation Jump to search
Initial Save
 
m Added more about the code still have to included some methods and ==Methods Available== section
Line 35: Line 35:




'''EMGU Coding Level:''' While the coding is not advanced the rated level for this example is Intermediate/Beginner. This is not designed as a full on tutorial and general knowledge of the EMGU is expected. While the coding is basic the are several methods involved that may be of putting the newcomers of EMGU.  
'''EMGU Coding Level:''' While the coding is not advanced the rated level for this example is Intermediate. This is not designed as a full on tutorial and general knowledge of the EMGU is expected. While the coding is basic the are several methods involved that may be of putting the newcomers of EMGU.  




Line 43: Line 43:
The code provided in this sample is basic there is little or no error checking. Support is available through the Forums but please try and examine the code before saying it doesn't work for you. The code is not optimised instead is better formatted to provided an understanding of the stages involved.  
The code provided in this sample is basic there is little or no error checking. Support is available through the Forums but please try and examine the code before saying it doesn't work for you. The code is not optimised instead is better formatted to provided an understanding of the stages involved.  


Decription....
As the example demonstrates two methods, both viewing and recording video, some of the methods have two operations within them. They are controlled by setting <code>VideoMethod</code> enum called <code>CurrentState</code>. The methods are discussed individually in the order they appear in the code [http://www.emgu.com/wiki/index.php?title=Video_Files#The_Code:_Methods bellow].




====The Code: Variables====
====The Code: Variables====


What they do...
An Open and Save file dialogue are globally declared, this is just so the file name for either saving or reading of the video can be accessed by other threads if needed.


<syntaxhighlight lang="csharp">Variables</syntaxhighlight>
<syntaxhighlight lang="csharp">
        OpenFileDialog OF = new OpenFileDialog();
        SaveFileDialog SF = new SaveFileDialog();
</syntaxhighlight>


The current method of viewing/recording videos is checked using the following variables. The two boolean variables <code>playstate</code> and <code>recordstate </code> are used for changing the button image and action depending on the program operation they record the play/pause/run state of the recording and viewing process. The enumerator <code>CurrentState</code> is used to classify the current state either 'Viewing' or 'Recording', this allows the program to operate according to reading or writing video files.
<syntaxhighlight lang="csharp">
        //current video mode and state
        bool playstate = false;
        bool recordstate = false;
        VideoMethod CurrentState = VideoMethod.Viewing; //default state
        public enum VideoMethod
        {
            Viewing,
            Recording
        };
</syntaxhighlight>
The following variables and Class initialiser variables (<code>VW<code>,<code>SW<code>, and <code>_Capture<code>) deal with the capture device/video, storing its variables, and for writing video files. The <code>_Capture</code> variable is used in two ways depending on the program operation. If viewing videos it is initialised using the <code>Capture(string 'video file name')</code> method. If recording a video it is initialised using the default constructor <code>Capture()</code> setting up the variable to capture from the default video acquisition device installed on the system. To enable selection of device see the [http://www.emgu.com/wiki/index.php?title=Camera_Capture Capture: Camera] example for reference.
The <code>VideoWriter</code> variable <code>VW</code> is used to set up a video writer when recording a video from the acquisition device. Caution must be used when using the class as even when correctly disposing of the object video index buffers can still become corrupt. Using uncompressed video formats and the re-encoding the video later is the most stable method of use. Other variables are used for storing and displaying of video information.
<syntaxhighlight lang="csharp">
        //Capture Setting and variables
        Capture _Capture;
        double FrameRate = 0;
        double TotalFrames = 0;
        VideoWriter VW;
        Stopwatch SW;
        int Frame_width;
        int Frame_Height;
        int FrameCount;
</syntaxhighlight>




====The Code: Methods====
====The Code: Methods====


What a <code>method</code> does...
The <code>Form1()</code> method initialises the forms controls as default and no extra code is included here. The<code>ProcessFrame()</code> method has two sections, separated with an two <code>if</code> statements looking at the <code>CurrentState</code> of the program, either viewing or recording videos.
 
Viewing videos (<code>VideoMethod.Viewing</code>) is a fairly simple in it's application firstly it shows the frame and then updates the forms controls, labels and trackbar information. This is all done using thread safe calls to methods that include delegate operations if the controls need invoking. As the process frame is called from an independent thread set up in the <code>Capture</code> variable an control invoke is required to prevent cross thread interference. Then the <code>ProcessFrame()</code> thread is told to sleep for a specific period of time. This allows the video to be displayed at a correct frame rate. If this is removed the video will play as fast as the computer can process each frame. In this example delay is dependant on the frame rate that the video was encoded with, at least what the codec says it was. This is not always truthful and sometimes the video will play faster than what is expected. Additional check can be introduced by checking the total time of the video and the total number of frames and setting a delay according to that. These variables are available through the <code>GetCaptureProperty()</code> method call. Although to get the final time stamp you will have to set the <code>Capture</code> variable to the final frame before reading the time stamp and then reset it to the starting frame. More information on the <code>GetCaptureProperty()</code> method call is available [http://www.emgu.com/wiki/files/2.3.0/document/html/3ea8552d-7a4c-b7ed-d527-2602e614fb82.htm here].
 
Finally a check is done to see if the video has played all the way through, this is a relatively easy comparison of checking the current frame and seeing if it's the same number as the total number of frames. If the video has played all the way through an automated button method call is made to stop the video and the video is rewound to the beginning by setting the frame number using the <code>SetCaptureProperty()</code> method call.
 
<syntaxhighlight lang="csharp">
            if (CurrentState == VideoMethod.Viewing)
            {
                try
                {
                    //Show image
                    DisplayImage(_Capture.RetrieveBgrFrame().ToBitmap());
 
                    //Show time stamp
                    double time_index = _Capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_MSEC);
                    UpdateTextBox("Time: " + TimeSpan.FromMilliseconds(time_index).ToString(), Time_Label);
 
                    //show frame number
                    double framenumber = _Capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES);
                    UpdateTextBox("Frame: " + framenumber.ToString(), Frame_lbl);
 
                    //update trackbar
                    UpdateVideo_CNTRL(framenumber);
 
                    /*Note: We can increase or decrease this delay to fastforward of slow down the display rate
                    if we want a re-wind function we would have to use _Capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES, FrameNumber*);
                    //and call the process frame to update the picturebox ProcessFrame(null, null);. This is more complicated.*/
 
                    //Wait to display correct framerate
                    Thread.Sleep((int)(1000.0 / FrameRate)); //This may result in fast playback if the codec does not tell the truth
 
                    //Lets check to see if we have reached the end of the video
                    //If we have lets stop the capture and video as in pause button was pressed
                    //and reset the video back to start
                    if (framenumber == TotalFrames)
                    {
                        //pause button update
                        play_pause_BTN_MouseUp(null, null);
 
                        framenumber = 0;
                        UpdateVideo_CNTRL(framenumber);
                        _Capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES, framenumber);
                        //call the process frame to update the picturebox
                        ProcessFrame(null, null);
                    }
                }
                catch
                {
                }
            }
</syntaxhighlight>
 
 
Recording videos (<code>VideoMethod.Recording</code>) is a much smaller section of code as less information is displayed and <code>VideoWriter</code> is managed according to the press of the <code>play_pause_BTN</code> button. The captured frame is always displayed to the user, upon pressing the <code>play_pause_BTN</code> (now set up as a record stop button) the frames are passed to the <code>VideoWriter</code>. The video writer is disposed when the <code>play_pause_BTN</code> is pressed again this tries to provided a successful closing event for the video files so it is written correctly. This is not essential at this stage and the <code>VideoWriter</code> can be written to intermittently say every 3rd frame etc. but it must be disposed correctly using another event call such as the form closing event. Further video compression can be obtained by re-sizing the frame before passing it to the <code>VideoWriter</code> for recording to the video file.
 
<syntaxhighlight lang="csharp">
            if (CurrentState == VideoMethod.Recording)
            {
                Image<Bgr, Byte> frame = _Capture.RetrieveBgrFrame(); //capture to a Image variable so we can use it for writing to the VideoWriter
                DisplayImage(_Capture.RetrieveBgrFrame().ToBitmap()); //Show the image
 
                //if we wanted to compresse the image to a smaller size to save space on our video we could use
                //frame.Resize(100,100, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR)
                //But the VideoWriter must be set up with the correct size


<syntaxhighlight lang="csharp">Method</syntaxhighlight>
                if (recordstate && VW.Ptr != IntPtr.Zero)
                {
                    VW.WriteFrame(frame); //If we are recording and videowriter is avaliable add the image to the videowriter
                    //Update frame number
                    FrameCount++;
                    UpdateTextBox("Frame: " + FrameCount.ToString(), Frame_lbl);


                    //Show time stamp or there abouts
                    UpdateTextBox("Time: " + TimeSpan.FromMilliseconds(SW.ElapsedMilliseconds).ToString(), Time_Label);
                }
            }
</syntaxhighlight>





Revision as of 11:19, 30 November 2012

Capture: Video Files

Namespace

Emgu.CV

Emgu.CV.Capture


References

EMGU Capture Reference
EMGU VideWriter Reference
OpenCV Use Reference

Downloads

Source Code V1.0


Example

The following example shows the use of the Capture function within EMGU. The function of this library is to allow video streaming for web camera type devices and video files. This example will shows an example of reading and viewing video files, and recoding video files from a capture device using the VideWriter class. A video capture example is available here for the acquisition from devices.


Software

NameName


Pre-Requisites

The code provided should run straight out of the Emgu.Example folder (V2.4.2), extract it to this location. If the code fails to execute re-reference the EMGU libraries and include the required opencv dlls in the bin directory. Note that the project is set to build to the output path "..\..\..\bin\" you may wish to change this if you don't extract to the EMGU.Example folder.

The video record function will require a webcam or alternative capture device. It will acquire from the Os default device. Some additional video codecs may be required if they are not already installed on your system.


EMGU Coding Level: While the coding is not advanced the rated level for this example is Intermediate. This is not designed as a full on tutorial and general knowledge of the EMGU is expected. While the coding is basic the are several methods involved that may be of putting the newcomers of EMGU.


The Code

The code provided in this sample is basic there is little or no error checking. Support is available through the Forums but please try and examine the code before saying it doesn't work for you. The code is not optimised instead is better formatted to provided an understanding of the stages involved.

As the example demonstrates two methods, both viewing and recording video, some of the methods have two operations within them. They are controlled by setting VideoMethod enum called CurrentState. The methods are discussed individually in the order they appear in the code bellow.


The Code: Variables

An Open and Save file dialogue are globally declared, this is just so the file name for either saving or reading of the video can be accessed by other threads if needed.

        OpenFileDialog OF = new OpenFileDialog();
        SaveFileDialog SF = new SaveFileDialog();


The current method of viewing/recording videos is checked using the following variables. The two boolean variables playstate and recordstate are used for changing the button image and action depending on the program operation they record the play/pause/run state of the recording and viewing process. The enumerator CurrentState is used to classify the current state either 'Viewing' or 'Recording', this allows the program to operate according to reading or writing video files.

        //current video mode and state
        bool playstate = false;
        bool recordstate = false;

        VideoMethod CurrentState = VideoMethod.Viewing; //default state
        public enum VideoMethod
        {
            Viewing,
            Recording
        };


The following variables and Class initialiser variables (VW,SW, and _Capture) deal with the capture device/video, storing its variables, and for writing video files. The _Capture variable is used in two ways depending on the program operation. If viewing videos it is initialised using the Capture(string 'video file name') method. If recording a video it is initialised using the default constructor Capture() setting up the variable to capture from the default video acquisition device installed on the system. To enable selection of device see the Capture: Camera example for reference.

The VideoWriter variable VW is used to set up a video writer when recording a video from the acquisition device. Caution must be used when using the class as even when correctly disposing of the object video index buffers can still become corrupt. Using uncompressed video formats and the re-encoding the video later is the most stable method of use. Other variables are used for storing and displaying of video information.

        //Capture Setting and variables
        Capture _Capture;

        double FrameRate = 0;
        double TotalFrames = 0;

        VideoWriter VW;
        Stopwatch SW;

        int Frame_width;
        int Frame_Height;
        int FrameCount;


The Code: Methods

The Form1() method initialises the forms controls as default and no extra code is included here. TheProcessFrame() method has two sections, separated with an two if statements looking at the CurrentState of the program, either viewing or recording videos.

Viewing videos (VideoMethod.Viewing) is a fairly simple in it's application firstly it shows the frame and then updates the forms controls, labels and trackbar information. This is all done using thread safe calls to methods that include delegate operations if the controls need invoking. As the process frame is called from an independent thread set up in the Capture variable an control invoke is required to prevent cross thread interference. Then the ProcessFrame() thread is told to sleep for a specific period of time. This allows the video to be displayed at a correct frame rate. If this is removed the video will play as fast as the computer can process each frame. In this example delay is dependant on the frame rate that the video was encoded with, at least what the codec says it was. This is not always truthful and sometimes the video will play faster than what is expected. Additional check can be introduced by checking the total time of the video and the total number of frames and setting a delay according to that. These variables are available through the GetCaptureProperty() method call. Although to get the final time stamp you will have to set the Capture variable to the final frame before reading the time stamp and then reset it to the starting frame. More information on the GetCaptureProperty() method call is available here.

Finally a check is done to see if the video has played all the way through, this is a relatively easy comparison of checking the current frame and seeing if it's the same number as the total number of frames. If the video has played all the way through an automated button method call is made to stop the video and the video is rewound to the beginning by setting the frame number using the SetCaptureProperty() method call.

            if (CurrentState == VideoMethod.Viewing)
            {
                try
                {
                    //Show image
                    DisplayImage(_Capture.RetrieveBgrFrame().ToBitmap());

                    //Show time stamp
                    double time_index = _Capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_MSEC);
                    UpdateTextBox("Time: " + TimeSpan.FromMilliseconds(time_index).ToString(), Time_Label);

                    //show frame number
                    double framenumber = _Capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES);
                    UpdateTextBox("Frame: " + framenumber.ToString(), Frame_lbl);

                    //update trackbar
                    UpdateVideo_CNTRL(framenumber);

                    /*Note: We can increase or decrease this delay to fastforward of slow down the display rate
                     if we want a re-wind function we would have to use _Capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES, FrameNumber*);
                    //and call the process frame to update the picturebox ProcessFrame(null, null);. This is more complicated.*/

                    //Wait to display correct framerate
                    Thread.Sleep((int)(1000.0 / FrameRate)); //This may result in fast playback if the codec does not tell the truth

                    //Lets check to see if we have reached the end of the video
                    //If we have lets stop the capture and video as in pause button was pressed
                    //and reset the video back to start
                    if (framenumber == TotalFrames)
                    {
                        //pause button update
                        play_pause_BTN_MouseUp(null, null);

                        framenumber = 0;
                        UpdateVideo_CNTRL(framenumber);
                        _Capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES, framenumber);
                        //call the process frame to update the picturebox
                        ProcessFrame(null, null);
                    }
                }
                catch
                {
                }
            }


Recording videos (VideoMethod.Recording) is a much smaller section of code as less information is displayed and VideoWriter is managed according to the press of the play_pause_BTN button. The captured frame is always displayed to the user, upon pressing the play_pause_BTN (now set up as a record stop button) the frames are passed to the VideoWriter. The video writer is disposed when the play_pause_BTN is pressed again this tries to provided a successful closing event for the video files so it is written correctly. This is not essential at this stage and the VideoWriter can be written to intermittently say every 3rd frame etc. but it must be disposed correctly using another event call such as the form closing event. Further video compression can be obtained by re-sizing the frame before passing it to the VideoWriter for recording to the video file.

            if (CurrentState == VideoMethod.Recording)
            {
                Image<Bgr, Byte> frame = _Capture.RetrieveBgrFrame(); //capture to a Image variable so we can use it for writing to the VideoWriter
                DisplayImage(_Capture.RetrieveBgrFrame().ToBitmap()); //Show the image

                //if we wanted to compresse the image to a smaller size to save space on our video we could use
                //frame.Resize(100,100, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR)
                //But the VideoWriter must be set up with the correct size

                if (recordstate && VW.Ptr != IntPtr.Zero)
                {
                    VW.WriteFrame(frame); //If we are recording and videowriter is avaliable add the image to the videowriter 
                    //Update frame number
                    FrameCount++;
                    UpdateTextBox("Frame: " + FrameCount.ToString(), Frame_lbl);

                    //Show time stamp or there abouts
                    UpdateTextBox("Time: " + TimeSpan.FromMilliseconds(SW.ElapsedMilliseconds).ToString(), Time_Label);
                }
            }


Methods Available

Used

  • name()


Unused

  • name()


Bugs

  1. Numbered list If any