我有一个来自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
,它们会产生同样的问题。
答案 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}}),这应该分别等于magicNumber
和totalImages
。在此代码之后,2051, 28, 28
的{{1}}元素将10000
数字存储在MNIST数据库中。如果你kth
imageCellArray
是kth
到imshow(imageCellArray{k});
之间的任何整数,那么你应该能看到一个数字。
另外,最后一点注意事项:由于矩阵数据中的读数将位于k
,我们需要将其转换为1
,因为图像属于该类型的10000
数据库中。