java - 在 Java 中读取 IDX 文件类型

标签 java file-io bitmap

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

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

第一个问题: 我想知道是否有人可以指导我如何将 .idx1-ubyte 转换为位图 (.bmp) 文件?

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

关于 IDX 文件格式的信息: IDX 文件格式是一种用于各种数值类型的 vector 和多维矩阵的简单格式。 基本格式为:

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

魔数(Magic Number)是一个整数(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 个字节编码 vector/矩阵的维数:1 表示 vector ,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();
                }
            }
        }
    }

}

关于java - 在 Java 中读取 IDX 文件类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17279049/

相关文章:

具有长类名和字段名的 Java 默认序列化

java - 下载带有元数据/属性(如标题、艺术家等)的 mp3

java - 如何使用Java查找文件属于哪个文件夹?

c - 使用 fwrite 存储在文本文件中的数据在 C 中不可读

c# - Image.FromFile 为什么读取位图比读取 jpeg 文件快

java - 创建 spring Pollable Channel 时出现异常

java - JDBC getGeneratedKeys() 方法是否始终与插入元素的顺序相同

C++ - 简单 - 嵌套的 while 循环永远不会终止?

android - 位图回收Android

java - 在循环中创建位图时发生内存泄漏