Camera Capture - Legacy: Difference between revisions
m →Example |
|||
(3 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
==Camera Capture - Legacy | ==Camera Capture - Legacy== | ||
===Namespace=== | ===Namespace=== | ||
Line 11: | Line 11: | ||
====Downloads==== | ====Downloads==== | ||
[Source Code V2.0 | [http://sourceforge.net/projects/emguexample/files/Capture/CameraCapture%20V2.0%20-%20Legacy.zip/download Source Code V2.0] | ||
==Example== | ==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 | 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 the legacy method of web camera capture as well as reading and setting properties of the camera. Only some function is available in this version to demonstrate the methods available to the user. A video file example is available [http://www.emgu.com/wiki/index.php?title=Video_Files here]. | ||
The key difference from this example and the [http://www.emgu.com/wiki/index.php?title=Camera_Capture Capture: Camera] example is .... | The key difference from this example and the [http://www.emgu.com/wiki/index.php?title=Camera_Capture Capture: Camera] example is that frames are acquired during when the <code> Application.Idle</code> event fires. This is a static event, and you must detach the event handlers when the application is disposed, or memory leaks will result. It is still a valid method for acquisition however the frame rate of the camera is based upon the form processing being completed first. There are a few more method handlers available with this methods see | ||
'''Software''' | '''Software''' | ||
[[File:|ScreenShot|400px]] | [[File:Cam Capture LegacyV2 ScreenShot.png|ScreenShot|400px]] | ||
Line 100: | Line 100: | ||
The method <code>ProcessFrame()</code> simply switches between what type of capture event is used either <code> | The method <code>ProcessFrame()</code> simply switches between what type of capture event is used either <code>QueryFrame()</code>, <code>QueryGrayFrame()</code>, or <code>QuerySmallFrame</code> according to the selected checkbox on the form. The frame can be displayed straight into the picture box regardless of SizeMode as the <code>pplication.Idle</code> thread belongs to this form unlike in the _capture.ImageGrabbed event method (see [http://www.emgu.com/wiki/index.php?title=Camera_Capture here]). | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
Line 110: | Line 110: | ||
if (RetrieveBgrFrame.Checked) | if (RetrieveBgrFrame.Checked) | ||
{ | { | ||
Image<Bgr, Byte> frame = _capture.RetrieveBgrFrame() | Image<Bgr, Byte> frame = _capture.QueryFrame(); //alternativly RetrieveBgrFrame() works in the same manner | ||
// | //As the Application.Idle thread belongs to this form we no longer need to invoke the picturebox as with the _capture.ImageGrabbed event method | ||
captureBox.Image = frame.ToBitmap(); | |||
} | } | ||
else if (RetrieveGrayFrame.Checked) | else if (RetrieveGrayFrame.Checked) | ||
{ | { | ||
Image<Gray, Byte> frame = _capture.RetrieveGrayFrame(); | Image<Gray, Byte> frame = _capture.QueryGrayFrame();//alternativly .RetrieveGrayFrame(); works in the same manner | ||
// | //As the Application.Idle thread belongs to this form we no longer need to invoke the picturebox as with the _capture.ImageGrabbed event method | ||
captureBox.Image = frame.ToBitmap(); | |||
} | } | ||
else if (QuerySmallFrame.Checked) | |||
if ( | |||
{ | { | ||
Image<Bgr, Byte> frame = _capture.QuerySmallFrame(); | |||
captureBox.Image = frame.ToBitmap(); | |||
captureBox.Image = | |||
} | } | ||
} | } | ||
Line 149: | Line 130: | ||
The method <code>captureButtonClick()</code> looks complex but it's mainly for error checking purposes. As we are allowing the user to set/change the camera according to form settings we need to look for this. This can be done within the <code>SelectedIndexChanged</code> method as an alternative. First we see if the <code>_capture</code> variable has been initiated yet. If not then we call the <code>SetupCapture();</code> method to set the Camera_Identifier and | The method <code>captureButtonClick()</code> looks complex but it's mainly for error checking purposes. As we are allowing the user to set/change the camera according to form settings we need to look for this. This can be done within the <code>SelectedIndexChanged</code> method as an alternative. First we see if the <code>_capture</code> variable has been initiated yet. If not then we call the <code>SetupCapture();</code> method to set the Camera_Identifier and construct <code>_capture</code> variable. We then recall the same event to initialise the the camera as it will instantly fall down to the <code>RetrieveCaptureInformation()</code> method call. Here is where we attach an event handler to the <code>Application.Idle</code> event. | ||
If the <code>_capture</code> variable has been initialised the we either stop the camera acquiring or check to see if camera selection has changed before restarting the camera. If the camera selection has changed then <code>SelectedIndexChanged</code> is called again to dispose of the old <code>_capture</code> and re-initialise a new one. | If the <code>_capture</code> variable has been initialised the we either stop the camera acquiring by detaching the <code>Application.Idle</code> event or check to see if camera selection has changed before restarting the camera. If the camera selection has changed then <code>SelectedIndexChanged</code> is called again to dispose of the old <code>_capture</code> and re-initialise a new one. | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
Line 163: | Line 144: | ||
//stop the capture | //stop the capture | ||
captureButton.Text = "Start Capture"; //Change text on button | captureButton.Text = "Start Capture"; //Change text on button | ||
Slider_Enable(false); | Slider_Enable(false); | ||
//Because this is a static event, you must detach your event handlers when your application is disposed, or memory leaks will result. | |||
Application.Idle -= new EventHandler(ProcessFrame); //detach the idle event handler | |||
_captureInProgress = false; //Flag the state of the camera | _captureInProgress = false; //Flag the state of the camera | ||
} | } | ||
Line 179: | Line 161: | ||
StoreCameraSettings(); //Save Camera Settings | StoreCameraSettings(); //Save Camera Settings | ||
Slider_Enable(true); //Enable User Controls | Slider_Enable(true); //Enable User Controls | ||
Application.Idle += new EventHandler(ProcessFrame); //attach or re-attach the idle event handler | |||
_captureInProgress = true; //Flag the state of the camera | _captureInProgress = true; //Flag the state of the camera | ||
} | } | ||
Line 204: | Line 186: | ||
//Dispose of Capture if it was created before | //Dispose of Capture if it was created before | ||
if (_capture != null) _capture.Dispose(); | if (_capture != null) | ||
{ | |||
_capture.Dispose(); | |||
} | |||
try | try | ||
{ | { | ||
//Set up capture device | //Set up capture device | ||
_capture = new Capture(CameraDevice); | _capture = new Capture(CameraDevice); | ||
} | } | ||
catch (NullReferenceException excpt) | catch (NullReferenceException excpt) | ||
Line 284: | Line 268: | ||
*Capture(Int32) | *Capture(Int32) | ||
*Dispose() | *Dispose() | ||
*QueryFrame() <b>Legacy Method</b> | |||
*QueryGrayFrame() <b>Legacy Method</b> | |||
*QuerySmallFrame() <b>Legacy Method</b> | |||
*GetCaptureProperty(CAP_PROP) | *GetCaptureProperty(CAP_PROP) | ||
*SetCaptureProperty(CAP_PROP, Double) | *SetCaptureProperty(CAP_PROP, Double) | ||
'''Unused''' | '''Unused''' | ||
Line 294: | Line 279: | ||
*Capture() | *Capture() | ||
*Capture(String) | *Capture(String) | ||
*Start() | |||
*Stop() | |||
*Wait() | |||
*RetrieveBgrFrame() | |||
*RetrieveGrayFrame() | |||
*RetrieveBgrFrame(Int32) | *RetrieveBgrFrame(Int32) | ||
*RetrieveGrayFrame(Int32) | *RetrieveGrayFrame(Int32) | ||
*DuplexQueryFrame() <b>WCF dependant</b> | *DuplexQueryFrame() <b>WCF dependant</b> | ||
*DuplexQuerySmallFrame() <b>WCF dependant</b> | *DuplexQuerySmallFrame() <b>WCF dependant</b> | ||
*Equals(Object) | *Equals(Object) | ||
*GetHashCode() | *GetHashCode() |
Latest revision as of 13:18, 27 November 2012
Camera Capture - Legacy
Namespace
Emgu.CV.Capture
References
EMGU Reference
EMGU CV_PROP Reference
OpenCV 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 the legacy method of web camera capture as well as reading and setting properties of the camera. Only some function is available in this version to demonstrate the methods available to the user. A video file example is available here.
The key difference from this example and the Capture: Camera example is that frames are acquired during when the Application.Idle
event fires. This is a static event, and you must detach the event handlers when the application is disposed, or memory leaks will result. It is still a valid method for acquisition however the frame rate of the camera is based upon the form processing being completed first. There are a few more method handlers available with this methods see
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.
A Web camera is required for this example.
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.
The Code
The code provided in this sample is basic there is only someo 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.
Each method is split up to do it's own function while there are several methods in the code the code is not advanced and is often repetitive. The new features introduced in this code is the ability to select the camera source through Direct Show (dll supplied). The code shows the use of two functions for acquiring the frame the others are legacy based and will not work see the Methods Available section. This example also shows how to get and set camera features such as Brightness, Contrast, and Sharpness. While other settings are available only these three attributes are changeable from the form interface. It is easy to add additional support for other settings, these will be made available in future iterations of the example.
The Code: Variables
There are only a few variables in the example separated into two regions the first Camera Capture Variables
contains the variables for camera information and the capture device. The Video_Device[]
array is a custom structure to store video information this is discussed bellow.
#region Camera Capture Variables
private Capture _capture = null; //Camera
private bool _captureInProgress = false; //Variable to track camera state
int CameraDevice = 0; //Variable to track camera device selected
Video_Device[] WebCams; //List containing all the camera available
#endregion
The second region Camera Settings
simply stores the original setting of the camera when it is loaded this is useful in case we need to reset the values to the way we had them.
#region Camera Settings
int Brightness_Store = 0;
int Contrast_Store = 0;
int Sharpness_Store = 0;
#endregion
The Code: Methods
As discussed there are several method in the code, they will be decribed in the order that they appear in the code.
The method CameraCapture()
is the form initialiser here we disable all our sliders on the form with the method call of Slider_Enable(false)
. We gather all the video devices available on the system using the Direct Show library (Supplied in the 'Lib' Folder). We populate both an array of Video_Device
s and the combo box on the form to enable user selection. Finally we set the combo box to the first index '0' which will be the default device of the OS.
public CameraCapture()
{
InitializeComponent();
Slider_Enable(false); //Disable sliders untill capturing
//-> Find systems cameras with DirectShow.Net dll
//thanks to carles lloret
DsDevice[] _SystemCamereas = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
WebCams = new Video_Device[_SystemCamereas.Length];
for (int i = 0; i < _SystemCamereas.Length; i++)
{
WebCams[i] = new Video_Device(i, _SystemCamereas[i].Name, _SystemCamereas[i].ClassID); //fill web cam array
Camera_Selection.Items.Add(WebCams[i].ToString());
}
if (Camera_Selection.Items.Count > 0)
{
Camera_Selection.SelectedIndex = 0; //Set the selected device the default
captureButton.Enabled = true; //Enable the start
}
}
The method ProcessFrame()
simply switches between what type of capture event is used either QueryFrame()
, QueryGrayFrame()
, or QuerySmallFrame
according to the selected checkbox on the form. The frame can be displayed straight into the picture box regardless of SizeMode as the pplication.Idle
thread belongs to this form unlike in the _capture.ImageGrabbed event method (see here).
private void ProcessFrame(object sender, EventArgs arg)
{
//***If you want to access the image data the use the following method call***/
//Image<Bgr, Byte> frame = new Image<Bgr,byte>(_capture.RetrieveBgrFrame().ToBitmap());
if (RetrieveBgrFrame.Checked)
{
Image<Bgr, Byte> frame = _capture.QueryFrame(); //alternativly RetrieveBgrFrame() works in the same manner
//As the Application.Idle thread belongs to this form we no longer need to invoke the picturebox as with the _capture.ImageGrabbed event method
captureBox.Image = frame.ToBitmap();
}
else if (RetrieveGrayFrame.Checked)
{
Image<Gray, Byte> frame = _capture.QueryGrayFrame();//alternativly .RetrieveGrayFrame(); works in the same manner
//As the Application.Idle thread belongs to this form we no longer need to invoke the picturebox as with the _capture.ImageGrabbed event method
captureBox.Image = frame.ToBitmap();
}
else if (QuerySmallFrame.Checked)
{
Image<Bgr, Byte> frame = _capture.QuerySmallFrame();
captureBox.Image = frame.ToBitmap();
}
}
The method captureButtonClick()
looks complex but it's mainly for error checking purposes. As we are allowing the user to set/change the camera according to form settings we need to look for this. This can be done within the SelectedIndexChanged
method as an alternative. First we see if the _capture
variable has been initiated yet. If not then we call the SetupCapture();
method to set the Camera_Identifier and construct _capture
variable. We then recall the same event to initialise the the camera as it will instantly fall down to the RetrieveCaptureInformation()
method call. Here is where we attach an event handler to the Application.Idle
event.
If the _capture
variable has been initialised the we either stop the camera acquiring by detaching the Application.Idle
event or check to see if camera selection has changed before restarting the camera. If the camera selection has changed then SelectedIndexChanged
is called again to dispose of the old _capture
and re-initialise a new one.
private void captureButtonClick(object sender, EventArgs e)
{
if (_capture != null)
{
if (_captureInProgress)
{
//stop the capture
captureButton.Text = "Start Capture"; //Change text on button
Slider_Enable(false);
//Because this is a static event, you must detach your event handlers when your application is disposed, or memory leaks will result.
Application.Idle -= new EventHandler(ProcessFrame); //detach the idle event handler
_captureInProgress = false; //Flag the state of the camera
}
else
{
//Check to see if the selected device has changed
if (Camera_Selection.SelectedIndex != CameraDevice)
{
SetupCapture(Camera_Selection.SelectedIndex); //Setup capture with the new device
}
RetrieveCaptureInformation(); //Get Camera information
captureButton.Text = "Stop"; //Change text on button
StoreCameraSettings(); //Save Camera Settings
Slider_Enable(true); //Enable User Controls
Application.Idle += new EventHandler(ProcessFrame); //attach or re-attach the idle event handler
_captureInProgress = true; //Flag the state of the camera
}
}
else
{
//set up capture with selected device
SetupCapture(Camera_Selection.SelectedIndex);
//Be lazy and Recall this method to start camera
captureButtonClick(null, null);
}
}
The method SetupCapture()
is a simple method it records the selected index for the chosen camera provided to the method. Then it disposes of the existing _capture
variable if it exists and then attempts to re-initialise a new one.
private void SetupCapture(int Camera_Identifier)
{
//update the selected device
CameraDevice = Camera_Identifier;
//Dispose of Capture if it was created before
if (_capture != null)
{
_capture.Dispose();
}
try
{
//Set up capture device
_capture = new Capture(CameraDevice);
}
catch (NullReferenceException excpt)
{
MessageBox.Show(excpt.Message);
}
}
The method FlipHorizontalButtonClick()
simply sets the FlipHorizontal flag of the _capture
variable. Similarly the FlipVerticalButtonClick()
method sets the FlipVertical flag. Each one flips the produced frame according to the flag direction.
The method RetrieveCaptureInformation()
demonstrates the use of the GetCaptureProperty()
. A majority of the variables gathered from this method are simply displayed in the richtextbox on the form. Only Brightness, Contrast, and Sharpness are saved to variables and slider values for adjustment. If a method is invalid it will usually return a '-1'. The commented GetCaptureProperty()
calls are used for specific devices. Not all properties are writeable through the SetCaptureProperty(). For more reference see
private void RetrieveCaptureInformation()
{
richTextBox1.Clear();
richTextBox1.AppendText("Camera: " + WebCams[CameraDevice].Device_Name + " (-1 = Unknown)\n\n");
//Brightness
richTextBox1.AppendText("Brightness: " + _capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_BRIGHTNESS).ToString() + "\n"); //get the value and add it to richtextbox
Brigtness_SLD.Value = (int)_capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_BRIGHTNESS); //Set the slider value
Brigthness_LBL.Text = Brigtness_SLD.Value.ToString(); //set the slider text
//Contrast
richTextBox1.AppendText("Contrast: " + _capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_CONTRAST).ToString() + "\n");//get the value and add it to richtextbox
Contrast_SLD.Value = (int)_capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_CONTRAST); //Set the slider value
Contrast_LBL.Text = Contrast_SLD.Value.ToString(); //set the slider text
//Sharpness
richTextBox1.AppendText("Sharpness: " + _capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_SHARPNESS).ToString() + "\n");
Sharpness_SLD.Value = (int)_capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_CONTRAST); //Set the slider value
Sharpness_LBL.Text = Sharpness_SLD.Value.ToString(); //set the slider text
....
}
The method StoreCameraSettings()
is called after the _capture
variable is initialised, it simply records the values that have been assigned to the sliders by the GetCaptureProperty()
method call. It does does as it is more efficient that invoking the GetCaptureProperty()
method again. It simply stores the values that can be adjusted by the user in global variables allowing the camera properties to be reset to their original state. This is useful in case adjustments are made that the user does not want to save.
The method Refresh_BTN_Click()
simply allows the user to re-read the camera setting from the RetrieveCaptureInformation()
method. This allows the user to see some of the limitations of the values they can use and ensure that the camera setting have been updated.
The method Reset_Cam_Settings_Click()
resets the overwritten properties to those initially read in when the camera was initialised. It does this using the SetCaptureProperty()
method call.
private void Reset_Cam_Settings_Click(object sender, EventArgs e)
{
if (_capture != null)
{
_capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_BRIGHTNESS, Brightness_Store);
_capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_CONTRAST, Contrast_Store);
_capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_SHARPNESS, Sharpness_Store);
RetrieveCaptureInformation(); // This will refresh the settings
}
}
The region Sliders
contains four methods the 'Scroll' call simply update the associated label and sets the camera variable using the SetCaptureProperty()
. The Slider_Enable
method simply allows the 'Enable' state of the scroll bars to be set all together rather than individually.
The method OnClosing()
will reset the camera to the default settings using the Reset_Cam_Settings_Click()
method unless the user has stopped capturing from the device. If a user stops the capture the setting will be saved by default. This method will dispose of the _capture
object to release the camera.
Methods Available
Used
- Capture(Int32)
- Dispose()
- QueryFrame() Legacy Method
- QueryGrayFrame() Legacy Method
- QuerySmallFrame() Legacy Method
- GetCaptureProperty(CAP_PROP)
- SetCaptureProperty(CAP_PROP, Double)
Unused
- Capture()
- Capture(String)
- Start()
- Stop()
- Wait()
- RetrieveBgrFrame()
- RetrieveGrayFrame()
- RetrieveBgrFrame(Int32)
- RetrieveGrayFrame(Int32)
- DuplexQueryFrame() WCF dependant
- DuplexQuerySmallFrame() WCF dependant
- Equals(Object)
- GetHashCode()
- GetType()
- MemberwiseClone()
- ToString()
Bugs
(None to Date)