在MATLAB中读取MNIST图像数据库二进制文件

时间:2014-06-09 19:52:27

标签: image matlab mnist

我有一个来自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

我知道前几个数字应该是什么,输出数据不符合预期。我也尝试了int32uintuint32,它们会产生同样的问题。

1 个答案:

答案 0 :(得分: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读入,该数字也将作为double存储在MATLAB中,因此您需要在进入{之前转换该数字{1}}。

一旦我们得到实际的图像数据,我们可以一次读入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)和图像总数(存储为{ {1}}),这应该分别等于magicNumbertotalImages。在此代码之后,2051, 28, 28的{​​{1}}元素将10000数字存储在MNIST数据库中。如果你kth imageCellArraykthimshow(imageCellArray{k});之间的任何整数,那么你应该能看到一个数字。

另外,最后一点注意事项:由于矩阵数据中的读数将位于k,我们需要将其转换为1,因为图像属于该类型的10000数据库中。

祝你好运!