Я пытаюсь написать приложение, которое может получить доступ к камерам, подключенным к ПК, записать видео и получить изображение из видео. Для доступа к камерам я использую библиотеки AForge.NET: http://www.aforgenet.com/framework/
Я не знаю, как работает событие AForge.Video.NewFrameEventHandler. В этом коде событие возвращает null в битмап вместо нового кадра из видео или событие не вызывается. Я хочу получать кадры из видео в picture box каждый таймфрейм, чтобы сделать что-то вроде видео потока и после нажатия на кнопку stop я хочу, чтобы последнее изображение оставалось отображенным в picture box. Кто-нибудь знает, как это сделать? И почему мой код не работает?
Код:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AForge.Video.DirectShow;
using System.Drawing;
using AForge.Video;
namespace CameraDevice
{
public class CameraImaging
{
// enumerate video devices
public FilterInfoCollection videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice );
//camera
public VideoCaptureDevice videoSource;
//screen shot
public Bitmap bitmap;
public CameraImaging()
{
// create video source
VideoCaptureDevice videoSource = new VideoCaptureDevice(videoDevices[0].MonikerString );
// set NewFrame event handler
videoSource.NewFrame += new NewFrameEventHandler( video_NewFrame );
}
public void StartVideo(VideoCaptureDevice videoSource)
{
// start the video source
videoSource.Start();
// ...
}
public void StopVideo(VideoCaptureDevice videoSource)
{
// stop the video source
videoSource.Stop();
// ...
}
private void video_NewFrame( object sender, NewFrameEventArgs eventArgs )
{
// get new frame
bitmap = eventArgs.Frame;
// process the frame
}
}
}
Похожий код находится здесь: http://www.aforgenet.com/framework/features/directshow_video.html[^]
В Windows Forms я запускаю это видео в потоке, который выполняет этот метод:
private void VideoRecording()
{
camImg.videoSource.Start();
while (!StopVideo)
{
pictureBox1.Image = camImg.bitmap;
pictureBox1.Invalidate();
}
camImg.videoSource.Stop();
}
Если я правильно помню, битмап нужно копировать сразу, так как он перезаписывается после события. Использование ссылки здесь не подходит. Попробуйте что-нибудь вроде:
private void video_NewFrame( object sender, NewFrameEventArgs eventArgs )
{
// copy the new frame
bitmap = new Bitmap(eventArgs.Frame);
// process the frame
}
или
private void video_NewFrame( object sender, NewFrameEventArgs eventArgs )
{
// clone new frame
bitmap = eventArgs.Frame.Clone();
// process the frame
}
Также не стоит использовать дополнительный поток для этого, AForge уже делает это.
Вызовите Start (например, в событии загрузки или после нажатия кнопки).
Обработать события кадра
private void VideoStream_NewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs) { Bitmap newFrame = new Bitmap(eventArgs.Frame); pictureBox1.Image = newFrame; }
Вызов остановки (событие закрытия или кнопка)
Если у вас возникли проблемы с элементами управления WinForm, например, с меткой, вам нужно знать, что эти элементы управления были созданы в другом потоке, и вам нужно использовать Invoke. Например:
label_ms.Invoke((MethodInvoker)(() => label_ms.Text = msTimeSpan.TotalMilliseconds.ToString()));
Лучше всего посмотреть этот пример AForge, который поставляется вместе с фреймворком: http://aforge.googlecode.com/svn/trunk/Samples/Video/Player/
Я использую библиотеку видео Aforge с моими камерами Foscams, и она работает очень хорошо. Вот мой код для обработчика события.
private void Video_NewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
{
//Create Bitmap from frame
Bitmap FrameData = new Bitmap(eventArgs.Frame);
//Add to PictureBox
PictureBox.Image = FrameData;
}
Один из способов - получить или написать обертку вокруг FFMPEG, которая может сделать за вас работу по извлечению изображений из вашего видео. Я'работал над двумя проектами, в которых использовался этот способ получения миниатюр и/или снимков из загруженных видео. Это будет немного халтурно, но должно сработать.