在Java中读取IDX文件类型

Q L*_*Liu 5 java file-io bitmap

我用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
Run Code Online (Sandbox Code Playgroud)

幻数是一个整数(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)
Run Code Online (Sandbox Code Playgroud)

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

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

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

Ray*_*eeA 11

非常直截了当,正如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();
                }
            }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)


WPr*_*cht 0

URL 描述了您必须解码的格式,并且他们提到它是非标准的,因此明显的 Google 搜索不会出现任何使用代码。然而,它非常简单,带有标题,后跟 0-255 灰度值的 28x28 像素矩阵。

读出数据后(记住要注意字节顺序),创建 BMP 文件就很简单了。

我向您推荐以下文章:

如何在java中从像素字节数组制作bmp图像

他们的问题是关于颜色的,但是他们的代码已经适用于灰度,这就是您所需要的,您应该能够从该片段中得到一些东西。