I have a C# Winforms project in which I have to capture an image from an external webcam (Logitech HD Pro C920). I am using the Aforge media library. The list of video input devices are showing up, and the laptop's internal webcam is connecting and the stream is being displayed in the picturebox.
However the stream from the USB cam is not being displayed in the picturebox even though it is listed as a video input device. The relevant code is shown below:
cam = new VideoCaptureDevice(webcam[cbCameras.SelectedIndex].MonikerString);
cam.NewFrame +=new NewFrameEventHandler(cam_NewFrame);
cam.Start();
void cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Bitmap bit = (Bitmap)eventArgs.Frame.Clone();
picPhoto.Image = bit;
}
Where am I missing it? Thanks
Try this:
public VideoCapabilities[] videoCapabilities;
videoCapabilities = Cam.VideoCapabilities;
Cam.VideoResolution = videoCapabilities[0];
Finally I found the solution by changing the way I used to select the webcam. Now, I opted for the form provided by AForge (VideoCaptureDeviceForm).
Here is the Code:
private void BtnCamSelection_Click(object sender, RoutedEventArgs e)
{
VideoCaptureDeviceForm form = new VideoCaptureDeviceForm();
if(form.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
this.pVideoSource = form.VideoDevice;
}
}
Then, I loaded the aforge:VideoSourcePlayer with the variable pVideoSource.
I also had the same problem as shown here. There is a fix and a 'Workaround'.
Using the VideoCaptureDeviceForm does work and this is fine if you want to display this form.
The Problem
It appears the Logitect C920 doesn't have a default video resolution, or AForge isn't setting it. Other webcams seem to perform correctly.
The Fix
I was able to fixed the issue going on Laurenz Albes answer. This will just set the default resolution to the first in the array of camera supported resolutions, which seems to be the lowest. You can add logic to set the resoution you want.
From the question asked on here before
How initialize AForge webcam
public Form1() // init
{
InitializeComponent();
{
VideoCaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
foreach (FilterInfo VideoCaptureDevice in VideoCaptureDevices)
{
comboBox1.Items.Add(VideoCaptureDevice.Name);
}
comboBox1.SelectedIndex = 0;
}
}
private void button1_Click(object sender, EventArgs e)
{
FinalVideo = new VideoCaptureDevice(VideoCaptureDevices[comboBox1.SelectedIndex].MonikerString);
FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
FinalVideo.Start();
}
void FinalVideo_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Bitmap video = (Bitmap)eventArgs.Frame.Clone();
pictureBox1.Image = video;
}
private void button2_Click(object sender, EventArgs e)
{
FinalVideo.Stop();
}
}
Related
I want to make a picture change itself very fast between 2 pictures. I have the pictures saved in the debug folder of the program.
Here is the image of pictures with there names saved:
https://i.stack.imgur.com/XQ9g5.png
So here is the code were I save a picture in the picturebox so that there is not an empty picturebox
private void Gamble_Load(object sender, EventArgs e)
{
pictureBox1.Image = (Image.FromFile("21.png"));
}
And here is the timer click method I think I need to use for this action
private void timer1_Tick(object sender, EventArgs e)
{
pictureBox1.Image = pictureBox1.Image is null;
}
Try putting this in your Gamble_Load:
var t = new Timer(x => pictureBox1.Image = (Image.FromFile("otherimage.png")), null, 1000);
This creates a timer that will fire after 1 second and update the image.
https://learn.microsoft.com/en-us/dotnet/api/system.timers.timer?view=net-6.0
How can I freeze the video displayed in the CameraControl when TakeSnapshot() has been called in order to display the fetched image?
Basically, I would like to rebuild the same capture behaviour as in the devexpress TakePictureDialog class in my own form, because in the TakePictureDialog it does not seem to be possible to store the user-selected camera device, which I need to do in my app, though.
I followed the instructions and examples in these articles:
https://www.devexpress.com/Support/Center/Question/Details/T269133/obtaining-the-last-selected-camera-device-and-restoring-it-in-a-takepicturedialog
https://documentation.devexpress.com/WindowsForms/114582/Controls-and-Libraries/Editors-and-Simple-Controls/Camera-Control
UserAppDataReigistry not persisting
Welcome to the stackoverflow.
CameraControl doesn't provide that functionality itself.
Either way you can use the Paint event to render the image, obtained via TakeSnapshot.
Something like this:
private void CameraControl1_Paint(object sender, PaintEventArgs e)
{
CameraControl c = sender as CameraControl;
if (isStopped && img != null)
e.Graphics.DrawImage(img, new Rectangle(0,0, c.Width, c.Height));
}
bool isStopped = false;
Bitmap img;
private void button1_Click(object sender, EventArgs e)
{
img = cameraControl1.TakeSnapshot();
cameraControl1.Stop();
isStopped = true;
}
Credits from devexpress.com
I'm doing a very simple program on EMGU CV, so I need to take a screenshot of what my camera is recording and save it in a specific folder, here follows my code of camera capture:
ImageViewer viewer = new ImageViewer();
VideoCapture capture = new VideoCapture();
Application.Idle += new EventHandler(delegate (object sender, EventArgs e)
{
viewer.Image = capture.QueryFrame();
});
viewer.ShowDialog();
I apologize for the simple terms, I still really noob in programming.
It seems like you just posted the standard code from the EmguCV wiki. But let me try to explain how you can show a video feed of your webcam on your computer and save a screenshot when you press a button (you'll have to create all the UI elements yourself). You'll need a form with an PictureBox element to display the image and a button to save a snapshot.
I'll explain everything in the code through comments and work from the standard EmguCV code:
private Capture capture;
private bool takeSnapshot = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Make sure we only initialize webcam capture if the capture element is still null
if (capture == null)
{
try
{
// Start grabbing data, change the number if you want to use another camera
capture = new Capture(0);
}
catch (NullReferenceException excpt)
{
// No camera has been found
MessageBox.Show(excpt.Message);
}
}
// This makes sure the image will be fitted into your picturebox
originalImageContainer.SizeMode = PictureBoxSizeMode.StretchImage;
// When the capture is initialized, start processing the images in the PorcessFrame method
if (capture != null)
Application.Idle += ProcessFrame;
}
// You registered this method, so whenever the application is Idle, this method will be called.
// This allows you to process a new frame during that time.
private void ProcessFrame(object sender, EventArgs arg)
{
// Get the newest webcam frame
Image<Bgr, double> capturedImage = capture.QueryFrame();
// Show it in your PictureBox. If you don't want to convert to Bitmap you should use an ImageBox (which is an EmguCV element)
originalImageContainer.Image = capturedImage.ToBitmap();
// If the button was clicked indicating you want a snapshot, save the image
if(takeSnapshot)
{
// Save the image
capturedImage.Save(#"C:\your\picture\path\image.jpg");
// Set the bool to false again to make sure we only take one snapshot
takeSnapshot = !takeSnapshot;
}
}
//When clicking the save button
private void SaveButton_Click(object sender, EventArgs e)
{
// Set the bool to true, so that on the next frame processing the frame will be saved
takeSnapshot = !takeSnapshot;
}
Hope this helps you. Let me know if anything is still unclear!
Sometimes Bgr cannot be converted to bitmap directly. Instead I do employ
following lines:
Emgu.CV.Mat capturedImage = capture.QueryFrame();
pictureBox1.Image = capturedImage.Bitmap;
Is there any way for how to record the images into a video file (output.avi) by implementing some code inside the NewFrame event handler. Also how can we make the size of file not too much big?
I've got a pictureBox1 and a button1 and I'm using the code below to switch on the webcam and display the output on pictureBox1
The code works fine. However, I need to implement a way to Save the output to a video file rather than showing it on the pictureBox
I use the code below
private void button1_Click(object sender, EventArgs e)
{
videoSource = new VideoCaptureDevice(videoDevices[comboBox1.SelectedIndex].MonikerString);
videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
///
CloseVideoSource();
videoSource.Start();
}
private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Bitmap img = (Bitmap)eventArgs.Frame.Clone();
pictureBox1.Image = img; // Something should go here to make the video file out of successive bitmaps ?
}
private void CloseVideoSource()
{
if (!(videoSource == null))
if (videoSource.IsRunning)
{
videoSource.SignalToStop();
videoSource = null;
}
}
I think all you need is to use the VideoFileWriter class. There's a nice demo in the AForge.Net documentation.
Note that your code will need to include the FFMPEG dlls found in the Externals folder in your AForge installation directory.
I have the following code to display an image in imagebox using EmgucV:
Capture capture;
Image<Bgr, Byte> image;
public Form1()
{
InitializeComponent();
Application.Idle += new EventHandler(Start);
}
void Start(object sender, EventArgs e)
{
capture = new Capture();
image = capture.QueryFrame();
imageBox1.Image = image;
}
I get the exception Attempted to read or write protected memory. What do I need to do to correct this?
This is an indication of possible native memory leak
I think there is an error in your code. Your Start method will get called many times (very often) during application lifetime.
It looks like you should use only one Capture object in your application.
Simply move your Capture instantiation to Form constructor:
Capture capture;
public Form1()
{
InitializeComponent();
Application.Idle += new EventHandler(Capture);
capture = new Capture();
}
void Capture(object sender, EventArgs e)
{
imageBox1.Image = capture.QueryFrame();
}
The current fix for Emgu CV version 3.4.1 using Windows Form c#; add one button call it btnCapture, add one PictureBox control leave the name to its defaults for the purpose of this answer. hope this code example helps
public VideoCapture capture;
private void btnCatpure_Click(object sender, EventArgs e)
{
// each click a single frame will be capture and then display in the control.
Mat iframe = new Mat();
capture.Retrieve(iframe, 0);
Mat grayFrame = new Mat();
CvInvoke.CvtColor(iframe, grayFrame, ColorConversion.Bgr2Gray);
pictureBox1.Image = iframe.Bitmap;
pictureBox1.Image = grayFrame.Bitmap;
}