Record video with Accord.net (AForge) - c#

I used Accord.net (AForge) for connect to the webcam and record video
But stored videos is slow motion ...
this my project :
using AForge.Video;
using AForge.Video.DirectShow;
using AForge.Video.FFMPEG;
using System;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
namespace CaptureWebcam
{
public partial class Form1 : Form
{
private VideoCaptureDeviceForm captureDevice;
private string path = Path.GetDirectoryName(Application.ExecutablePath) + #"\Videos\";
private FilterInfoCollection videoDevice;
private VideoCaptureDevice videoSource;
private VideoFileWriter FileWriter = new VideoFileWriter();
private Bitmap video;
bool isRecord = false;
public Form1()
{
InitializeComponent();
}
private void videoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
video = (Bitmap)eventArgs.Frame.Clone();
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
}
private void btnStartCam_Click(object sender, EventArgs e)
{
videoDevice = new FilterInfoCollection(FilterCategory.VideoInputDevice);
captureDevice = new VideoCaptureDeviceForm();
if (captureDevice.ShowDialog(this) == DialogResult.OK)
{
videoSource = captureDevice.VideoDevice;
videoSource = captureDevice.VideoDevice;
videoSource.NewFrame += new NewFrameEventHandler(videoSource_NewFrame);
videoSource.Start();
timer1.Enabled = true;
}
//videoSource.DisplayPropertyPage(IntPtr.Zero);
}
private Thread workerThread = null;
private bool stopProcess = false;
private void recordLiveCam()
{
if (!stopProcess)
{
while (isRecord)
{
FileWriter.WriteVideoFrame(video);
}
FileWriter.Close();
}
else
{
workerThread.Abort();
}
}
private void btnRecord_Click(object sender, EventArgs e)
{
//try
//{
isRecord = true;
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
int h = captureDevice.VideoDevice.VideoResolution.FrameSize.Height;
int w = captureDevice.VideoDevice.VideoResolution.FrameSize.Width;
FileWriter.Open(path + "recorded at " + DateTime.Now.ToString("HH-mm-ss") + ".mp4", w, h, 25, VideoCodec.MPEG4);
stopProcess = false;
workerThread = new Thread(new ThreadStart(recordLiveCam));
workerThread.Start();
//}
//catch (Exception ex)
//{
// MessageBox.Show(ex.Message);
//}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void btnStopRecord_Click(object sender, EventArgs e)
{
stopProcess = true;
isRecord = false;
FileWriter.Close();
workerThread.Abort();
video = null;
}
private void btnStopCam_Click(object sender, EventArgs e)
{
try
{
if (videoSource.IsRunning)
{
videoSource.SignalToStop();
videoSource.Stop();
pictureBox1.Image = null;
pictureBox1.Invalidate();
if (FileWriter.IsOpen)
{
FileWriter.Close();
video = null;
}
}
else
return;
}
catch
{
videoSource.Stop();
FileWriter.Close();
video = null;
}
}
float fts = 0.0f;
private void timer1_Tick(object sender, EventArgs e)
{
fts = videoSource.FramesReceived;
label1.Text = "Frame Rate : " + fts.ToString("F2") + " fps";
}
}
}
And when click the btnStopRecord following error :
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

