[TensorFlow]入门学习笔记(3)-图像预处理

图像预处理

前言

因为在做目标追踪方面,一直在matlab中写代码,不得不说改代码改的又复杂又难改,优化难做啊。就把图像预处理过程直接放到tensorflow中学习吧。

TFRecord数据格式

对于数据量较小而言,可能一般选择直接将数据加载进内存,然后再分batch输入网络进行训练(tip:使用这种方法时,结合yield 使用更为简洁,之前我一直用的这个方法)。
如果数据量较大,这样的方法就不适用了,因为太耗内存,所以这时最好使用tensorflow提供的队列queue,也就是第二种方法 从文件读取数据。对于一些特定的读取,比如csv文件格式,官网有相关的描述,在这儿我介绍一种比较通用,高效的读取方法(官网介绍的少),即使用tensorflow内定标准格式——TFRecords。这种方式也对图像文件比较友好,主要是图像的都比较大。

不多说,直接贴代码,有些写在注释里了。
读取TFRecord中的样例,以队列的形式。

#-*-encoding:UTF-8 -*-
import tensorflow as tf

#创建一个reader来读取TFRecord中的样例
reader = tf.TFRecordReader()

#创建一个临时队列用于维护输入文件列表
filename_queue = tf.train.string_input_producer(["path/to/output.tfrecords"])

#从文件中读取一个样例。read_up_to函数用于一次性读取多个样例
_,serialized_example = reader.read(filename_queue)
#解析读入的样例。如果需要解析多个样例,用parse_example
features = tf.parse_single_example(serialized_example,features={
    #TensorFlow提供了两种属性解析方法
    #1.tf.FixedLenFeature解析结果为Tensor.
    #2.tf.VarLenFeature,这种解析方法解析为一个SparseTensor,用于处理稀疏矩阵
    #格式需要与上面的写入数据的格式相一致
    'image_raw':tf.FixedLenFeature([],tf.string),
    'pixels':tf.FixedLenFeature([],tf.int64),
    'label':tf.FixedLenFeature([],tf.int64),
})

#tf.decode_raw将字符串解析为对应的像素数组
images = tf.decode_raw(features['image_raw'],tf.uint8)
labels = tf.cast(features['label'],tf.int32)
pixels = tf.cast(features['pixels'],tf.int32)

sess = tf.Session()
#启动多线程处理输入数据
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess,coord=coord)

#每次读取一个样例,当所有样例读取完之后,从头读取。
for i in range(10):
    image,label,pixel = sess.run([images,labels,pixels])

那么如何将已经存在的数据存储为TFRecord呢?
以mnist的数据集为例,

  • 获取你的数据
  • 将数据填入到Example协议内存块(protocol buffer)
  • 将数据中的信息feature写入这个结构
  • 之后,通过tf.python_io.TFRecordWriter 写入到TFRecords文件
# -*- coding: UTF-8 -*
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np

#生成整数型的属性
def _int64_feature(value):
    return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))

#生成字符串的属性
def _bytes_feature(value):
    return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))

mnist = input_data.read_data_sets("../MNIST_data/", dtype=tf.uint8,one_hot=True)
images = mnist.train.images
labels = mnist.train.labels
pixels = images.shape[1] #像素值可以作为Example的一个属性
num_examples = mnist.train.num_examples

#输出TFRecord文件的地址
filename = "path/to/output.tfrecords"

#创建一个writer来写TFRecord文件
writer = tf.python_io.TFRecordWriter(filename)
for index in range(num_examples):
    #将图像转化为字符串
    image_raw = images[index].tostring()
    #将一个样例转化为Example Protocol Buffer,并将所有信息写入这个结构
    example = tf.train.Example(features = tf.train.Features(feature={
        'pixels':_int64_feature(pixels),
        'label':_int64_feature(np.argmax(labels[index])),
        'image_raw':_bytes_feature(image_raw)
    }))
    #写入TFRecord
    writer.write(example.SerializeToString())

writer.close()

图像预处理

