在Java中读取IDX文件类型

我用Java构建了一个图像分类器,我想针对这里提供的图像进行测试:http: //yann.lecun.com/exdb/mnist/

不幸的是,如果您下载train-images-idx3-ubyte.gz或任何其他3个文件,它们都是文件类型:.idx1-ubyte

第一个问题:我想知道是否有人可以向我提供有关如何将.idx1-ubyte转换为位图(.bmp)文件的说明?

第二个问题:或者我一般如何阅读这些文件?

有关IDX文件格式的信息:IDX文件格式是各种数字类型的向量和多维矩阵的简单格式。 基本格式是:

magic number size in dimension 0 size in dimension 1 size in dimension 2 ..... size in dimension N data 

幻数是一个整数(MSB优先)。 前2个字节始终为0。

第三个字节编码数据的类型:

 0x08: unsigned byte 0x09: signed byte 0x0B: short (2 bytes) 0x0C: int (4 bytes) 0x0D: float (4 bytes) 0x0E: double (8 bytes) 

第4个字节编码向量/矩阵的维数:1表示向量,2表示矩阵….

每个维度的大小为4字节整数(MSB优先,高端,与大多数非英特尔处理器一样)。

数据存储在C数组中,即最后一维中的索引变化最快。

非常直截了当,正如WPrecht所说:“URL描述了你必须解码的格式”。 这是我的idx文件的ImageSet导出器,不是很干净,但它做了它必须做的事情。

 public class IdxReader { public static void main(String[] args) { // TODO Auto-generated method stub FileInputStream inImage = null; FileInputStream inLabel = null; String inputImagePath = "CBIR_Project/imagesRaw/MNIST/train-images-idx3-ubyte"; String inputLabelPath = "CBIR_Project/imagesRaw/MNIST/train-labels-idx1-ubyte"; String outputPath = "CBIR_Project/images/MNIST_Database_ARGB/"; int[] hashMap = new int[10]; try { inImage = new FileInputStream(inputImagePath); inLabel = new FileInputStream(inputLabelPath); int magicNumberImages = (inImage.read() << 24) | (inImage.read() << 16) | (inImage.read() << 8) | (inImage.read()); int numberOfImages = (inImage.read() << 24) | (inImage.read() << 16) | (inImage.read() << 8) | (inImage.read()); int numberOfRows = (inImage.read() << 24) | (inImage.read() << 16) | (inImage.read() << 8) | (inImage.read()); int numberOfColumns = (inImage.read() << 24) | (inImage.read() << 16) | (inImage.read() << 8) | (inImage.read()); int magicNumberLabels = (inLabel.read() << 24) | (inLabel.read() << 16) | (inLabel.read() << 8) | (inLabel.read()); int numberOfLabels = (inLabel.read() << 24) | (inLabel.read() << 16) | (inLabel.read() << 8) | (inLabel.read()); BufferedImage image = new BufferedImage(numberOfColumns, numberOfRows, BufferedImage.TYPE_INT_ARGB); int numberOfPixels = numberOfRows * numberOfColumns; int[] imgPixels = new int[numberOfPixels]; for(int i = 0; i < numberOfImages; i++) { if(i % 100 == 0) {System.out.println("Number of images extracted: " + i);} for(int p = 0; p < numberOfPixels; p++) { int gray = 255 - inImage.read(); imgPixels[p] = 0xFF000000 | (gray<<16) | (gray<<8) | gray; } image.setRGB(0, 0, numberOfColumns, numberOfRows, imgPixels, 0, numberOfColumns); int label = inLabel.read(); hashMap[label]++; File outputfile = new File(outputPath + label + "_0" + hashMap[label] + ".png"); ImageIO.write(image, "png", outputfile); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (inImage != null) { try { inImage.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (inLabel != null) { try { inLabel.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } 

URL描述了您必须解码的格式,并且它们提到它是非标准的,因此明显的Goggle搜索不会显示任何使用代码。 然而,它非常直接,标题后跟一个28到28像素矩阵的0-255灰度值。 一旦您读出数据(记得要注意字节序),创建BMP文件是直截了当的。 我向你推荐以下文章: 如何从java中的像素字节数组制作bmp图像,他们的问题是关于颜色,但是他们的代码已经适用于灰度级,这就是你需要的东西,你应该能够从中得到一些东西片段。