2021-09-26


读取图片文件

# 有三种获取数据到TensorFlow程序的方法:
# 1. QueueRunner:基于队列的输入管道从TensorFlow图形开头的文件中读取数据。
# 2.Feeding:运行每一步时,Python代码提供数据。
# 3.预加载数据:TensorFlow图中的张量包含所有数据(对于小数据集)。

文件读取流程:

第一阶段构造文件名队列

第二阶段读取与解码

第三阶段批处理 注:这些操作需要启动运行这些队列操作的线程,以便我们在进行文件读取的过程中能够顺利进行入队出队操作。
在这里插入图片描述
一般数据文件格式有文本、excel和图片数据。那么TensorFlow都有对应的解析函数,除了这几种。还有TensorFlow指定的文件格式

# 3.1 文件读取流程
#     多线程 + 队列
#     3.1.1 文件读取流程
#         1)构造文件名队列
#             file_queue = tf.train.string_input_producer(string_tensor,shuffle=True)
#         2)读取与解码
#             文本:
#                 读取:tf.TextLineReader()
#                 解码:tf.decode_csv()
#             图片:
#                 读取:tf.WholeFileReader()
#                 解码:
#                     tf.image.decode_jpeg(contents)
#                     tf.image.decode_png(contents)
#             二进制:
#                 读取:tf.FixedLengthRecordReader(record_bytes)
#                 解码:tf.decode_raw()
#             TFRecords
#                 读取:tf.TFRecordReader()
#             key, value = 读取器.read(file_queue)
#             key:文件名
#             value:一个样本
#         3)批处理队列
#             tf.train.batch(tensors, batch_size, num_threads = 1, capacity = 32, name=None)
#         手动开启线程
#             tf.train.QueueRunner()
#             开启会话:
#                 tf.train.start_queue_runners(sess=None, coord=None)

1.文件队列生成函数

tf.train.string_input_producer(string_tensor, num_epochs=None, shuffle=True, seed=None, capacity=32, name=None)
string_tensor:含有文件名+路径的1阶张量 [这里传一个文件路径列表就可以]
num_epochs:过几遍数据,默认无限过数据 [一直过道训练出你满意的结果,无线循环,结果会越来越拟合]
return文件队列

产生指定文件张量

2.文件阅读器类

class tf.TextLineReader
阅读文本文件逗号分隔值(cSV)格式,默认按行读取
return:读取器实例

阅读文本文件逗号分隔值(CSV)格式

tf.FixedLengthRecordReader
return:读取器实例
tf.FixedLengthRecordReader(record_bytes):二进制文件
要读取每个记录是固定数量字节的二进制文件
record_bytes:整型,指定每次读取(一个样本)的字节数o return:读取器实例

要读取每个记录是固定数量字节的二进制文件

tf.TFRecordReader
读取TFRecords文件

return:读取器实例

解码

2)内容解码 读取不同类型的文件,也应该对读取到的不同类型的内容进行相对应的解码操作,解码成统一的Tensor格式

tf.decode_csv:解码文本文件内容
tf.image.decode _jpeg(contents)
将JPEG编码的图像解码为uint8张量
return:uint8张量,3-D形状[height, width, channels]
tf.image.decode_png(contents)
将PNG编码的图像解码为uint8张量
return:张量类型,3-D形状[height, width, channels]
tf.decode_raw:解码二进制文件内容
与tf.FixedLengthRecordReader搭配使用,二进制读取为uint8类型

将CSV转换为张量,与tf.TextLineReader搭配使用

tf.decode_raw(bytes,out_type,little_endian = None,name = None

将字节转换为一个数字向量表示,字节为一字符串类型的张量,与函数tf.FixedLengthRecordReader搭配使用

# 读取CSV格式文件
# 1、构建文件队列

# 2、构建读取器,读取内容

# 3、解码内容

# 4、现读取一个内容,如果有需要,就批处理内容
import tensorflow as tf
import os
def readcsv_decode(filelist):
    # 把文件目录和文件名合并
    flist = [os.path.join("./csvdata/",file) for file in filelist]

    # 构建文件队列
    file_queue = tf.train.string_input_producer(flist,shuffle=False)

    # 构建阅读器,读取文件内容
    reader = tf.TextLineReader()

    key,value = reader.read(file_queue)

    record_defaults = [["null"],["null"]] # [[0],[0],[0],[0]]

    # 解码内容,按行解析,返回的是每行的列数据
    example,label = tf.decode_csv(value,record_defaults=record_defaults)

    # 通过tf.train.batch来批处理数据
    example_batch,label_batch = tf.train.batch([example,label],batch_size=9,num_threads=1,capacity=9)


    with tf.Session() as sess:

        # 线程协调员
        coord = tf.train.Coordinator()

        # 启动工作线程
        threads = tf.train.start_queue_runners(sess,coord=coord)

        # 这种方法不可取
        # for i in range(9):
        #     print(sess.run([example,label]))

        # 打印批处理的数据
        print(sess.run([example_batch,label_batch]))


        coord.request_stop()

        coord.join(threads)

    return None


if __name__=="__main__":
    filename_list = os.listdir("./csvdata")
    readcsv_decode(filename_list)

图片数据
组成一张图片特征值是所有的像素值,有这么几个要素。图片长度、图片宽度、图片通道数。什么是图片的通道数呢,描述一个像素点,如果是灰度,那么只需要一个数值来描述它,就是单通道。如果一个像素点,有RGB三种颜色来描述它,就是三通道。那所以灰度图片:单通道;彩色图片:三通道
假设一张彩色图片的长200,宽200,通道数为3,那么总的像素数量为200x200x3
张量形状

读取图片之后,怎么用张量形状来表示呢。一张图片就是一个3D张量,[height, width, channel],height就表示高,width表示宽,channel表示通道数。我们会经常遇到3D和4D的表示

单个图片:[height, width, channel]
多个图片(4D):[batch, height, width, channel],batch表示批数量

图片特征值处理

在进行图片识别的时候,每个图片样本的特征数量要保持相同(方便神经网络的训练)。所以需要将所有图片张量大小统一转换。另一方面如果图片的像素量太大,也可以通过这种方式适当减少像素的数量,减少训练的计算开销

tf.image.resize_images(images, size)
缩小放大图片
images:4-D形状[batch, height, width, channels],或3-D形状的张量[height, width, channels]的图片数据
size:1-D int32张量:new_height, new_width,图像的新尺寸
返回4-D格式或者3-D格式图片

数据格式

存储:uint8(节约空间)
矩阵计算:float32(提高精度)

import tensorflow as tf
import os


def picture_read(filename_list):
    # 1. 构造文件名队列
    file_queue = tf.train.string_input_producer(filename_list)

    # 2. 读取与解码
    reader = tf.WholeFileReader()
    # key 文件名 value 一张图片的原始编码形式
    key, value = reader.read(file_queue)

    # 解码阶段
    image = tf.image.decode_jpeg(value)
    # 图像的形状类型修改,改成统一的宽高
    image_resized = tf.image.resize_images(image, [200, 200])
    # 静态形状修改,添加通道数
    image_resized.set_shape(shape=[200, 200, 3])
    image_batch = tf.train.batch([image_resized], batch_size=10, num_threads=1, capacity=100)
    print(image_batch)
    with tf.Session() as sess:
        # 开启县城
        # 线程协调员
        coord = tf.train.Coordinator()
        threads = tf.train.start_queue_runners(sess=sess, coord=coord)
        print(image_resized.shape)
        print(image_resized.eval())
        # 回收线程
        coord.request_stop()
        coord.join(threads)


if __name__ == "__main__":
    # 构造路径+ 文件名列表
    filename = os.listdir("dog")

    filename_list = [os.path.join('dog', i) for i in filename]
    picture_read(filename_list)

二进制文件

import tensorflow as tf
import os


class Cifar():

    def __init__(self):
        # 设置图像大小
        self.height = 32
        self.width = 32
        self.channel = 3

        # 设置图像字节数 一张图片大小 是 3*32*32
        self.image = self.height * self.width * self.channel
        self.label = 1
        self.sample = self.image + self.label

    def read_and_decode(self, file_list):
        # 1. 构造文件名队列
        file_queue = tf.train.string_input_producer(file_list)

        # 2. 读取与解码
        reader = tf.FixedLengthRecordReader(self.sample)
        # key 文件名  value 一个样本
        key, value = reader.read(file_queue)
        # 解码阶段
        decoded = tf.decode_raw(value, tf.uint8)  # 得到一张图片的label数字和三通道数字 [1+ 3*32*32] 一维张量
        # 把目标值和特征值切开
        label = tf.slice(decoded, [0], [self.label])
        image = tf.slice(decoded, [self.label], [self.image])
        # 调整图片形状
        image_reshaped = tf.reshape(image, shape=[self.channel, self.height, self.width])  # 3*32*32
        # 但是tensorflow 的世界里想要 32*32*3这种形式的图片  我们要把这个三维张量的坐标轴转换一下
        image_transposed = tf.transpose(image_reshaped, [1, 2, 0])  # 32*32 *3
        # 调整图像类型
        image_cast = tf.cast(image_transposed, dtype=tf.float32)

        # 3.批处理
        label_batch, image_batch = tf.train.batch([label, image_cast], batch_size=100, num_threads=1, capacity=100)

        with tf.Session() as sess:
            coord = tf.train.Coordinator()
            threads = tf.train.start_queue_runners(sess=sess, coord=coord)

            key_new, value_new = key.eval(), value.eval()
            print("key_new:\n", key_new)
            print("value_new:\n", value_new)
            label_value, image_value = label_batch.eval(), image_batch.eval()
            # 回收线程
            coord.request_stop()
            coord.join(threads)

        return label_value, image_value


if __name__ == "__main__":
    cifar = Cifar()
    file_name = os.listdir('cifar-10-batches-bin')
    # 构造问及高明路径列表
    file_list = [os.path.join('cifar-10-batches-bin', file) for file in file_name if file[-3:] == 'bin']

    cifar.read_and_decode(file_list)

TFRecords文件读取

TFRecords其实是一种二进制文件,虽然它不如其他格式好理解,但是它能更好的利用内存,更方便复制和移动,并且不需要单独的标签文件。

使用步骤︰

1)获取数据 2)将数据填入到 Example协议内存块(protocol buffer) 3)将协议内存块序列化为字符串,并且通过 tf.python_io.TFRecordwriter写入到TFRecords文件。

