簡體   English   中英

Emgu CV從視頻文件中獲取所有幀

[英]Emgu CV get all frames from video file

我想請你幫我用Emgu CV從視頻文件中獲取所有幀。 我知道我可以使用Capture類及其QueryFrame()方法,但這只返回一幀。 獲得所有幀的最簡單方法是什么? (並將其保存為例如Image<Bgr, Byte>[] )我需要所有幀進行更多處理(更具體地說:視頻摘要的關鍵幀提取)。

非常感謝你的幫助。

請參閱我的答案以供參考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語句來捕獲它將提供的特定錯誤,而不是簡單地終止轉換。

如果您使用圖像陣列,則必須循環文件遞增變量並計算幀,然后在將視頻文件轉換為數組之前創建圖像陣列。


[編輯]

根據要求,這是從視頻文件中檢索所有幀的方法版本我沒有在大型視頻文件上測試過這個,因為我預計程序會崩潰,因為它需要大量內存。

    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

希望這可以幫助,

干杯,

克里斯

即使我面臨同樣的問題。所以我初始化了另一個計時器,並在那里提供了視頻保存代碼。只有當點擊記錄按鈕[點擊記錄視頻的表格上的按鈕]時才啟用此計時器。現在我可以捕獲視頻但音頻未被錄制。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM