加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

在Scala中编写功能强大且功能强大的图像处理库

发布时间:2020-12-16 09:38:56 所属栏目:安全 来源:网络整理
导读:我们正在为Scala(学生项目)开发一个小型图像处理库。该库完全功能(即无变异性)。图像的栅格存储为Stream [Stream [Int]],以最小的努力利用懒惰评估的好处。然而,在对映像执行一些操作时,堆将被满载并抛出OutOfMemoryError。 (例如,在JVM堆空间不足之前,
我们正在为Scala(学生项目)开发一个小型图像处理库。该库完全功能(即无变异性)。图像的栅格存储为Stream [Stream [Int]],以最小的努力利用懒惰评估的好处。然而,在对映像执行一些操作时,堆将被满载并抛出OutOfMemoryError。 (例如,在JVM堆空间不足之前,可以对大小为500 x 400,35 kb的jpeg图像执行多达4个操作。)

我们想到的方法是:

>使用JVM选项进行Twiddling并增加堆大小。 (我们不知道如何做到这一点在IDEA – 我们正在使用的IDE。)
>选择与Stream [Stream [Int]]不同的数据结构,更适合图像处理任务。 (再次,我们对于简单的List和Stream之外的功能数据结构并不太了解。)

我们最后一个选择是放弃不变性,并使其成为一个可变的库(如流行的图像处理库),这是我们不想做的。请建议我们有一些方法来保持这个库的功能并且仍然有效,如果你知道我的意思。

谢谢,
Siddharth Raina。

附录:
对于大小为1024 x 768的图像,即使对于单个映射操作,JVM也会耗尽堆空间。我们测试中的一些示例代码:

val image = Image from "E:/metallica.jpg"
val redded = image.map(_ & 0xff0000)
redded.display(title = "Redded")

并输出:

"C:Program Files (x86)Javajdk1.6.0_02binjava" -Didea.launcher.port=7533 "-Didea.launcher.bin.path=C:Program Files (x86)JetBrainsIntelliJ IDEA Community Edition 10.0.2bin" -Dfile.encoding=windows-1252 -classpath "C:Program Files (x86)Javajdk1.6.0_02jrelibcharsets.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibdeploy.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibjavaws.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibjce.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibjsse.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibmanagement-agent.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibplugin.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibresources.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibrt.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibextdnsns.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibextlocaledata.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibextsunjce_provider.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibextsunmscapi.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibextsunpkcs11.jar;C:new PhPhoebeoutproductionPhoebe;E:InventoryMarvin.jar;C:scala-2.8.1.finallibscala-library.jar;C:scala-2.8.1.finallibscala-swing.jar;C:scala-2.8.1.finallibscala-dbc.jar;C:new Ph;C:scala-2.8.1.finallibscala-compiler.jar;E:Inventorycommons-math-2.2.jar;E:Inventorycommons-math-2.2-sources.jar;E:Inventorycommons-math-2.2-javadoc.jar;E:Inventoryjmathplot.jar;E:Inventoryjmathio.jar;E:Inventoryjmatharray.jar;E:InventoryJavax Media.zip;E:Inventoryjai-core-1.1.3-alpha.jar;C:Program Files (x86)JetBrainsIntelliJ IDEA Community Edition 10.0.2libidea_rt.jar" com.intellij.rt.execution.application.AppMain phoebe.test.ImageTest
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at scala.collection.Iterator$class.toStream(Iterator.scala:1011)
    at scala.collection.IndexedSeqLike$Elements.toStream(IndexedSeqLike.scala:52)
    at scala.collection.Iterator$$anonfun$toStream$1.apply(Iterator.scala:1011)
    at scala.collection.Iterator$$anonfun$toStream$1.apply(Iterator.scala:1011)
    at scala.collection.immutable.Stream$Cons.tail(Stream.scala:565)
    at scala.collection.immutable.Stream$Cons.tail(Stream.scala:557)
    at scala.collection.immutable.Stream$$anonfun$map$1.apply(Stream.scala:168)
    at scala.collection.immutable.Stream$$anonfun$map$1.apply(Stream.scala:168)
    at scala.collection.immutable.Stream$Cons.tail(Stream.scala:565)
    at scala.collection.immutable.Stream$Cons.tail(Stream.scala:557)
    at scala.collection.immutable.Stream$$anonfun$flatten1$1$1.apply(Stream.scala:453)
    at scala.collection.immutable.Stream$$anonfun$flatten1$1$1.apply(Stream.scala:453)
    at scala.collection.immutable.Stream$Cons.tail(Stream.scala:565)
    at scala.collection.immutable.Stream$Cons.tail(Stream.scala:557)
    at scala.collection.immutable.Stream.length(Stream.scala:113)
    at scala.collection.SeqLike$class.size(SeqLike.scala:221)
    at scala.collection.immutable.Stream.size(Stream.scala:48)
    at scala.collection.TraversableOnce$class.toArray(TraversableOnce.scala:388)
    at scala.collection.immutable.Stream.toArray(Stream.scala:48)
    at phoebe.picasso.Image.force(Image.scala:85)
    at phoebe.picasso.SimpleImageViewer.<init>(SimpleImageViewer.scala:10)
    at phoebe.picasso.Image.display(Image.scala:91)
    at phoebe.test.ImageTest$.main(ImageTest.scala:14)
    at phoebe.test.ImageTest.main(ImageTest.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115)

Process finished with exit code 1

解决方法

如果我理解正确,您将每个像素存储在一个Stream元素中,这可能是低效的。您可以做的是创建自定义的LazyRaster类,其中包含对某些大小(例如,20×20)的图像块的延迟引用。第一次写一个块时,它的相应的数组被初始化,从那里改变像素意味着写入该数组。

这是更多的工作,但可能会导致更好的性能。此外,如果您希望支持图像操作的堆叠(例如,进行地图绘制),然后在“一次性”中评估图像,则实施可能会变得棘手 – 流实现是最佳证据。

另一件可以做的事情是确保旧的Streams是properly garbage collected.我怀疑你的例子中的图像对象是你的流的包装器。如果您希望将多个映像操作(如映射)堆叠在一起,并且能够gc不再需要的引用,则必须确保不保存对流的任何引用 – 请注意,如果:

>你有一个参考你的图像堆栈(在图中的例子)
>您的图像包装器包含这样的参考。

不用多了解具体的用例,很难说更多。

就个人而言,我会完全避免Streams,只需使用一些不可改变的基于阵列的数据结构,既节省空间,又避免了拳击。我唯一可以看到Streams使用的地方是迭代图像转换,如卷积或应用一叠过滤器。相反,您不会有像素流,而是流图像。这可能是表达一系列变革的好方法 – 在这种情况下,上面给出的链接中关于gc的评论适用。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读