"Slow motion" can have multiple reasons. First you need to know if the actual framerate, at which the NewFrames get produces is so slow (how many HZ then?) or if the CPU is too busy. Or the graphics card maybe.
For everything DirectShow related I strongly suggest using GraphEdit and AMCap to see what the real capabilites of the device are. AForge was prone to oversampling and I would not wonder if it's similar in Accord.
Also, you can always rely on good old processexplorer to see if the load (if any) is caused by SYSTEM or INTERRUPRS or is actually produced by your executable.
Another thing that happened to me was PictureBox. VideoSourcePlayer is far better and I wound up doing my own blitting.
It is worth mentioning these three optimizations:
DO NOT USE Bitmap.GetPixel!
Use videoSource.DisplayPinPropertyPage(IntPtr.Zero)
Check the color space of the videostream
Bitmap.GetPixel
The problem with GetPixel is, that it's really slow as it has to unmanage/manage a lot for every single pixel. It is fine as along as you only get a small a mount of calls and use it on a loaded bitmap. It is definately the wrong approach if you want to use it on all pixelx every couple of milliseconds. The CPU load from this phenomenon is associated with your application and will show as such in process explorer.
In the end I wrote my own pixel routines starting here: Work with bitmap faster with Csharp
If you just want a kernel or something more usual than I needed, implement a
custom Filter.
VideoSource.DisplayPinPropertyPage
If you use the AForge-buit-in mechanism for choosing the resolution and initiating the video stream, you cannot set the Framerate (I do not consider this a bug in AForge). So AForge always chooses the highest framerate. If you circumvent videoSource.VideoCapabilities and directly show the native device configuration dialog (it's formally called "Video Capture Pin Properties Dialog"). There you can set all the parameters manually and the dialog will fill in the appropriate framerate. This way, you will get the "real" (hardware) refresh rate in your callbacks. The CPU load of this oversampling happens in the SYSTEM process.
Color space conversion
In my case, the camera supports three output formats: YUY2, MJPG and RGB24. Depending on what format you use, the image is transformed by AForge into RGB (I think actually it's ARGB32). The rendered DirectShow graphs for all three formats are different and RGB obviously uses much less CPU than the others, as the color conversion is quite trivial. The load from this conversion also shows up in the SYSTEM process and not in your applications exe.

You can try to put some timers to understand which operation is slowing down the process.(Stopwatch class will be perfect)
I don't know the format of your Frame but usually the conversion to Bitmap is the bottle neck, AForge is quite fast. Furthermore you can pass a time stamp to WriteVideoFrame method, then the frame rate indicated in Open is just for replaying the video. Aforge will ordinate the frames in the right order with the right time.
That's according to my experience. Hope it can help.

Try this
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using AForge;
using AForge.Video.DirectShow;
using Accord.Video.FFMPEG;
using System.IO;
using AForge.Video;
using System.Threading;
namespace New_Project_2
{
public partial class Form1 : Form
{
private VideoCaptureDeviceForm captureDevice;
private FilterInfoCollection videoDevice;
private VideoCaptureDevice videoSource;
private VideoFileWriter FileWriter = new VideoFileWriter();
bool isRecord = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void videoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
try
{
if (isRecord == true)
{
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
FileWriter.WriteVideoFrame((Bitmap)eventArgs.Frame.Clone());
}
}
catch (Exception)
{
throw;
}
}
private void button1_Click(object sender, EventArgs e)
{
videoDevice = new FilterInfoCollection(FilterCategory.VideoInputDevice);
captureDevice = new VideoCaptureDeviceForm();
if (captureDevice.ShowDialog(this) == DialogResult.OK)
{
isRecord = true;
int h = captureDevice.VideoDevice.VideoResolution.FrameSize.Height;
int w = captureDevice.VideoDevice.VideoResolution.FrameSize.Width;
FileWriter.Open("d:\\" + "recorded at " + DateTime.Now.ToString("HH-mm-ss") + ".mp4", w, h, 25, VideoCodec.MPEG4);
videoSource = captureDevice.VideoDevice;
videoSource.NewFrame += new NewFrameEventHandler(videoSource_NewFrame);
videoSource.Start();
}
//videoSource.DisplayPropertyPage(IntPtr.Zero)
}
private void button2_Click(object sender, EventArgs e)
{
}
private void button3_Click(object sender, EventArgs e)
{
isRecord = false;
FileWriter.Close();
}
private void button4_Click(object sender, EventArgs e)
{
}
}
}

You can use emguCV to record videos.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu;
using Emgu.CV;
using Emgu.CV.Structure;
namespace Load_Images
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
double TotalFrame;
double Fps;
int captureFrameNo;
VideoCapture capture;
VideoWriter writer;
bool isCapturing = false;
private void button1_Click(object sender, EventArgs e)
{
if (isCapturing == false)
{
capture = new VideoCapture(0);
TotalFrame = capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameCount);
Fps = capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps);
isCapturing = true;
int fourcc = fourcc = VideoWriter.Fourcc('H', '2', '6', '4');
capture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth, 2048);
capture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight, 1024);
//int fourcc = Convert.ToInt32(capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FourCC));
int width = Convert.ToInt32(capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth));
int height = Convert.ToInt32(capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight));
string destin_path = "D:\\out.mp4";
writer = new VideoWriter(destin_path, fourcc, Fps, new Size(width, height), true);
capture.ImageGrabbed += Capture_ImageGrabbed;
capture.Start();
}
}
private void Capture_ImageGrabbed(object sender, EventArgs e)
{
try
{
if (isCapturing == true)
{
if (capture == null)
{
return;
}
Mat m = new Mat();
capture.Retrieve(m);
writer.Write(m);
pictureBox1.Image = m.ToImage<Bgr, byte>().Bitmap;
}
}
catch (Exception)
{
throw;
}
}
private void button2_Click(object sender, EventArgs e)
{
if (isCapturing == true) {
capture.Stop();
isCapturing = false;
}
}
private void button3_Click(object sender, EventArgs e)
{
if (capture != null) {
capture.Pause();
}
}
private void button4_Click(object sender, EventArgs e)
{
if (writer.IsOpened)
{
isCapturing = false;
writer.Dispose();
}
MessageBox.Show("Completed");
}
private void Form2_Load(object sender, EventArgs e)
{
}
}
}

