清理算法

时间:2011-09-30 21:50:11

标签: c#

我制作了一个连接到我的网络摄像头的C#应用​​程序,并以网络摄像头提供的速度读取图像。我正在解析流,我每秒都有几个jpeg。

我不想将所有网络摄像头数据写入磁盘,我想将图像存储在内存中。此外,该应用程序将充当网络服务器,我可以在查询字符串中提供日期时间。并且网络服务器必须将最接近该时间的图像提供给内存。

在我的代码中我有这个:

Dictionary<DateTime, byte[]> cameraImages;

其中DateTime是接收图像的时间戳,而bytearray是jpeg。 所有这些都有效;还处理webrequest工作。基本上我想通过根据年龄保持图像来清理字典。

现在我需要一个算法,因为它可以清理旧的图像。

我无法为它找出算法,其中一个原因是日期时间并非完全在特定时刻,我无法确定图像是否总是到达。 (有时图像流中止几分钟)。但我想做的是:

  • 第一分钟保留所有图像。
  • 前半个小时每秒保留2张图像。
  • 如果超过30分钟,则每秒只保留一张图片。
  • 如果超过2小时,则每30秒只保留一张图片。
  • 如果超过12小时,则每分钟只保留一张图片。
  • 如果超过24小时,则每小时只保留一张图片。
  • 如果超过两天,则每天只保留一张图片。
  • 删除超过1周的所有图片。

以上间隔只是一个例子。

有什么建议吗?

4 个答案:

答案 0 :(得分:2)

我认为@Kevin Holditch的方法非常合理,并且具有很容易获得正确代码的优势。

如果有大量图片,或者您想要“高效”地考虑如何做到这一点,我会提出如下的思考过程:

创建7个队列,代表您的七个类别。我们注意按照排序的时间顺序将图像保留在此队列中。队列数据结构能够有效地插入其前部并从其后部移除。 .NET的队列将是完美的。

每个队列(称之为Qi)都有一个“传入”集和一个“传出”集。队列0的传入集是来自摄像机的图像,对于任何其他集,它等于队列i-1的传出集

每个队列在其输入和输出端都有规则,用于确定队列是否允许来自其传入集的新项目以及是否应将项目从其后面弹出到其传出集中。作为一个具体的例子,如果Q3是队列“如果它超过2小时,每30秒只保留一个图像”,那么Q3将迭代它的传入集(这是Q2的输出集)并且只允许项目i在哪里我的时间戳离Q3.first()30秒或更远(为了正常工作,需要从最高时间戳到最低时间戳处理项目)。在输出端,我们从Q3的尾部弹出任何超过12小时的对象,这将成为Q4的输入设置。

同样,@ Kevin Holditch的方法具有简单的优点,可能就是你应该做的。我只是觉得你可能会发现上述内容值得深思。

答案 1 :(得分:0)

如果您使用.net 4,则可以在CachItemPolicy对象的每个时间间隔使用MemoryCache,以便在希望它们到期时使它们过期,并使用UpdateCallbacks将某些时间移到下一个时间间隔。

答案 2 :(得分:0)

你可以很容易地做到这一点(尽管使用Linq可能不是最有效的方法)。

E.g。

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

然后对每个时间间隔执行等效查询。将它们组合成一个图像存储区并覆盖现有的存储区(假设您不想保留它们)。这将符合您当前的标准,因为随着时间的推移,所需的图像会逐渐减少。

答案 3 :(得分: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));
       }
    }

这样做可以指定如何对对象进行分组并在分组上设置年龄阈值。现在终于使用......

对于任何超过2天的照片,这将删除除1张照片之外的所有照片:

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

这将删除1天后每小时的所有照片:

        KeepOnlyOneFor(intTime, a => a.when.Hour, DateTime.Now.AddDays(-1));