图像预处理有很多过程。这里只介绍函数。方便使用。

  • 图像读取原始
    • tf.gfile.FastGFile().read()
  • 图像格式的编码解码 :图像不直接记录图像上的不同位置,不同颜色的亮度。而是记录压缩编码之后的结果。所以要还原成三维矩阵,需要解码。
    • tf.image.decode_jpeg()
    • tf.image.encode_jpeg()
    • 转换函数 tf.image.convert_image_dtype
  • 图像大小调整
    • tf.image.resize_images(image,[size],method)
    • method 0:双线性插值 1:最近邻居法 2: 双三次插值法 3:面积差值法
    • tf.image.resize_image_with_crop_pad 自动裁剪或者填充
  • 图像翻转
    • tf.image.flip_up_down()
    • tf.image.filp_left_right()
    • tf.image.transpose_image()
  • 图像色彩调整
    • 亮度调整 tf.image.adjust_brightness(image,brightness)
    • 随机亮度调整 tf.image.random_brightness(image,max_delta)
    • 同理调整,tf.image.adjust_contrast,tf.image.adjust_hue,tf.image.
      saturation.
    • 图像标准化 tf.image.per_image_whitening(image)
  • 标注框

    • tf.image.draw_bounding_boxes(batch,boxes) 这个函数要求图像矩阵的数字为实数,而且输入是一个batch的数据,即多张图像组成的四维矩阵,所以将编码后的图像矩阵加一维。
    • tf.expand_dims() 这个加的维度大家自己要看api去理解
    • tf.image.sample_distorted_bounding_box(size,boxes) 随机截取图像信息

      随机翻转图像,随机调整颜色,随机截图图像中的有信息含量的部分,这些事提高模型健壮性的一种方式。这样可以使是训练得到的模型不受被识别物体大小的影响。
      下面贴出完整代码:

# -*- coding: UTF-8 -*
import tensorflow as tf

import numpy as np
import matplotlib.pyplot as plt

def distort_color(image,color_ordering=0):
    if color_ordering == 0:
        image = tf.image.random_brightness(image,max_delta=32./255.)#亮度
        image = tf.image.random_saturation(image,lower=0.5,upper=1.5)#饱和度
        image = tf.image.random_hue(image,max_delta=0.2)#色相
        image = tf.image.random_contrast(image,lower=0.5,upper=1.5)#对比度
    elif color_ordering == 1:
        image = tf.image.random_brightness(image, max_delta=32. / 255.)  # 亮度
        image = tf.image.random_hue(image, max_delta=0.2)  # 色相
        image = tf.image.random_saturation(image, lower=0.5, upper=1.5)  # 饱和度
        image = tf.image.random_contrast(image, lower=0.5, upper=1.5)  # 对比度
    return tf.clip_by_value(image,0.0,1.0) #将张量值剪切到指定的最小值和最大值

def preprocess_for_train(image,height,width,bbox):
    #如果没有提供标注框,则认为整个图像就是需要关注的部分
    if bbox is None:
        bbox = tf.constant([0.0,0.0,1.0,1.0],dtype=tf.float32,shape=[1,1,4])

    #转换图像张量的类型
    if image.dtype != tf.float32:
        image = tf.image.convert_image_dtype(image,dtype=tf.float32)

    #随机截取图像,减少需要关注的物体大小对图像识别的影响
    bbox_begin,bbox_size,_ = tf.image.sample_distorted_bounding_box(tf.shape(image),
                                                                    bounding_boxes=bbox)
    distort_image = tf.slice(image,bbox_begin,bbox_size)

    #将随机截图的图像调整为神经网络输入层的大小。大小调整的算法是随机的
    distort_image = tf.image.resize_images(
        distort_image,[height,width],method=np.random.randint(4)
    )
    #随机左右翻转图像
    distort_image = tf.image.random_flip_left_right(distort_image)
    #使用一种随机的顺序调整图像色彩
    distort_image = distort_color(distort_image,np.random.randint(1))
    return distort_image

image_raw_data = tf.gfile.FastGFile("../cat.jpg",'r').read()

with tf.Session() as Sess:
    ima_data = tf.image.decode_jpeg(image_raw_data)
    boxes = tf.constant([[[0.05,0.05,0.9,0.7],[0.35,0.47,0.5,0.56]]])

    #运行6次获得6中不同的图像,在图中显示效果
    for i in range(6):
        #将图像的尺寸调整为299*299
        result = preprocess_for_train(ima_data,299,299,boxes)

        plt.imshow(result.eval())
        plt.show()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值