我正在使用Java项目进行高级图像处理。实际上,我大部分的操作都是使用OpenCV完成的,并且我使用JNI来包装我需要的OpenCV函数。我非常满意OpenCV提供的性能,编写OpenCV代码的人们应该得到很大的赞誉。与Java开发者编写的代码形成了鲜明的对比。
我一开始对我的编程语言选择感到乐观,我的第一个工作版本的效果还可以,但其性能远远不足以实现实时性(每2秒钟获得1帧)。我已经对我的代码进行了一些优化,这有很大的帮助。我已经成功将帧速率提高到每秒约10-20帧,这很不错,但我发现要进行进一步的优化,我必须重写Java代码以使其更加高效。
我对Java开发人员在编写与媒体相关类的代码时非常不重视性能感到震惊。我已经下载并探索了我使用的函数的OpenJDK。例如,在Raster类下有一个名为getPixels(...)的函数,它获取图像的像素。我期望这个函数在源代码中是高度优化的函数,使用System.arrayCopy进行多次调用以进一步优化性能。但实际上我发现的是非常“繁琐”的代码,他们调用了5-6个不同的类和10-20个不同的方法,仅仅为了完成我可以用一行代码完成的任务:
for (int i =0; i < n; i++) {
long p = rawFrame[i];
p = (p << 32) >>> 32;
byte red = (byte) ((p >> 16) & 0xff);
byte green = (byte) ((p >> 8) & 0xff);
byte blue = (byte) ((p) & 0xff);
byte val = (byte)(0.212671f * red + 0.715160f * green + 0.072169f * blue);
data[i] = val;
grayFrameData[i] = (val & 0x80) + (val & (0x7f));
}
上面的代码将图像转换为灰度并获得浮点像素数据,大约需要1-10毫秒。如果我想使用Java内置函数完成相同的操作,转换为灰度本身就需要200-300毫秒,然后获取浮点像素需要大约50-100毫秒。这对于实时性能来说是不可接受的。请注意,为了加速,我大量使用位运算符,而Java开发人员则避之唯恐不及。我理解他们需要处理一般情况,但即使这样,他们也不能至少提供优化选项或者至少警告这段代码执行起来会有多慢吗。
我的问题是,在开发的这个晚期(我已经有了第一次迭代,现在正在进行第二次,以便更实时地工作),我应该咬紧牙关切换到C/C++,在那里我可以更好地调整细节,还是应该坚持使用Java,并希望事情变得更加实时友好,这样我就不必重新编写已经实现的Java代码以获得加速。
我真的开始对Java的“高雅”和缓慢感到厌倦。似乎有太多的类。