2011-09-30 33 views
1

我製作了一個C#應用程序,它連接到我的網絡攝像頭並以網絡攝像頭提供的速度讀取圖像。我正在解析流,以一種我每秒有幾個jpeg的方式。清理算法

我不想將所有攝像頭數據寫入磁盤,我想將圖像存儲在內存中。此外,該應用程序將作爲一個Web服務器,我可以在查詢字符串中提供日期時間。並且網絡服務器必須服務器最接近那個時間的圖像,它仍然在內存中。

在我的代碼,我有這樣的:

Dictionary<DateTime, byte[]> cameraImages; 

的日期時間是接收到的圖像的時間戳和字節組是JPEG。 所有這些工作;也處理webrequest工作。基本上我想通過根據年齡保留圖像來清理字典。

現在我需要一個算法,因爲它可以清理舊圖像。

我無法真正弄清楚它的算法,其中一個原因是日期時間並不完全在特定的時刻,我不能確定圖像總是到達。 (有時圖像流會中止幾分鐘)。但我想要做的是:

  • 保留所有圖像爲第一分鐘。
  • 前半個小時保持每秒2張圖像。
  • 如果大於30分鐘,則每秒只保留一個圖像。
  • 如果超過2小時,則每30秒只保留一張圖像。
  • 如果超過12小時,則每分鐘只保留一張圖像。
  • 如果超過24小時,每小時只保留一張圖片。
  • 如果超過兩天,則每天只保留一張圖片。
  • 刪除所有超過1周的圖像。

上述間隔只是一個例子。

有什麼建議嗎?

+0

我從我標記爲答案的答覆中得到了靈感。在每個新的傳入圖像中,我運行我的清理例程。每個隊列我已經指定了一個時間間隔,如果這個時間間隔已經到期,我從上面的最近的隊列中得到最年長的圖像,並且清理那些對於正在處理的隊列來說太舊的圖像。 – frankhommers

回答

2

我認爲@Kevin Holditch的方法非常合理,其優點是可以很容易地獲得正確的代碼。

如果有大量的圖片,或你,否則要考慮如何將這個「有效」這樣做,我建議像一個思維過程如下:

創建7個隊列,代表你的七類。我們注意按照排序的時間順序保留這個隊列中的圖像。隊列數據結構能夠在其前端有效插入並從後端移除。 .NET的隊列將是完美的。

每個隊列(稱爲Qi)具有「傳入」集合和「傳出」集合。隊列0的輸入集合是來自攝像機的圖像,對於任何其他集合,它等於隊列i-1的輸出集合。每個隊列在其輸入和輸出側都有規則,這些規則確定隊列將從其傳入的集合中接收新的項目,並且是否應該將項目從其背面彈出到其傳出集合中。作爲一個具體的例子,如果Q3是隊列「如果超過2小時,每30秒只保留一個圖像」,那麼Q3迭代它的輸入集合(這是Q2的輸出集合)並且只允許項目i,其中我的時間戳與Q3.first()相距30秒或更遠(爲了正確工作,需要從最高時間戳到最低時間戳處理這些項目)。在輸出端,我們從Q3的尾部彈出任何超過12小時的對象,這成爲Q4的輸入集。

再次,@Kevin Holditch的方法具有簡單的優點,可能是你應該做的。我只是覺得你可能會發現上述內容是值得思考的。

0

如果你使用.net 4,你可以使用一個MemoryCache用於CachItemPolicy對象的每個區間,當你希望它們過期時使它們到期,並且UpdateCallbacks將一些區間移動到下一個區間。

0

你可以很容易地做到這一點(雖然它可能不是使用Linq最有效的方法)。

例如

var firstMinImages = cameraImages.Where(
    c => c.Key >= DateTime.Now.AddMinutes(-1)); 

然後對每個時間間隔進行等效查詢。將它們組合成一個圖像存儲區並覆蓋現有商店(假定您不想保留它們)。這將符合您目前的標準,因爲隨着時間的推移,所需的圖像逐漸減少。

+0

我建議把DateTime.Now放在一個臨時變量中,並從LINQ查詢中引用該變量。這將防止查詢之間的時鐘偏斜。 –

0

我的策略是將元素分組爲桶,你打算剔除,然後從列表中選擇1元素以保持...我已經做了一個例子,如何使用DateTimes和Ints列表但Pics將以完全相同的方式工作。

我的課時用於存儲各事先知情同意

class Pic 
    { 
     public DateTime when {get;set;} 
     public int val {get;set;} 
    } 

,並在列表中的幾個項目的範例......

 List<Pic> intTime = new List<Pic>(); 
     intTime.Add(new Pic() { when = DateTime.Now, val = 0 }); 
     intTime.Add(new Pic() { when = DateTime.Now.AddDays(-1), val = 1 }); 
     intTime.Add(new Pic() { when = DateTime.Now.AddDays(-1.01), val = 2 }); 
     intTime.Add(new Pic() { when = DateTime.Now.AddDays(-1.02), val = 3 }); 
     intTime.Add(new Pic() { when = DateTime.Now.AddDays(-2), val = 4 }); 
     intTime.Add(new Pic() { when = DateTime.Now.AddDays(-2.1), val = 5 }); 
     intTime.Add(new Pic() { when = DateTime.Now.AddDays(-2.2), val = 6 }); 
     intTime.Add(new Pic() { when = DateTime.Now.AddDays(-3), val = 7 }); 

現在我創建一個輔助函數來桶和刪除..

private static void KeepOnlyOneFor(List<Pic> intTime, Func<Pic, int> Grouping, DateTime ApplyBefore) 
    { 
     var groups = intTime.Where(a => a.when < ApplyBefore).OrderBy(a=>a.when).GroupBy(Grouping); 
     foreach (var r in groups) 
     { 
      var s = r.Where(a=> a != r.LastOrDefault()); 
      intTime.RemoveAll(a => s.Contains(a)); 
     } 
    } 

這樣做可以讓您指定如何對對象進行分組並設置分組的年齡閾值。現在終於用...

這將刪除所有,但每天1張圖片爲大於2天的任何圖片:後1日齡

 KeepOnlyOneFor(intTime, a => a.when.Day, DateTime.Now.AddDays(-2)); 

這將刪除所有,但1個畫面的每個小時: