在学习深度学习的过程中,会发现教程中的模型大多都是用mnist和cifar这两个数据集来演示的。想要使用这些模型在自己的数据上看一下效果,就想到将自己的数据做成与mnist或者cifar格式一样的数据。这里,主要是总结一下自已通过一番百度和学习,如何实现mnist格式数据与jpg、png格式数据的相互转化。
一、MNIST数据集
MNIST 数据集可在 http://yann.lecun.com/exdb/mnist/ 获取, 它包含了四个部分:
Training set images: train-images-idx3-ubyte.gz (9.9 MB, 解压后 47 MB, 包含 60,000 个样本)
Training set labels: train-labels-idx1-ubyte.gz (29 KB, 解压后 60 KB, 包含 60,000 个标签)
Test set images: t10k-images-idx3-ubyte.gz (1.6 MB, 解压后 7.8 MB, 包含 10,000 个样本)
Test set labels: t10k-labels-idx1-ubyte.gz (5KB, 解压后 10 KB, 包含 10,000 个标签)
TEST SET IMAGE FILE (t10k-images-idx3-ubyte):
[offset] [type] [value] [description]
0000 32 bit integer 0x00000803(2051) magic number
0004 32 bit integer 10000 number of images
0008 32 bit integer 28 number of rows
0012 32 bit integer 28 number of columns
0016 unsigned byte ?? pixel
0017 unsigned byte ?? pixel
........
xxxx unsigned byte ?? pixel
这是MNIST官网上对数据集的介绍,用8-bit (1 byte ) 来表示一个pixel 的灰度,0 表示纯白色,255表示纯黑色,共256个灰度级别。每张图片有28 * 28个pixel,所以每张图片占用 28 * 28=784个bytes。
第一个32-bit 是 magic number, 00 00 08 03 = 8 * 16^2 + 3 * 16^0=2051
前两个bytes 均为0, 第三个byte 表名数据类型, 0x08 表示 unsigned byte,第四个byte 是数据的维度信息,0x03 表示测试集有3 dimensions, 图片 * 图片行 * 图片列=10000 * 28 * 28。
第二个32-bit 是样本数量,10000。
第三个32-bit 是行数, 28。
第四个32-bit 是列数, 28。
后面每 28*28=784 bytes 为一张图片的二进制信息。
二、将mnist数据集转化成图片(matlab 实现)
(1)main.m
首先,将mnist格式数据转化成.mat文件,然后将.mat文件转化成jpg格式。
clear
clc
%% 首先将ubyte格式文件转化成常用的.mat文件格式
filename = './train-images.idx3-ubyte';
savename = './test_x';
FID = fopen(filename,'r');
MagicNumber=readint32(FID);
NumberofImages=readint32(FID);
rows=readint32(FID);
colums=readint32(FID);
savePath = [savename,'.mat'];
test_x = zeros(NumberofImages,rows*colums);
for i = 1:NumberofImages
temp = fread(FID,(rows*colums), 'uchar');
test_x(i,:) = temp';
end
save(savePath,'test_x')
%%将.mat文件转化为jpg格式
for j = 1:1:NumberofImages
b = test_x(j,:); %每次读取一行数据
D = reshape(b,28,28);
sc=strcat('C:\Users\ouc\Desktop\demo\',sprintf('%d',j)); %命名保存
Sc=strcat(sc,'.jpg');
imwrite(D,Sc);
end
(2)readint32.m
function [getdata]=readint32(FID)
data = [];
for i = 1:4
f=fread(FID,1);
data = strcat(data,num2str(dec2base(f,2,8)));
end
getdata = bin2dec(data);
end
最终可以得到jpg格式的图片。
三、将图片转化成mnist格式数据(python 实现)
这部分百度到了别人的代码,附代码地址:https://github.com/gskielian/JPG-PNG-to-MNIST-NN-Format,
亲试有效,感谢作者~
import os
from PIL import Image
from array import *
from random import shuffle
# Load from and save to
Names = [['./training-images','train'], ['./test-images','test']]
for name in Names:
data_image = array('B')
data_label = array('B')
FileList = []
for dirname in os.listdir(name[0])[1:]: # [1:] Excludes .DS_Store from Mac OS
path = os.path.join(name[0],dirname)
for filename in os.listdir(path):
if filename.endswith(".png"):
FileList.append(os.path.join(name[0],dirname,filename))
shuffle(FileList) # Usefull for further segmenting the validation set
for filename in FileList:
label = int(filename.split('/')[2])
Im = Image.open(filename)
pixel = Im.load()
width, height = Im.size
for x in range(0,width):
for y in range(0,height):
data_image.append(pixel[y,x])
data_label.append(label) # labels start (one unsigned byte each)
hexval = "{0:#0{1}x}".format(len(FileList),6) # number of files in HEX
# header for label array
header = array('B')
header.extend([0,0,8,1,0,0])
header.append(int('0x'+hexval[2:][:2],16))
header.append(int('0x'+hexval[2:][2:],16))
data_label = header + data_label
# additional header for images array
if max([width,height]) <= 256:
header.extend([0,0,0,width,0,0,0,height])
else:
raise ValueError('Image exceeds maximum size: 256x256 pixels');
header[3] = 3 # Changing MSB for image data (0x00000803)
data_image = header + data_image
output_file = open(name[1]+'-images-idx3-ubyte', 'wb')
data_image.tofile(output_file)
output_file.close()
output_file = open(name[1]+'-labels-idx1-ubyte', 'wb')
data_label.tofile(output_file)
output_file.close()
# gzip resulting files
for name in Names:
os.system('gzip '+name[1]+'-images-idx3-ubyte')
os.system('gzip '+name[1]+'-labels-idx1-ubyte')
最终可以得到mnist格式的数据。