4

我有一个来自 MNIST 图像数据库的二进制文件,重命名为“myfile.dat”。这由一组 4 个无符号 32 位整数组成,然后是一个无符号 8 位整数链。我想读取这个文件并将其内容存储为一个数组。这是我的代码:

file_id = fopen('myfile.dat', 'rb');
data = fread(file_id, 'int');
size(data)
class(data)

输出是:

ans =

    2502           1


ans =

double

(2502, 1) 的大小符合预期。但是为什么它告诉我数据是double,当我指定它是int

我知道前几个数字应该是什么,并且输出数据不符合预期。我也试过了int32,这uint给出uint32了同样的问题。

4

1 回答 1

3

根据我们的评论,MATLAB 一次读取 4 个整数的方式是little-endian格式,而 MNIST 数据库文件的文件格式是big-endian. 因此,当我们读入文件的前四个字节时,这些字节0x00, 0x00, 0x08, 0x03与我们预期的一样。但是,MATLAB 会将其读取为0x03, 0x08, 0x00, 0x00. 将其转换为整数时,我们实际上会得到50855936不是我们想要的。

解决这个问题的一个技巧是,当我们需要一次读取几个字节时,我们需要确保我们指定了uint8数据类型。这会将每个字节存储到数组中的单独元素中。然后,我们可以通过将每个字节移位指定的数量,然后对结果求和来计算我们需要的必要数字。我们需要对数据文件中的前几个字节执行此操作。

或者,我们可以使用swapbytes您在评论中所述的方法,这将给我们完全相同的东西。您可以只读取 1 个uint32类型的字节,然后交换字节的顺序以使字节符合big-endian格式。您需要记住,即使您将数据读取为uint32,该数字也将存储在 MATLAB 中,double因此您需要在进入swapbytes.

一旦我们得到实际的图像数据,我们可以一次读取numRows x numCols字节,然后重塑数组,使其成为图像。我们可以将每个图像存储到一个元胞数组中。事不宜迟,代码如下。

clear all;
close all;

%//Open file
fid = fopen('t10k-images-idx3-ubyte', 'r');

%//Read in magic number
%//A = fread(fid, 4, 'uint8');
%//magicNumber = sum(bitshift(A', [24 16 8 0]));

%//OR
A = fread(fid, 1, 'uint32');
magicNumber = swapbytes(uint32(A));

%//Read in total number of images
%//A = fread(fid, 4, 'uint8');
%//totalImages = sum(bitshift(A', [24 16 8 0]));

%//OR
A = fread(fid, 1, 'uint32');
totalImages = swapbytes(uint32(A));

%//Read in number of rows
%//A = fread(fid, 4, 'uint8');
%//numRows = sum(bitshift(A', [24 16 8 0]));

%//OR
A = fread(fid, 1, 'uint32');
numRows = swapbytes(uint32(A));

%//Read in number of columns
%//A = fread(fid, 4, 'uint8');
%//numCols = sum(bitshift(A', [24 16 8 0]));

%// OR
A = fread(fid, 1, 'uint32');
numCols = swapbytes(uint32(A));

%//For each image, store into an individual cell
imageCellArray = cell(1, totalImages);
for k = 1 : totalImages
    %//Read in numRows*numCols pixels at a time
    A = fread(fid, numRows*numCols, 'uint8');
    %//Reshape so that it becomes a matrix
    %//We are actually reading this in column major format
    %//so we need to transpose this at the end
    imageCellArray{k} = reshape(uint8(A), numCols, numRows)';
end

%//Close the file
fclose(fid);

如果检查行数和列数(存储为numRows, numCols)、幻数(存储为magicNumber)和图像总数(存储为totalImages),这应该分别等于2051, 28, 2810000。在这段代码之后, 的kth元素imageCellArray会将kth数字存储在 MNIST 数据库中。如果你这样做imshow(imageCellArray{k});,在到k之间的任何整数,你应该能够看到一个数字。110000

另外,最后一点:由于矩阵数据的读取将在 中double,我们需要将其转换uint8为数据库中的图像属于该类型。

祝你好运!

于 2014-06-09T21:00:02.700 回答