png转mnist数据集
数据集目录
二分类则目录为0,1。多分类目录0,1,…依次类推。
MNIST格式
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
- 第一个32bit是文件的头信息,前两个bytes 均为0, 第三个byte 表名数据类型, 0x08 表示 unsigned byte,第四个byte 是数据的维度信息,0x03 表示测试集有3 dimensions
- 第二个32bit是内容的数量,即图片的数量
- 第三个和四个32bit是图片的行和列长,即长宽
- 以后的都为图片的数据
代码
原代码地址:https://github.com/gskielian/JPG-PNG-to-MNIST-NN-Format
import os
from PIL import Image
from array import *
from random import shuffle
# 图片训练数据集和测试数据集
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]): #遍历所有lable下的图片
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) # 打乱
for filename in FileList:
label = int(filename.split('/')[2]) #获取lable,索引根据具体文件路径决定
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) # 存储图片数据
hexval = "{0:#0{1}x}".format(len(FileList),6) # 获取图片个数
# 文件头部信息
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
# 在文件头中添加图片长宽信息
if max([width,height]) <= 256: # 长宽最大为256
header.extend([0,0,0,width,0,0,0,height])
else:
raise ValueError('Image exceeds maximum size: 256x256 pixels');
header[3] = 3 # 图片维度为3维,即将00000801改为00000803
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()
# 在linux下可压缩文件
for name in Names:
os.system('gzip '+name[1]+'-images-idx3-ubyte')
os.system('gzip '+name[1]+'-labels-idx1-ubyte')
错误提示
1.长度错误
invalid literal for int() with base 16: '0x'
说明添加图片个数时索引超过了hexval的长度。
长度超过4,则要多一次header.append(),最多两个append即长度不超过8,对应的header.extend([0,0,8,1,0,0])中末尾占位的0依次减少。
2.数值不匹配
假设图片数量为1139320条,十六进制为0x116278,按两位分割转为10进制分别为17、98、120,存入header为0803001798120