2

我正在编写一个以设定的时间间隔捕获屏幕的程序,当我开始测试时,我发现在它开始捕获图片后我几乎立即收到了 OutOfMemoryException。我尝试分配更多内存 - 我给了它 256m,但这几乎没有帮助。它所做的只是让它在抛出异常并再次崩溃之前再持续 2 或 3 秒。

我知道 createScreenCapture(...) 方法使用大量内存,但我已经看到可以使用相同方法长时间记录的示例程序 - 他们是如何做到的?

编辑:我已经使用了你们的一些建议,现在我没有得到 OutOfMemoryExceptions!万岁!我采取了将照片保存到硬盘驱动器的路线。但是,实际上将它们写入存档文件确实需要很长时间。将 63 帧写入存档文件需要将近 2 分钟!

我无法提供任何代码,因为我正在重写 I/O 部分。致力于改善 ^ 情况。

4

5 回答 5

1

我已经看到可以使用相同方法长时间记录的示例程序 - 他们是如何做到的?

将图像序列化到磁盘(作为单独的文件或单个 Zip)。


我应该使用某种程序将其保存在硬盘上吗?我正在考虑将图像转换为 int[] 数组,然后将其存储,因为数组是可序列化的。

有许多策略可以采用。

  • 将图像转换为无损(且易于编码)图像格式并存储图像:
    1. 在磁盘上的单独文件中,或..
    2. 作为(未压缩的)Zip 存档中的单独条目。通过使用 Zip,我们可以解决存储“数千”文件时报告的早期问题。出于速度考虑(以及 Zip 对大多数媒体格式的作用很小的事实),使其未压缩。
  • 我曾经在 usenet 上看到称为 (AFAIR) 'Screenies' 的代码或类似的代码(现在找不到),它的功能与您的建议非常相似。它将原始信息(没有任何编码)存储到磁盘上。我尝试了代码,但无法获得比将图像编码为 PNG 并将图像序列化到磁盘更好的性能。您可能想运行一些测试,看看现在哪种方法更快。
于 2012-01-08T23:39:00.310 回答
1

它是如何存储图像的?你的屏幕有多大?我不熟悉 BufferedImage 支持的所有 ColorModel,但最坏的情况是 1900 x 1200 的完整 RGB 图像将是 1900 * 1200 * 24 位,或大约 7 MB。即使在 5 FPS 下,也就是每秒 35 MB,这将在 10 秒内溢出 256 MB,忽略所有其他内存使用情况。

您肯定需要改为写入磁盘,或动态压缩该数据,但您仍然会轻松达到内存限制。

于 2012-01-09T00:56:53.470 回答
0

在拍摄下一张照片之前,90 毫秒是一个非常短的睡眠间隔。你可能吃的太多了。collection为什么不限制可以得到多大。

于 2012-01-08T23:39:05.980 回答
0

Thread.sleep(90) 将使您的程序暂停 90 毫秒。所以在 2-3 秒内,大约需要 200-300 张照片,这将是相当多的。

于 2012-01-08T23:39:50.757 回答
0

您正在将图像(区域)的内存添加到集合中。

        BufferedImage image = robot.createScreenCapture(area); //OutOfMemory on this line.
        collection.addFirst(image);

你能期待什么,你添加的越多,它就越大。

尝试将其写入文件/数据库或删除较旧的图像缓冲区以维护可能包含 20 个最后图像的缓冲区。

90 毫秒有点短,如果您要比较图像,请在添加到集合之前尝试将前一个图像与当前图像进行比较。

如果您正在使用网络摄像头进行跟踪类型的解决方案,请告诉我们,它是一套全新的工具和概念。

于 2012-01-09T01:08:54.563 回答