if you write file on newFrame handler Func will cause fastplaqy/slow record on some codec VP8-VP9 etc. (mpeg4 not effect) but if you start different timer on some time to write you solve your issues

Related

AForge experience and file manipulation

Morning all,
Does anyone on here have experience with using AForge and Video or webcam apps?
There is a .cs file called VideoCaptureDeviceForm that is part of AForge.DirectShow which provides a way of selecting a local video device i.e webcam.
I want to be able to automatically detect and start the webcam on my computer but a dialogbox pops up asking to select a webcam. I need a way to either bypass this in someway or automatically press the OK button.
Dialogbox
I have tried using SendKeys.Send("{ENTER}") within the open dialogbox button method i.e Start camera but I get errors.
Within VideoCaptureDeviceForm.cs, there is a method called okButton_Click and the next idea is to manipulate this to do what I want the app to do.
Unfortunately I don't have the experience to figure this out. Can anyone advise on how to do this or what I should do next? Thank you.
VideoCaptureDeviceForm.cs is below:
using System;
using System.Threading;
using System.Windows.Input;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AForge.Video;
using AForge.Video.DirectShow;
using Accord.Video.FFMPEG;
using AForge.Video.VFW;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
private FilterInfoCollection VideoCaptureDevices;
private VideoCaptureDevice FinalVideo = null;
private VideoCaptureDeviceForm captureDevice;
private Bitmap video;
private VideoFileWriter FileWriter = new VideoFileWriter();
private SaveFileDialog saveAvi;
public Form1()
{
InitializeComponent();
Start_Vid();
}
private void Form1_Load(object sender, EventArgs e)
{
VideoCaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
captureDevice = new VideoCaptureDeviceForm();
}
void FinalVideo_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
if (Stop.Text == "Stop Record")
{
video = (Bitmap)eventArgs.Frame.Clone();
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
//AVIwriter.Quality = 0;
FileWriter.WriteVideoFrame(video);
//AVIwriter.AddFrame(video);
}
else
{
video = (Bitmap)eventArgs.Frame.Clone();
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
}
}
private void Stop_Vid()
{
if (Stop.Text == "Stop Record")
{
Stop.Text = "Stop";
if (FinalVideo == null)
{ return; }
if (FinalVideo.IsRunning)
{
//this.FinalVideo.Stop();
FileWriter.Close();
//this.AVIwriter.Close();
pictureBox1.Image = null;
}
}
else
{
this.FinalVideo.Stop();
FileWriter.Close();
//this.AVIwriter.Close();
pictureBox1.Image = null;
}
}
private void butstop_Click(object sender, EventArgs e)
{
if (Stop.Text == "Stop Record")
{
Stop.Text = "Stop";
if (FinalVideo == null)
{ return; }
if (FinalVideo.IsRunning)
{
//this.FinalVideo.Stop();
FileWriter.Close();
//this.AVIwriter.Close();
pictureBox1.Image = null;
}
}
else
{
this.FinalVideo.Stop();
FileWriter.Close();
//this.AVIwriter.Close();
pictureBox1.Image = null;
}
}
private void button3_Click(object sender, EventArgs e)
{
pictureBox1.Image.Save("IMG" + DateTime.Now.ToString("hhmmss") + ".jpg");
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (FinalVideo == null)
{ return; }
if (FinalVideo.IsRunning)
{
this.FinalVideo.Stop();
FileWriter.Close();
//this.AVIwriter.Close();
}
}
private void Save_Click(object sender, EventArgs e)
{
saveAvi = new SaveFileDialog();
saveAvi.Filter = "Avi Files (*.avi)|*.avi";
saveAvi.FileName = "New Vid1";
if (saveAvi.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
int h = captureDevice.VideoDevice.VideoResolution.FrameSize.Height;
int w = captureDevice.VideoDevice.VideoResolution.FrameSize.Width;
FileWriter.Open(saveAvi.FileName, w, h, 25, VideoCodec.Default, 5000000);
FileWriter.WriteVideoFrame(video);
//AVIwriter.Open(saveAvi.FileName, w, h);
Stop.Text = "Stop Record";
//FinalVideo = captureDevice.VideoDevice;
//FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
//FinalVideo.Start();
}
}
//##############################################//
// Method not working //
//##############################################//
private void Start_Vid()
{
SendKeys.Send("{ENTER}");
if (captureDevice.ShowDialog(this) == DialogResult.OK)
{
VideoCaptureDevice videoSource = captureDevice.VideoDevice;
FinalVideo = captureDevice.VideoDevice;
FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
FinalVideo.Start();
}
}
//##############################################//
// Method working //
//##############################################//
private void Start_Click(object sender, EventArgs e)
{
SendKeys.Send("{ENTER}");
if (captureDevice.ShowDialog(this) == DialogResult.OK)
{
VideoCaptureDevice videoSource = captureDevice.VideoDevice;
FinalVideo = captureDevice.VideoDevice;
FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
FinalVideo.Start();
}
}
private void Close_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
1) First, you need to find all webcam device is attached with you system
public FilterInfoCollection LoaclWebCamsCollection = new FilterInfoCollection(FilterCategory.VideoInputDevice);
2) Then which webcam you want to use select "MonikerString" of that webcam
VideoCaptureDevice videoSource = new VideoCaptureDevice(LoaclWebCamsCollection["Select webcam you want to user"].MonikerString);
OR
VideoCaptureDevice videoSource = new VideoCaptureDevice(LoaclWebCamsCollection[0].MonikerString);
private void Start_Vid()
{
FinalVideo = new
VideoCaptureDevice(LoaclWebCamsCollection[0].MonikerString);
FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
FinalVideo.Start();
}