文件格式 *.tfrecords

import tensorflow as tf


def read_tfrecords():
    # 1. 构造文件名队列
    file_queue = tf.train.string_input_producer(["cifar10.tfrecords"])

    # 读取和解码
    # 读取
    reader = tf.TFRecordReader()
    key, value = reader.read(file_queue)

    # 解析example

    feature = tf.parse_single_example(value, features={
        "image": tf.FixedLenFeature([], tf.string),
        "label": tf.FixedLenFeature([], tf.int64)  # 这里的数据类型要与之前创建的时候保持一直
    })

    image = feature["image"]  # 图片是二进制,要解码成张量[32,32,3]

    label = feature["label"]

    # 解码成一维张量
    image_decode = tf.decode_raw(image, tf.float32) # 这里的数据类型一定要与之前一致是tf.float32 教程里是uint 8 搞混了,总之一定要跟以前一样,否则形状转化不来

    # 改变形状
    img_reshaped = tf.reshape(image_decode, [32, 32, 3])
    # 解码
     # 3. 构造批处理队列
    image_batch, label_batch = tf.train.batch([img_reshaped, label], batch_size=2, num_threads=2, capacity=100)
    print("image_batch", image_batch)
    print('label_batch:', label_batch)
    # 开启回话
    with tf.Session() as sess:
        # 开启县城
        coord = tf.train.Coordinator()
        threads = tf.train.start_queue_runners(sess=sess, coord=coord)
        for i in range(4):
        # print(img_reshaped.eval())
            print('第%d批label:'%(i+1),label_batch.eval())
        # 回收资源
        coord.request_stop()
        coord.join(threads)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值