java中的图像:最有效的浮点表示法?
我需要用java做一些图像处理。我正在移植python代码,它使用numpy数组,数组的维数为cols、rows、channels;这些是浮点。我知道如何将RGB从BuffereImage中取出并将其放回原处;这个问题是关于如何布局生成的浮动图像 以下是一些选项:java中的图像:最有效的浮点表示法?,java,image,image-processing,Java,Image,Image Processing,我需要用java做一些图像处理。我正在移植python代码,它使用numpy数组,数组的维数为cols、rows、channels;这些是浮点。我知道如何将RGB从BuffereImage中取出并将其放回原处;这个问题是关于如何布局生成的浮动图像 以下是一些选项: 直接翻译: float[][]img=新的float[cols][rows][channels]; 将频道放在首位: float[][]img=新的float[channels][cols][rows]; 合并索引: float[
float[][]img=新的float[cols][rows][channels];
float[][]img=新的float[channels][cols][rows];
float[]img=新浮点[行*列*通道];
img[i*cols*通道+j*通道+k]=。。。;
选项1的优点是它读取的代码与原始代码相同;但对于Java来说,它似乎不是惯用语言,可能也不太快
如果我理解Java N维数组在引擎盖下是如何工作的,那么选项2应该更快;以看起来有点古怪为代价。这似乎分配了channels*cols
大小为rows
的数组,而选项1分配了rows*cols
大小为channels
的数组(非常多的小数组=很大的开销)
选项3似乎最接近AWT和其他Java代码的功能;但是它需要传递维度(它们没有内置到数组中),并且很容易导致索引错误(特别是在有其他索引算法的情况下)
哪一个更好?为什么?其他的优点和缺点是什么?还有更好的办法吗
更新
我在一个非平凡的图像处理示例上对选项1和选项2进行了基准测试,该示例运行四种不同的算法(在10倍循环中,因此VM开始预热)。这是在Ubuntu上的OpenJDK 7上,Intel i5 cpu。令人惊讶的是,速度差别不大:选项2比选项1慢约6%。在收集的内存垃圾量上有很大的不同(使用
java-verbose:gc
):选项1在整个运行期间收集1.32GB内存,而选项2只收集0.87GB(不是一半,但也不是所有使用的图像都是彩色的)。我想知道Dalvik会有多大的不同?你是对的,选项3的内存占用更小
至于哪一个性能更好,您必须对选项进行评测和/或基准测试
如果您声明行数和列数都很大,我会选择选项3,但将数组包装在一个知道维度的类中,例如称为
Image
您是对的,选项3的内存占用较小
至于哪一个性能更好,您必须对选项进行评测和/或基准测试
如果您声明行和列计数很大,我会选择选项3,但将数组包装在一个知道维度的类中,例如称为
Image
选项3由Java中的BuffereImage使用。正如Andreas所说,这对记忆有好处,但对于图像处理和信息连续性来说,这并不是最优的。
最实际的是:
float[][] img = new float[channels][cols*rows];
这样,通道是分离的,因此可以独立处理。如果要调用本机代码,此表示将是最佳的。选项3由Java中的BuffereImage使用。正如Andreas所说,这对记忆有好处,但对于图像处理和信息连续性来说,这并不是最优的。 最实际的是:
float[][] img = new float[channels][cols*rows];
这样,通道是分离的,因此可以独立处理。如果要调用本机代码,此表示将是最佳的。具有浮点图像类型,可以直接操作原始像素数据。看
BoofCV提供了几个例程,用于将BuffereImage快速转换为不同的BoofCV映像类型。使用BoofCV例程转换缓冲区图像非常快
使用BoofCV将缓冲区图像转换为多光谱浮点型图像:
MultiSpectral<ImageFloat32> image =
ConvertBufferedImage.convertFromMulti(image,null,true,ImageFloat32.class);
获取和设置像素值的另一种方法:
float value = image.getBand(i).data[ image.startIndex + y*image.stride + x];
float f = image.getBand(i).get(x, y);
...
image.getBand(i).set(x, y, f);
BufferedImage bufferedImage =
new BufferedImage(image.width, image.height, BufferedImage.TYPE_4BYTE_ABGR);
BufferedImage bufferedImage = ConvertBufferedImage.convertTo(
image, bufferedImage, true);
其中i表示颜色通道的索引
将BoofCV图像转换回buffereImage:
float value = image.getBand(i).data[ image.startIndex + y*image.stride + x];
float f = image.getBand(i).get(x, y);
...
image.getBand(i).set(x, y, f);
BufferedImage bufferedImage =
new BufferedImage(image.width, image.height, BufferedImage.TYPE_4BYTE_ABGR);
BufferedImage bufferedImage = ConvertBufferedImage.convertTo(
image, bufferedImage, true);
具有浮点图像类型,可以直接操作原始像素数据。看
BoofCV提供了几个例程,用于将BuffereImage快速转换为不同的BoofCV映像类型。使用BoofCV例程转换缓冲区图像非常快
使用BoofCV将缓冲区图像转换为多光谱浮点型图像:
MultiSpectral<ImageFloat32> image =
ConvertBufferedImage.convertFromMulti(image,null,true,ImageFloat32.class);
获取和设置像素值的另一种方法:
float value = image.getBand(i).data[ image.startIndex + y*image.stride + x];
float f = image.getBand(i).get(x, y);
...
image.getBand(i).set(x, y, f);
BufferedImage bufferedImage =
new BufferedImage(image.width, image.height, BufferedImage.TYPE_4BYTE_ABGR);
BufferedImage bufferedImage = ConvertBufferedImage.convertTo(
image, bufferedImage, true);
其中i表示颜色通道的索引
将BoofCV图像转换回buffereImage:
float value = image.getBand(i).data[ image.startIndex + y*image.stride + x];
float f = image.getBand(i).get(x, y);
...
image.getBand(i).set(x, y, f);
BufferedImage bufferedImage =
new BufferedImage(image.width, image.height, BufferedImage.TYPE_4BYTE_ABGR);
BufferedImage bufferedImage = ConvertBufferedImage.convertTo(
image, bufferedImage, true);
这些都是在桌面上进行基准测试(只比python慢10倍)。但在选项1中,内存使用率似乎要高出2倍。如果我理解这一点,那么选项2和选项3的内存占用都将比选项1小得多。另一方面,2和3将非常接近(使用典型的维度:rows和cols~1000,channels~3),这些都在桌面上进行适当的基准测试(仅比python慢10倍)。但在选项1中,内存使用率似乎要高出2倍。如果我理解这一点,那么选项2和选项3的内存占用都将比选项1小得多。另一方面,2和3将非常接近(使用典型尺寸:行和列~1000,通道~3)