赞
踩
深度学习界的Hello Word程序,MNIST手写数字体识别。
MNIST 数据集可在 http://yann.lecun.com/exdb/mnist/ 获取, 它包含了四个部分:
train-images-idx3-ubyte.gz: training set images (9912422 bytes),训练图像数据
train-labels-idx1-ubyte.gz: training set labels (28881 bytes),训练图像标签
t10k-images-idx3-ubyte.gz: test set images (1648877 bytes),测试图像数据
t10k-labels-idx1-ubyte.gz: test set labels (4542 bytes),测试图像标签
train-images-idx3-ubyte.gz需要解压为train-images.idx3-ubyte,用winhex打开此文件,如下图所示,00000803是固定,0000EA60表示有6万张图片,0000001C表示图片的宽度为28,接着0000001C表示图片的高度为28。
本次目的,使用go语言把文件train-images.idx3-ubyte读取,并生成一张图片。
代码如下:
- import (
- "encoding/binary"
- "fmt"
- "image"
- "image/color"
- "image/png"
- "io"
- "log"
- "os"
- )
-
- type RawImage []byte
-
-
- // 输入文件句柄
- // 输出所有图片切片数组
- func readImageFile(r io.Reader) ([]RawImage, error) {
-
- var magic int32
-
- if err := binary.Read(r, binary.BigEndian, &magic); nil != err{
- return nil , err
- }
-
- if 0x0803 != magic{
- return nil, os.ErrInvalid
- }
-
- var picNum int32
- if err := binary.Read(r, binary.BigEndian, &picNum); nil != err{
- return nil, err
- }
-
- var width, heigth int32
-
- if err := binary.Read(r, binary.BigEndian, &width); nil != err{
- return nil, err
- }
-
-
- if err := binary.Read(r, binary.BigEndian, &heigth); nil != err{
- return nil, err
- }
-
- imags := make([]RawImage, picNum)
-
- for i := 0; i < int(picNum); i++ {
-
- imags[i] = make(RawImage, width * heigth)
-
- fLen, err := io.ReadFull(r, imags[i])
-
- if nil != err{
- return nil, err
- }
-
- if fLen != int(width * heigth) {
- return nil, os.ErrInvalid
- }
-
- }
-
- return imags, nil
-
-
- }
-
-
-
- func main() {
-
- fp, _ := os.Open("train-images.idx3-ubyte")
-
- imgs, err := readImageFile(fp)
-
- if nil != err{
- log.Fatal(err)
- }
-
- fmt.Println(len(imgs))
-
- // 使用GO生成图片
-
-
- imCols := 28
- imRows := 28
-
- rect := image.Rect(0, 0, imCols, imRows)
-
- rgba := image.NewNRGBA(rect)
-
- //
- for dy := 0; dy < imCols; dy++{
- for dx := 0; dx < imRows; dx++{
- rgba.Set(dy, dx, color.Gray{imgs[0][dy + dx * imRows]})
- }
- }
-
- fIm, err := os.Create("aaa.png")
-
- if nil != err{
- log.Fatal(err)
- }
-
- err = png.Encode(fIm, rgba)
-
- if nil != err{
- log.Fatal(err)
- }
-
-
- }
- fp, _ := os.Open("train-images.idx3-ubyte")
-
- imgs, err := readImageFile(fp)
-
- if nil != err{
- log.Fatal(err)
- }
-
- fmt.Println(len(imgs))
函数readImageFile,用于读取文件train-images.idx3-ubyte,输入是文件句柄,输出是6万张图片的图片数据切片。
- var magic int32
-
- if err := binary.Read(r, binary.BigEndian, &magic); nil != err{
- return nil , err
- }
-
- if 0x0803 != magic{
- return nil, os.ErrInvalid
- }
函数readImageFile的实现,此处通过binary库读取二进制文件,并且按照大端读取,读取四个字节,读取魔数,并且判断是否为00000803。
- var picNum int32
- if err := binary.Read(r, binary.BigEndian, &picNum); nil != err{
- return nil, err
- }
接着继续通过binary库读取二进制文件,接着读取图片的数量0000EA60,即60000张。
- var width, heigth int32
-
- if err := binary.Read(r, binary.BigEndian, &width); nil != err{
- return nil, err
- }
-
-
- if err := binary.Read(r, binary.BigEndian, &heigth); nil != err{
- return nil, err
- }
继续读取图片的宽度和高度,都为0000001C,即28。
- imags := make([]RawImage, picNum)
-
- for i := 0; i < int(picNum); i++ {
-
- imags[i] = make(RawImage, width * heigth)
-
- fLen, err := io.ReadFull(r, imags[i])
-
- if nil != err{
- return nil, err
- }
-
- if fLen != int(width * heigth) {
- return nil, os.ErrInvalid
- }
-
- }
-
- return imags, nil
分配imags的60000张RawImage,其中RawImage也是切片[]byte。然后循环读取60000张,分别对每个imags切片,再次分配图片的大小width * heigth,再通过io.ReadFull接口读二进制文件内容。
至此函数readImageFile完成了读取每张图片的功能,并输出到imags的切片。
- // 使用GO生成图片
-
-
- imCols := 28
- imRows := 28
-
- rect := image.Rect(0, 0, imCols, imRows)
-
- rgba := image.NewNRGBA(rect)
-
- //
- for dy := 0; dy < imCols; dy++{
- for dx := 0; dx < imRows; dx++{
- //fmt.Printf("dx = [%d], dy = [%d]\r\n", dx, dy)
- rgba.Set(dy, dx, color.Gray{imgs[0][dy + dx * imRows]})
- }
- }
-
- fIm, err := os.Create("aaa.png")
-
- if nil != err{
- log.Fatal(err)
- }
-
- err = png.Encode(fIm, rgba)
-
- if nil != err{
- log.Fatal(err)
- }
此代码,是把imags的切片的第一张图片数据,生成灰图PNG格式图片。下面遂段分解说明:
rect := image.Rect(0, 0, imCols, imRows)
创建28 * 28大小矩形框。
rgba := image.NewNRGBA(rect)
创建28 * 28大小矩形框的画板,用于显示图片。
- for dy := 0; dy < imCols; dy++{
- for dx := 0; dx < imRows; dx++{
- rgba.Set(dy, dx, color.Gray{imgs[0][dy + dx * imRows]})
- }
- }
rgba.Set是用于在画板上画点,而颜色来源于color.Gray来设置8bit灰度。
- fIm, err := os.Create("aaa.png")
-
- if nil != err{
- log.Fatal(err)
- }
-
- err = png.Encode(fIm, rgba)
-
- if nil != err{
- log.Fatal(err)
- }
png.Encode的功能把画板上的图画,生成图片aaa.png。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。