How to detect canny edge and integral projection on a real time webcam using c# aforge?

"I have been trying to detect canny edge on an image and it has been successful, but I don't know how to detect its edge if I want it real time, here is my code, it has no error but the canny window can't be processed
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
//using KomCit;
using System.Drawing.Imaging;
using System.IO;
using System.Timers;
using AForge;
using AForge.Imaging.Filters;
using AForge.Video.DirectShow;
using System.Threading;
namespace canny_video
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private FilterInfoCollection CaptureDevice;
private VideoCaptureDevice FinalFrame;
void FinalFrame_NewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
{
CameraBox.Image = (Bitmap)eventArgs.Frame.Clone();
}
private static Image resizeImage(Image imgToResize, Size size)
{
return (Image)(new Bitmap(imgToResize, size));
}
private void Form1_Load(object sender, EventArgs e)
{
//timer1.Enabled = true;
CaptureDevice = new FilterInfoCollection(FilterCategory.VideoInputDevice);
foreach (FilterInfo Device in CaptureDevice)
{
listDevice.Items.Add(Device.Name);
}
listDevice.SelectedIndex = 0;
FinalFrame = new VideoCaptureDevice();
}
private void start_Click(object sender, EventArgs e)
{
FinalFrame = new VideoCaptureDevice(CaptureDevice[listDevice.SelectedIndex].MonikerString);
FinalFrame.NewFrame += new AForge.Video.NewFrameEventHandler(FinalFrame_NewFrame);
FinalFrame.Start();
//CannyBox.Image = (Bitmap)CameraBox.Image.Clone(); //capture image bitmap
//Bitmap gambar = new Bitmap(CameraBox.Image);
Bitmap gambar = new Bitmap(CameraBox.Image);
Grayscale gray = new Grayscale(0.2125, 0.7154, 0.0721);
CannyEdgeDetector cany = new CannyEdgeDetector(0, 70);
Bitmap hasil = cany.Apply(gray.Apply(gambar));
// BlobsFiltering blob = new BlobsFiltering(0, 0, 20, 20);
//Bitmap hasil = blob.Apply(gray.Apply(gambar));
//CannyBox.Width = gambar.Width;
//CannyBox.Height = gambar.Height;
CannyBox.Image = hasil;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (FinalFrame.IsRunning == true)
{
FinalFrame.Stop();
}
}
}
}
"
My problem above is solved, thank you :)
but I have another problem on integral projection, I didn't know how to do it though.
please help, thank you in advance
Some comments:
Your two private variables are very confusingly named. Your CaptureDevice is a collection of all the capture devices on the computer, while your FinalFrame is a capture device.
You do not look for canny edges on the bitmap upon reception.
The NewFrame event handler runs in the streaming thread, so you should use a .BeginInvoke in there to make it usable by the UI thread.
What you may do:
Inside _NewFrame handler, use BeginInvoke to transfer the cloned image to a ProcessCameraImage method (that will hence run on the UI thread).
Apply canny edge detection within this method.
Then assign the result to your picture box.
Note: I don't know how CPU heavy canny edge detection is. If it's costly, doing it on the UI thread may block user interaction. In that case you could do it within the streaming thread and only transfer the processed image for display. But depending on the time it takes, this may force the camera to lower its framerate.
thank you for your answer, it has been solved just now, I've modified it and it somehow solved
here is the code :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using AForge;
using AForge.Imaging;
using AForge.Imaging.Filters;
using AForge.Video;
using AForge.Video.DirectShow;
using System.Drawing.Imaging; //Save P2
using System.IO; //Save P2
namespace AForgeCamera
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Bitmap video;
private FilterInfoCollection CaptureDevice;
private VideoCaptureDevice FinalFrame;
int mode;
private void Form1_Load(object sender, EventArgs e)
{
CaptureDevice = new FilterInfoCollection(FilterCategory.VideoInputDevice);
foreach (FilterInfo Device in CaptureDevice)
{
comboBox1.Items.Add(Device.Name);
}
comboBox1.SelectedIndex = 0;
FinalFrame = new VideoCaptureDevice();
}
private void button1_Click(object sender, EventArgs e) //Tombol Start
{
FinalFrame = new VideoCaptureDevice(CaptureDevice[comboBox1.SelectedIndex].MonikerString);
FinalFrame.NewFrame += new NewFrameEventHandler(FinalFrame_NewFrame);
FinalFrame.Start();
}
void FinalFrame_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
video = (Bitmap)eventArgs.Frame.Clone();
Bitmap video2 = (Bitmap)eventArgs.Frame.Clone();
if (mode==1)
{
Grayscale gray = new Grayscale(0.2125, 0.7154, 0.0721);
Bitmap video3 = gray.Apply(video2);
CannyEdgeDetector canny = new CannyEdgeDetector(0, 70);
canny.ApplyInPlace(video3);
pictureBox2.Image = video3;
}
pictureBox1.Image = video;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (FinalFrame.IsRunning == true)
{
FinalFrame.Stop();
}
}
private void btnTrackingObject_Click(object sender, EventArgs e)
{
mode = 1;
}
}
}
but now I am working on the next problem, I try to detect the location of the object using integral projection, is it possible to use aforge to do it?

