用Accord.net录制视频(AForge) [英] Record video with Accord.net (AForge)

查看:4364
本文介绍了用Accord.net录制视频(AForge)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Accord.net(AForge)连接网络摄像头并录制视频
但存储的视频是慢动作...
这个我的项目:

 使用AForge.Video; 
使用AForge.Video.DirectShow;
使用AForge.Video.FFMPEG;
使用系统;
使用System.Drawing;
使用System.IO;
使用System.Threading;
使用System.Windows.Forms;

命名空间CaptureWebcam
{
public partial class Form1:Form
{
private VideoCaptureDeviceForm captureDevice;
private string path = Path.GetDirectoryName(Application.ExecutablePath)+ @\Videos\;
private FilterInfoCollection videoDevice;
私人VideoCaptureDevice videoSource; VideoFileWriter
私人位图视频;
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(视频);
}
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(路径+记录在+ 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;
}
}
}

当点击btnStopRecord以下错误:


附加信息:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。



解决方案

慢动作可以多重原因首先,您需要知道NewFrames获取的实际帧速率是否如此慢(多少HZ?)或者CPU是否太忙。或者图形卡可能。



对于所有DirectShow相关的,我强烈建议使用GraphEdit和AMCap来查看设备的实际功能。 AForge很容易进行过采样,我不会想知道在Accord中是否相似。



此外,您可以随时依靠旧的processexplorer来查看是否加载(如果有)是由SYSTEM或INTERRUPRS引起的,实际上是由您的可执行文件生成的。



另一件事发生在我的是PictureBox。 VideoSourcePlayer的效果要好得多,而且我自己做了一些事情。



值得一提的是这三个优化:




  • 不要使用 Bitmap.GetPixel

  • 使用 videoSource.DisplayPinPropertyPage IntPtr.Zero)

  • 检查视频流的颜色空间



< h2> Bitmap.GetPixel

GetPixel的问题是,它真的很慢,因为它必须对每个像素进行非管理/管理。只要你只收到一个小的调用,并在加载的位图上使用它就可以了。如果要在每两毫秒的像素上使用它,这一定是错误的方法。这种现象的CPU负载与您的应用程序相关联,并将在过程浏览器中显示。
最后我写了我自己的像素例程,从这里开始:使用Csharp更快地使用位图
如果您只想要一个内核或比我需要的更常用的东西,请执行
自定义过滤器



VideoSource.DisplayPinPropertyPage



如果您使用AForge-buit-in机制选择分辨率并启动视频流,则无法设置Framerate(我不认为这个a但在AForge)。所以AForge总是选择最高的帧率。如果您规避videoSource.VideoCapabilities并直接显示本地设备配置对话框(正式称为视频捕获引脚属性对话框)。您可以手动设置所有参数,并且对话框将填入适当的帧速率。这样,您将在您的回调中获得真实(硬件)刷新率。这种过采样的CPU负载发生在SYSTEM进程中。



颜色空间转换



在我的情况下,相机支持三种输出格式:YUY2,MJPG和RGB24。根据您使用的格式,图像由AForge转换为RGB(我认为其实是ARGB32)。所有三种格式的渲染DirectShow图都不同,RGB显然使用比其他格式少得多的CPU,因为颜色转换很简单。来自此转换的负载也显示在SYSTEM rpocess中,而不是在您的应用程序中。


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 but 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 rpocess and not in you applications exe.

这篇关于用Accord.net录制视频(AForge)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