Video Files: Difference between revisions
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 | '''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. | ||
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==== | ||
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"> | <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==== | ||
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 | |||
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
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
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
- Numbered list If any