AForge Convertation and problems with HD

First of all, I can't play and record HD video(1920x1080), when I change my camera resolution to 1920x1080 program show and record black background, if camera resolution is 720x576 it works without problems. I'm sure that the problem is in my solution because, when I use DesktopVideo(Software which is included with Blackmagic Decklink Studio 2) it shows HD video from camera.
Second, How do I convert video with AForge? like changing resolution and framerate, I can change codecs and bitrate, but when I change Resolution and FrameRate in "FileWriter.Open"
command I get Error Resolution and FrameRate must be the same as Bitmap I'm capturing from camera.
If anybody knows how to solve these problems please share information, thanks!
Here is the code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AForge.Video;
using AForge.Video.DirectShow;
using AForge.Video.FFMPEG;
using AForge.Video.VFW;
namespace WindowsFormsApplication12
{
public partial class Form1 : Form
{
private FilterInfoCollection VideoCaptureDevices;
private VideoCaptureDevice FinalVideo = null;
private VideoCaptureDeviceForm captureDevice;
private Bitmap video;
//private AVIWriter AVIwriter = new AVIWriter();
private VideoFileWriter FileWriter = new VideoFileWriter();
private SaveFileDialog saveAvi;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
VideoCaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
captureDevice = new VideoCaptureDeviceForm();
}
private void button1_Click(object sender, EventArgs e)
{
/////capture device list
if (captureDevice.ShowDialog(this) == DialogResult.OK)
{
VideoCaptureDevice videoSource = captureDevice.VideoDevice;
FinalVideo = captureDevice.VideoDevice;
FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
FinalVideo.Start();
}
}
void FinalVideo_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
if (butStop.Text == "Stop Record")
{
video = (Bitmap)eventArgs.Frame.Clone();
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
//AVIwriter.Quality = 0;
FileWriter.WriteVideoFrame(video);
//AVIwriter.AddFrame(video);
}
else
{
video = (Bitmap)eventArgs.Frame.Clone();
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
}
}
private void button2_Click(object sender, EventArgs e)
{
////record button
saveAvi = new SaveFileDialog();
saveAvi.Filter = "Avi Files (*.avi)|*.avi";
if (saveAvi.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
int h = captureDevice.VideoDevice.VideoResolution.FrameSize.Height;
int w = captureDevice.VideoDevice.VideoResolution.FrameSize.Width;
FileWriter.Open(saveAvi.FileName, w, h,25,VideoCodec.Default,5000000);
FileWriter.WriteVideoFrame(video);
//AVIwriter.Open(saveAvi.FileName, w, h);
butStop.Text = "Stop Record";
//FinalVideo = captureDevice.VideoDevice;
//FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
//FinalVideo.Start();
}
}
private void butStop_Click(object sender, EventArgs e)
{
if (butStop.Text == "Stop Record")
{
butStop.Text = "Stop";
if (FinalVideo == null)
{ return; }
if (FinalVideo.IsRunning)
{
//this.FinalVideo.Stop();
FileWriter.Close();
//this.AVIwriter.Close();
pictureBox1.Image = null;
}
}
else
{
this.FinalVideo.Stop();
FileWriter.Close();
//this.AVIwriter.Close();
pictureBox1.Image = null;
}
}
private void button3_Click(object sender, EventArgs e)
{
pictureBox1.Image.Save("IMG" + DateTime.Now.ToString("hhmmss") + ".jpg");
}
private void button4_Click(object sender, EventArgs e)
{
this.Close();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (FinalVideo == null)
{ return; }
if (FinalVideo.IsRunning)
{
this.FinalVideo.Stop();
FileWriter.Close();
//this.AVIwriter.Close();
}
}
}
}
The provided code simply captures and saves in the format currently active/selected for the capture device. In general, resolution change is an "expensive" operation is not available as a complimentary operation.
You want to change resolution right on capture device by switching it to more appropriate format, then capture in this resolution and have all further data manipulation in correct resolution. Available resolutions and options might be hardware specific there.
If/when no suitable capture resolution option is available, you typically resample the video to new resolution. Even though Windows API has suitable functionality, in your particular case you are interested to have this integrated with AForge library and you need to check its documentation to find out whether it provides a respective wrapper and whether it can be integrated into capture process overall (or, you need to write this code yourself to handle scaling).

