【发布时间】:2017-04-21 06:49:13
【问题描述】:
作为 Clojure 的新手,我想计算(很多)jpg 图像的平均亮度。为此,我使用 Java 中的 ImageIO/read 将图像加载到内存中,提取其后面的字节缓冲区并应用平均值。
(defn brightness
"Computes the average brightness of an image."
[^File file]
(-> file
ImageIO/read
.getRaster
.getDataBuffer
.getData
byteaverage))
这里是平均值
(defn byteaverage
[numbers]
(/ (float
(->> numbers
(map bytetoint)
(apply +)))
(count numbers))
)
需要考虑到字节是用Java签名的,需要先转换为足够大的整数。
(defn bytetoint
[b]
(bit-and b 0xFF)
)
虽然这确实给出了正确的结果,但速度非常慢。 20 兆像素的图像大约需要 10 到 20 秒。磁盘访问不是问题。从玩time 来看,罪魁祸首似乎是bytetoint 转换。仅将这个bytetoint 映射到字节数组会占用 8 GB 内存,并且不会在 REPL 中终止。
为什么会这样?对此我们能做些什么?
PS:我知道可以使用其他编程语言、库、多线程或更改算法。我的观点是,上面的 Clojure 代码应该要快得多,我想了解为什么它不是。
【问题讨论】: