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
Related
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();
}
}
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;
I get a pictureboxe and try to add it an action to change background Image upon click event happen, but there is no action. So, this is the code:
pieces bishopBB = new pieces();
public Form1()
{
// object of picturebox
bishopBB.Location = new Point(300, 455);
bishopBB.Parent = this;
bishopBB.Click += new System.EventHandler(pictureboxes_Click)
InitializeComponent();
}
private void pictureboxes_Click(object sender, EventArges e)
{
backgroundImage = Properties.Resources.black;
}
Looking at the name and other indicators I would assume (and hope) that pictureboxes_Click is a common click handler for many PictureBoxes.
So to access the one that has been clicked you need to cast sender to PictureBox and then set the BackgroundImage:
private void pictureboxes_Click(object sender, EventArges e)
{
((PictureBox)sender).BackgroundImage = Properties.Resources.black;
}
I'm a little amazed though that your spelling of backgroundImage compiles. The correct spelling BackgroundImage refers to the current class, usually the Form and it should also show, unless your Form has a black background already..
To change the current image of the PictureBox control, you need to refer to the control and reference the BackgroundImage property (not 'backgroundImage'):
private void pictureboxes_Click(object sender, EventArges e)
{
this.pictureboxes.BackgroundImage = Properties.Resources.black;
}
To change the background image of the form:
private void pictureboxes_Click(object sender, EventArgs e)
{
this.BackgroundImage = Properties.Resources.black;
}
To do this you can use the on_click property of the picturebox. You can then use the like picbox.image = whatever the image location is
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 picturebox with picture cb.
PBr1_1.Image = new Bitmap(#"Logos\\Images\\cb.png");
I'd like to change image to cg.png and do some action when i click this image. I was trying something like that but without success:
private void PBr1_1_Click(object sender, EventArgs e)
{
if (PBr1_1.Image.ToString() == "cb.png")
{
PBr1_1.Image = new Bitmap(#"Logos\\Images\\cg.png");
// Do some stuff.
}
}
And then do the same when i click image with cb. To visualise this cb is black circle button image, and cg is green one.
How can i do this?
Jason is right, you should use some kind of temporary storage to save your current bitmap.
The Tag property is useful in this kind of situations. Here a sample code: (Without error handling)
somewhere in your load event
PBr1.Tag = "cb.png";`
PBr1_1.Image = new Bitmap(Path.Combine("Logos\\Images", PBr1.Tag.ToString());
and then in button click
private void PBr1_1_Click(object sender, EventArgs e)
{
string imgPath = "Logos\\Images";
PBr1_1.Image.Dispose();
PBr1_1.Tag = (PBr1_1.Tag == "cb.png" ? "cg.png") : "cb.png") ;
Bitmap bm = new Bitmap(Path.Combine(imgPath, PBr1.Tag.ToString());
PBr1_1.Image = bm;
}
Are you sure that "PBr1_1.Image.ToString()" really returns only the image name?
Maybe you should check this by writing PBr1_1.Image.ToString() to console or something like that