最近写了一个程序,需要大批量地读取8位的BMP格式的灰度图,程序写完profiler一看,竟然读图和处理的时间不相上下,这是万万不可接受的。经过一番折腾,最后决定用C++来加速8位BMP图片的读取。目的很简单,读进来以后变成Float32类型就好了。
打个广告:julia什么语言都能call,C,C++,Fortran,python,R,AnyCall!
PyCall.jl + OpenCV方案
想想,读图是多么简单的事情啊,OpenCV走一波岂不美滋滋。然而julia没有OpenCV的封装,那就PyCall吧!于是请来Python轻松call了OpenCV。PyCall就是这么轻松愉快,所有python的库都直接call,你的是我的,他的也是我的,全是我的!
using PyCall
cv2=pyimport("cv2")
imreadcv(fname)=Float32.(cv2."imread"(fname,0))
选了张512×512的8位灰度图来测个速呗。快速计算一下大小。512×512=256KB,换成Float32也就1MB。
memory estimate: 61.25 MiB
allocs estimate: 2359352
--------------
minimum time: 483.473 ms (1.26% GC)
median time: 495.222 ms (1.87% GC)
mean time: 503.798 ms (3.19% GC)
maximum time: 548.973 ms (15.07% GC)
--------------
samples: 10
evals/sample: 1
然而测试结果大跌眼镜,竟然alloc了61.25M?WTF???来看看PyCall怎么说的:
Multidimensional NumPy arrays (ndarray
) are supported and can be converted to the native JuliaArray
type, which makes a copy of the data.
Copy,从Python到Julia的数组是Copy的,反之则不是。就算是Copy也不至于多吃60倍内存对不?果断放弃PyCall。
ImageMagick.jl方案
那要不用julia自己的库?ImageMagick.jl 给大名鼎鼎的ImageMagick库做了封装,速度应该不错。这里有个小坑,对于bmp格式的图,默认是3通道!bmp格式里明明有一位告诉了通道数,就这样被忽略了。无奈,必须先转灰度图,变成了0-1的8位浮点表示。不得不说这是Images.jl 的优秀设计,然而