I'm writing a program to save some webcam video to a file. I'm using the x264 codec found here x264.
When I try writing frames to a file I get this warning message poping up. It still records the video. But I don't want this popup showing on the screen.
x264vfw [warning]: Few frames probably would be lost. Ways to fix this:
x264vfw [warning]: -if you use VirtualDub or its fork than you can enable 'VirtualDub Hack' option
x264vfw [warning]: -you can enable 'File' output mode
x264vfw [warning]: -you can enable 'Zero Latency' option
Is there anyway to config "File ouput mode" or "Zero Latency" by using C# or C++ or command line?
This is the code:
public static void StartCapture()
{
try
{
capture = new Capture();
capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_WIDTH, 1920); //1920
capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT, 1080); //1080
CaptureOutput = new VideoWriter
(
"capture output.avi",
CvInvoke.CV_FOURCC('X','2','6','4'),
50, //fps
(int)capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_WIDTH),
(int)capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT),
true
);
if (capture != null)
{
capture.ImageGrabbed += SaveFrame;
capture.Start();
}
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
static void SaveFrame(System.Object sender, EventArgs e)
{
Image<Bgr, Byte> video;
video = capture.RetrieveBgrFrame();
CaptureOutput.WriteFrame(video);
}
Related
I'm using EmguCV 3.4.3.3016 to grab frame from camera. Below is the code for simply grab a frame everytime button1 is clicked. My problem is that the program doesn't release resource so memory used for the program is increasing very fast (up to GBs) and lead to program not responding and then crash.
Anyone knows the reason and solution?
private void button1_Click(object sender, EventArgs e)
{
if (cap != null)
{
cap = new VideoCapture(0);
}
Mat img = new Mat();
cap.Grab();
cap.Retrieve(img);
pictureBox1.Image = img.Bitmap;
}
I encountered the same problem like you before. It's not because of your code or the EmguCV, but it related to debugging setting of your solution. Try removing checking at the Tools>Options>Debugging>Suppress JIT optimization on module load.
I can run your code normally. Do you have any other dependency? Which is your machine's window version, 32 or 64 bit? Try to debug it in the correct platform, Debug -> [your-project] Properties -> Build -> Platform target.
Turns out, EmguCV is just the wrapper of OpenCV, we need to clean it up manually by using GC.Collect().
private void button1_Click(object sender, EventArgs e)
{
if (cap != null) //Why... Are you sure? Not cap==null ???
{
cap.Dispose();
cap = new VideoCapture(0);
}
Mat img = new Mat();
cap.Grab();
cap.Retrieve(img);
if (pictureBox1.Image != null)
{
var tempImage = pictureBox1.Image;
pictureBox1.Image = null;
tempImage.Dispose();
}
pictureBox1.Image =new Bitmap( img.Bitmap);
img.Dispose();
}
I have an accord videoSourcePlayer control in my form.Why is it that it is not rendering the video that I select? Please see my code below:
// Open video file using DirectShow
private void openVideoFileusingDirectShowToolStripMenuItem_Click(object sender, EventArgs e)
{
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
// create video source
FileVideoSource = new FileVideoSource(openFileDialog.FileName);
// open it
sourceInitialiization = true;
OpenVideoSource(FileVideoSource);
}
}
// Open video source
private void OpenVideoSource(IVideoSource source)
{
// set busy cursor
this.Cursor = Cursors.WaitCursor;
// close previous video source
CloseVideoSource();
// start new video source
videoSourcePlayer.VideoSource = new AsyncVideoSource(source);
videoSourcePlayer.Start();
// reset statistics
statIndex = statReady = 0;
// start timers
timer.Start();
alarmTimer.Start();
//alarmTimer1.Start();
videoSource = source;
this.Cursor = Cursors.Default;
}
In my laptop where I initially coded this program, this works perfectly, but if I transfer it to another machine, say a desktop or another laptop, the code doesn't work anymore. It runs but it doesn't render the video and there is not error detected in the debugger too.
I tried downloading a sample video project from accord framework but I still couldn't get it to play a video on the desktop except on my laptop. What am I missing? Thank you.
Have you subscribed to the NewFrameReceived event?
I need a simple, but complete, example of capturing a snapshot from Logitech USB webcam in a console application, but I don't find.
The next instruction not works.
private Capture _capture = null; //Camera
Where is Capture definition? In the Emgu.CV.World not it is.
I use the 3.2.0 version of EmguCV.
http://www.emgu.com/wiki/index.php?title=Camera_Capture
Thank you in advance.
The error is the attached image
Did you read the entire article? It is instantiated here:
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);
_capture.ImageGrabbed += ProcessFrame;
}
catch (NullReferenceException excpt)
{
MessageBox.Show(excpt.Message);
}
}
Hope this helps.
Doug
I am trying to change the code http://sites.google.com/site/webcamlibrarydotnet/winfrom-and-csharp-sample-code-and-download from picture box to image or bitmap as I dont want to display any image or plan to display, all I want is that it will output the image to file.
I have tried changing the webcam.cs from PictureBox _FrameImage to Bitmap _FrameImage and PictureBox ImageControl to Bitmap ImageControl and casting (Bitmap) at e.WebCamImage
As well as changing it on the main form:
private void bWebcam_Click(object sender, EventArgs e)
{
WebCam webcam = new WebCam();
Bitmap image = null;
webcam.InitializeWebCam(ref image);
webcam.Start();
webcam.Stop();
FileStream fstream = new FileStream("testWebcam.jpg", FileMode.Create);
image.Save(fstream, System.Drawing.Imaging.ImageFormat.Jpeg);
fstream.Close();
}
Unhappyly it doesnt seem to work so
how could I change it from picture
box to Bitmap or Image or similar
storage before saving it to a file or
save it to file directly ?
The source code I am using is:
http://sites.google.com/site/webcamlibrarydotnet/winfrom-and-csharp-sample-code-and-download
Instead of using the WebCam class, why not just use the WebCamCapture class directly (since you are not displaying this in a form) and handle the ImageCapture event directly. The event argument for the event contains the Image. You could, in the event handler save the image to disk. Alternately, if you want to use the sample and the WebCam class, and you have a form. Use a PictureBox but leave it hidden (set Visible to false) and then just copy the image from there and save to disk when you need to.
Here is some sample code of using the WebCamCapture class instead of the WebCam class. It should be noted that this code is based on the sample code from the link provided in the question. I have kept the style of the sample so that code lines up.
Edit: Adding example of using WebCamCapture instead of WebCam class. This code should be used to modify Form1.cs in the sample code.
// Instead of having WebCam as member variable, have WemCamCapture
WebCamCapture webCam;
// Change the mainWinForm_Load function
private void mainWinForm_Load(object sender, EventArgs e)
{
webCam = new WebCamCapture();
webCam.FrameNumber = ((ulong)(0ul));
webCam.TimeToCapture_milliseconds = 30;
webCam.ImageCaptured += webcam_ImageCaptured;
}
// Add the webcam Image Captured handler to the main form
private void webcam_ImageCaptured(object source, WebcamEventArgs e)
{
Image imageCaptured = e.WebCamImage;
// You can now stop the camera if you only want 1 image
// webCam.Stop();
// Add code here to save image to disk
}
// Adjust the code in bntStart_Click
// (yes I know there is a type there, but to make code lineup I am not fixing it)
private void bntStart_Click(object sender, Event Args e)
{
webCam.Start(0);
}
Using reflector you can see that internally the WebCam class uses a timer to simulate a framerate. Therefore calling start and stop right after each other will never generate an image since the application doesnt handle application events (and therefore the timer tick event) in between starting and stopping. You should register on the ImageChanged event and call stop in there.
Good luck
** Edit: the start logic **
public void Start(ulong FrameNum)
{
try
{
this.Stop();
this.mCapHwnd = capCreateCaptureWindowA("WebCap", 0, 0, 0, this.m_Width, this.m_Height, base.Handle.ToInt32(), 0);
Application.DoEvents();
SendMessage(this.mCapHwnd, 0x40a, 0, 0);
SendMessage(this.mCapHwnd, 0x432, 0, 0);
this.m_FrameNumber = FrameNum;
this.timer1.Interval = this.m_TimeToCapture_milliseconds;
this.bStopped = false;
this.timer1.Start();
}
catch (Exception exception)
{
MessageBox.Show("An error ocurred while starting the video capture. Check that your webcamera is connected properly and turned on.\r\n\n" + exception.Message);
this.Stop();
}
}
In WebCam.cs you have:
public void InitializeWebCam(ref System.Windows.Forms.PictureBox ImageControl)
{
webcam = new WebCamCapture();
webcam.FrameNumber = ((ulong)(0ul));
webcam.TimeToCapture_milliseconds = FrameNumber;
webcam.ImageCaptured += new WebCamCapture.WebCamEventHandler(webcam_ImageCaptured);
_FrameImage = ImageControl;
}
void webcam_ImageCaptured(object source, WebcamEventArgs e)
{
_FrameImage.Image = e.WebCamImage;
}
If you modify the ImageCaptured code you can do what you want: e.WebCamImage is an Image.
for example you could change/add constructor to accept a file name and, in the ImageCaptured event, you could save image to file.
How would I go about capturing one frame from a feed of video from a webcam or video capture card in C#? I want to display the live feed and have a method that takes one frame and saves it to a remote server either via FTP or over a shared network path.
If you are able to streaming live video, then you can capture the live video stream just click on button by this code:
private Capture capture = null;
private void btnStart_Click(object sender, System.EventArgs e)
{
try
{
if ( capture == null )
throw new ApplicationException( "Please select a video and/or audio device." );
if ( !capture.Cued )
capture.Filename = txtFilename.Text;
capture.Start();
btnCue.Enabled = false;
btnStart.Enabled = false;
}
catch (Exception ex)
{
MessageBox.Show( ex.Message + "\n\n" + ex.ToString() );
}
}
You could use OpenCV. If you search on StackOverflow you'll find a lot of source on how to do that.
There's even .NET wrappers for OpenCV like opencvdotnet and Emgu CV.
You will probably end up using a few functions from the library, such as cvCaptureFromCAM() and cvQueryFrame().