См. Мой ответ здесь для справки Emgu Capture воспроизводит видео очень быстро
Но это следует делать, как вы и просили. Я использовал список для хранения изображений, вы можете использовать массив, но вам нужно будет знать, насколько велик ваш avi-файл.
Timer My_Time = new Timer();
int FPS = 30;
List<Image<Bgr,Byte>> image_array = new List<Image<Bgr,Byte>>();
Capture _capture;
public Form1()
{
InitializeComponent();
//Frame Rate
My_Timer.Interval = 1000 / FPS;
My_Timer.Tick += new EventHandler(My_Timer_Tick);
My_Timer.Start()
_capture = new Capture("test.avi");
}
private void My_Timer_Tick(object sender, EventArgs e)
{
Image<Bgr, Byte> frame = _capture.QueryFrame();
if (frame != null)
{
imageBox.Image = _capture.QueryFrame();
image_array.Add(_capture.QueryFrame().Copy());
}
else
{
My_Timer.Stop();
{
}
Это было разработано, чтобы позволить воспроизведение видеофайла с ответственной скоростью, но в качестве простого преобразования вы можете использовать метод Application.Idle так же легко, как этот ...
List<Image<Bgr,Byte>> image_array = new List<Image<Bgr,Byte>>();
Capture _capture;
public Form1()
{
InitializeComponent();
//Frame Rate
_capture = new Capture("test.avi");
Application.Idle += ProcessFrame;
}
private void ProcessFrame(object sender, EventArgs arg)
{
Image<Bgr, Byte> frame = _capture.QueryFrame();
if (frame != null)
{
image_array.Add(frame.Copy());
}
else
{
Application.Idle -= ProcessFrame;// treat as end of file
}
}
Вы должны быть осторожны с ошибкой конца файла, вы получите ошибку. Вы всегда можете использовать оператор try catch, чтобы перехватить конкретную ошибку, которую он выдаст, вместо того, чтобы просто прекратить преобразование.
Если вы используете массив изображений, вам придется перебирать файл, увеличивая переменную и считая кадры, а затем создавать массив изображений перед преобразованием видеофайла в массив.
[EDIT]
Как и требовалось, это методическая версия извлечения всех кадров из видеофайла. Я не проверял это на большом видеофайле, так как ожидаю, что программа будет аварийно завершена, поскольку она потребует много памяти.
private List<Image<Bgr, Byte>> GetVideoFrames(String Filename)
{
List<Image<Bgr,Byte>> image_array = new List<Image<Bgr,Byte>>();
Capture _capture = new Capture(Filename);
bool Reading = true;
while (Reading)
{
Image<Bgr, Byte> frame = _capture.QueryFrame();
if (frame != null)
{
image_array.Add(frame.Copy());
}
else
{
Reading = false;
}
}
return image_array;
}
В качестве альтернативы я понимаю, что вы можете записать, скажем, 10 секунд видео с веб-камеры, поэтому этот метод сделает это, я использовал секундомер, поскольку цикл while запрещает использование таймера, если вы не используете многопоточность приложения
private List<Image<Bgr, Byte>> GetVideoFrames(int Time_millisecounds)
{
List<Image<Bgr,Byte>> image_array = new List<Image<Bgr,Byte>>();
System.Diagnostics.Stopwatch SW = new System.Diagnostics.Stopwatch();
bool Reading = true;
Capture _capture = new Capture();
SW.Start();
while (Reading)
{
Image<Bgr, Byte> frame = _capture.QueryFrame();
if (frame != null)
{
image_array.Add(frame.Copy());
if (SW.ElapsedMilliseconds >= Time_millisecounds) Reading = false;
}
else
{
Reading = false;
}
}
return image_array;
}
и это будет называться так:
List<Image<Bgr, Byte>> Image_Array = GetVideoFrames(10000); //10 Secounds
Надеюсь, это поможет,
Приветствия
Chris