2015-04-06 109 views
2

背景

我在所有需要的視頻流的一些圖像處理和顯示原始視頻和處理的視頻並排側的應用程序的工作。如何處理不同的線程的視頻幀(C#)

Situtation

下面是從相機收到新幀時的事件處理程序。 pictureBox1是顯示原始視頻的地方。 GetInputImage()函數會從pictureBox1中盜取a,以便可以在該幀上執行一些圖像處理。

private void camera_NewFrame(object sender, ref Bitmap image) 
{ 
    if (!isReadingPictureBox) 
    { 
     if (pictureBox1.Image != null) 
      pictureBox1.Image.Dispose(); 
     pictureBox1.Image = (Bitmap)image.Clone(); 
    } 
} 

private void GetInputImage() 
{ 
    if (inputImage != null) 
     inputImage.Dispose(); 

    isReadingPictureBox = true; 
    if (pictureBox1.Image != null) 
     inputImage = new Bitmap(pictureBox1.Image); 
    isReadingPictureBox = false; 
} 

圖像處理很沉重,需要時間來處理單個圖像。因此輸出視頻的幀速率預計會比原始幀速率低很多。

應用程序必須顯示原始視頻而不受圖像處理的影響。所以我想在另一個線程中執行圖像處理。

private void ProcessThread(some args) 
{ 
    GetInputImage(); 
    if (inputImage != null) { 
     // Do Image Processing on "inputImage" 
     // Show result in pictureBox2 
    } 
} 

問題

[1]是抓住一個幀(上文)的方法中,OK?或者下面的那個更好?

private void camera_NewFrame(object sender, ref Bitmap image) 
{ 
    pictureBox1.Image = image; // picturBox1's image will not be read for processing 

    if(!isReadingInputImage) { 
     if (inputImage != null) 
      inputImage.Dispose(); 
     inputImage = (Bitmap)image.Clone(); // GetInputImage() is not required now. 
    } 
} 

[2]如何使ProcessMyThread(),可用在當前幀完成處理的每一刻幀 運行?這(下面)方法好嗎?

private void ProcessMyThread(some args) 
{ 
    do { 
     GetInputImage(); 
     if (inputImage != null) { 
      // Do Image Processing on inputImage; 
      // Show result in pictureBox2 
     } 
    }while(someCondition); 
} 

或者我應該爲camera_NewFrame() func中的每個幀觸發一個處理事件嗎?

+0

您可以使用'Queue'來順序處理您的圖像。只需將它們排列在ProcessThread()中,然後觸發對ProcessMyThread()的調用,這會對圖像進行排隊並逐一處理它們。如果'Queue'已經處理完畢,你可以在ProcessMyThread()中不做任何事情(你可以使用bool來跟蹤這個) – bit 2015-04-06 04:06:20

+0

感謝您的幫助,但Queue沒有幫助。 (請參閱下面的解決方案) A.在多線程中使用隊列,循環回到我開始使用的問題。 B.正如我所提到的那樣,圖像處理非常繁重,所產生的幀速率非常低(2 fps)。我不希望處理所有的幀(可能是隊列的情況)。 – kernelman 2015-04-07 13:25:19

回答

1

我使用後臺工作者自己解決了這個問題。

private void camera_NewFrame(object sender, ref Bitmap image) 
{ 
    pictureBox1.Image = image; 

    if (backgroundWorker1.IsBusy != true) 
    { 
     lock (locker) 
     { 
      if (inputImage != null) 
       inputImage.Dispose(); 
      inputImage = (Bitmap)image.Clone(); 
     } 
     backgroundWorker1.RunWorkerAsync(); 
    } 
} 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    lock (locker) 
    { 
     baseImage = (Bitmap)inputImage.Clone(); 
    } 
    // Do Image processing here on "baseImage" 
    // show result in pictureBox2 
}