Saving images using Aforge

i wrote a code for accessing webcam and on clicking, saving the picture to a folder.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AForge.Imaging;
using AForge.Imaging.Filters;
using AForge.Video;
using AForge.Video.DirectShow;
namespace cam
{
public partial class Form1 : Form
{
public static Bitmap _latestFrame;
public Form1()
{
InitializeComponent();
}
private FilterInfoCollection webcam;
private VideoCaptureDevice cam;
Bitmap bitmap;
private void Form1_Load(object sender, EventArgs e)
{
webcam = new FilterInfoCollection(FilterCategory.VideoInputDevice);
foreach (FilterInfo VideoCaptureDevice in webcam)
{
comboBox1.Items.Add(VideoCaptureDevice.Name);
}
comboBox1.SelectedIndex = 0;
}
private void button1_Click(object sender, EventArgs e)
{
cam = new VideoCaptureDevice(webcam[comboBox1.SelectedIndex].MonikerString);
cam.NewFrame += new NewFrameEventHandler(cam_NewFrame);
cam.Start();
}
void cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
bitmap = (Bitmap)eventArgs.Frame.Clone();
pictureBox1.Image = bitmap;
}
private void pictureBox1_Click(object sender, EventArgs e)
{
pictureBox1.Image = bitmap;
}
private void button3_Click(object sender, EventArgs e)
{
if (cam.IsRunning)
{
cam.Stop();
}
}
private void button2_Click(object sender, EventArgs e)
{
Bitmap current = (Bitmap)_latestFrame.Clone();
string ActiveDir = AppDomain.CurrentDomain.BaseDirectory;
string filepath = System.IO.Path.Combine(ActiveDir, #"D://picture/");
if (!System.IO.Directory.Exists(filepath))
{
System.IO.DirectoryInfo OutputDir = System.IO.Directory.CreateDirectory(filepath);
string fileName = System.IO.Path.Combine(filepath, #"name.bmp");
if (!System.IO.File.Exists(fileName))
{
current.Save(fileName);
}
}
current.Dispose();
}
}
}
In the button2 I have written the code for saving the picture, on building the program, an null reference exception is shown for the given line(Bitmap current = (Bitmap)_latestFrame.Clone();)
As far as I can see in your code, the new image frame is copied to your member variable bitmap. The static member _latestFrame never seem to be assigned.
Therefore, in your button2_Click method, change the first line to:
Bitmap current = (Bitmap)bitmap.Clone();
Now, provided you have received at least one frame from the webcam when you click the button, the frame should be properly saved.
I also think you are overworking the filepath setting in the button2_Click method. To begin with, simply verify that the picture can be properly saved to the active directory by changing your button2_Click method to this:
private void button2_Click(object sender, EventArgs e)
{
Bitmap current = (Bitmap)bitmap.Clone();
string filepath = Environment.CurrentDirectory;
string fileName = System.IO.Path.Combine(filepath, #"name.bmp");
current.Save(fileName);
current.Dispose();
}
This will ensure that a new image will be written to the "current directory" every time you click on the Capture button.
I have tested your code with the above changes, and it works flawlessly.

playing video file using form application in c# with DirectX and not with Windows media player

i want to play video in c#. i searched related tutorial and i found this. i followed exactly the same but the video would not appear.
here is my code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX.AudioVideoPlayback;
namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{
Video video;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
// store the original size of the panel
int width = panel1.Width;
int height = panel1.Height;
// load the selected video file
//video = new Video("C:\\Users\\HDAdmin\\Desktop\\Example.avi");
video = new Video(openFileDialog1.FileName);
// set the panel as the video object’s owner
video.Owner = panel1;
// stop the video
video.Stop();
// resize the video to the size original size of the panel
panel1.Size = new Size(width, height);
try
{
video.Audio.Volume = 100;
}
catch { }
}
}
private void button2_Click(object sender, EventArgs e)
{
if (video.State != StateFlags.Running)
{
video.Play();
}
}
private void button3_Click(object sender, EventArgs e)
{
if (video.State == StateFlags.Running)
{
video.Pause();
}
}
private void button4_Click(object sender, EventArgs e)
{
if (video.State != StateFlags.Stopped)
{
video.Stop();
}
}
}
}
i even tried to put a path of the video like this:
video = new Video("C:\\Users\\HDAdmin\\Desktop\\Example.avi");
but both of it will show the error like picture below.
my question is, how i want to enable to view and play the video by using windows form application in c#?
p/s: i want to use Directx only and do not want to play the video in windows media player.

Categories