【TensorFlow】数据处理(对图像的处理)

项目已上传至 GitHub —— img-pre

 

目录结构


images 文件夹下存放将被用于处理的图像,img_all.py 示范了 TensorFlow 中图像处理函数的使用方法,img_pre.py 给出了一个对图像进行预处理的程序示例

img-pre/
    images/
        1.jpg
    img_all.py
    img_pre.py
  • 1
  • 2
  • 3
  • 4
  • 5

图像处理函数


编码处理

在使用图像之前需要先对图像进行解码,将图像转为像素矩阵,tensorflow.image 提供了图像解码函数,返回的矩阵数据类型是 uint8

  • decode_jpeg:解码 JPEG 格式图像
  • decode_and_crop_jpeg:解码并裁剪 JPEG 格式图像
  • decode_png:解码 PNG 格式图像
  • decode_gif:解码 GIF 格式图像
  • decode_bmp:解码 BMP 格式图像
  • decode_image:自动检测图像格式进行解码,注意 GIF 格式图像返回一个四维矩阵

以下代码示范对 JPEG 格式图像的解码处理

import tensorflow as tf
import matplotlib.pyplot as plt

# 读取图像的原始数据
image_raw_data = tf.gfile.FastGFile('images/1.jpg', 'rb').read()


# 使用pyplot显示图像
def show(img_data):
    plt.imshow(img_data.eval())
    plt.show()


with tf.Session() as sess:
    # 将原始数据解码成多维矩阵
    img_data = tf.image.decode_jpeg(image_raw_data)
    print(img_data.eval())
    show(img_data)

    # 将图像的矩阵编码成图像并存入文件
    encoded_image = tf.image.encode_jpeg(img_data)
    with tf.gfile.GFile('images/output.jpg', 'wb') as f:
        f.write(encoded_image.eval())

    # 将图像数据的类型转为实数类型,便于对图像进行处理
    img_data = tf.image.convert_image_dtype(img_data, dtype=tf.float32)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

大小调整

tf.image.resize_images 函数中有四种调整图像的方法,结果会有细微差别

method图像大小调整算法
0双线性插值法(Bilinear interpolation)
1最近邻居法(Nearest neighbor interpolation)
2双三次插值法(Bicubic interpolation)
3面积插值法(Area interpolation)


以下代码都是在图像编码处理代码的基础下运行,省去了加载原始图像,定义会话等过程

    # 用resize_images调整图像大小
    # 第一个参数为原始图像
    # 第二个参数为调整后的图像大小[new_height,new_width],跟旧版本分为两个参数不一样
    # method参数给出了调整图像大小的算法
    resized = tf.image.resize_images(img_data, [300, 300], method=0)
    print(resized.get_shape())  # 图像深度没有显式指定则为问号
    show(resized)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

还可以通过 resize_image_with_crop_or_pad 函数对图像进行裁剪或填充

    # 用resize_image_with_crop_or_pad调整图像大小
    # 第一个参数为原始图像
    # 第二个和第三个参数是调整后的图像大小,大于原图则填充,小于则裁剪居中部分
    croped = tf.image.resize_image_with_crop_or_pad(img_data, 200, 200)
    show(croped)
    padded = tf.image.resize_image_with_crop_or_pad(img_data, 500, 600)
    show(padded)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

还支持通过比例裁剪图像

    # 用central_crop调整图像大小
    # 第一个参数是原始图像
    # 第二个参数为调整比例,是(0,1]的实数
    central_cropped = tf.image.central_crop(img_data, 0.5)
    show(central_cropped)
  • 1
  • 2
  • 3
  • 4
  • 5

图像翻转

以下代码示范了将图像进行上下翻转、左右翻转及沿对角线翻转

    # 图像翻转
    flipped = tf.image.flip_up_down(img_data)  # 上下
    show(flipped)
    flipped = tf.image.flip_left_right(img_data)  # 左右
    show(flipped)
    transposed = tf.image.transpose_image(img_data)  # 对角线
    show(transposed)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

还可以随机翻转图像

    # 随机翻转图像
    flipped = tf.image.random_flip_up_down(img_data)  # 随机上下
    show(flipped)
    flipped = tf.image.random_flip_left_right(img_data)  # 随机左右
    show(flipped)
  • 1
  • 2
  • 3
  • 4
  • 5

色彩调整

图像的色彩调整有四方面

  • 亮度
  • 对比度
  • 饱和度
  • 色相

修改图像的亮度

    # 调整图像的亮度
    adjusted = tf.image.adjust_brightness(img_data, 0.5)  # 将图像的亮度+0.5
    show(adjusted)
    adjusted = tf.image.random_brightness(
        img_data, max_delta=0.5)  # 在[-0.5,0.5]范围内随机调整图像亮度
    show(adjusted)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

修改图像的对比度

    # 调整图像的对比度
    adjusted = tf.image.adjust_contrast(img_data, -5)  # 将图像的对比度-5
    show(adjusted)
    adjusted = tf.image.adjust_contrast(img_data, 5)  # 将图像的对比度+5
    show(adjusted)
    adjusted = tf.image.random_contrast(img_data, lower=-5, upper=5)  # 随机调整对比度
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

修改图像的饱和度

    # 调整图像的饱和度
    adjusted = tf.image.adjust_saturation(img_data, -5)  # 将饱和度-5
    show(adjusted)
    adjusted = tf.image.adjust_saturation(img_data, 5)  # 将饱和度+5
    show(adjusted)
    adjusted = tf.image.random_saturation(image, lower=-5, uppper=5)  # 随机调整饱和度
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

调整图像的色相

    # 调整图像的色相
    adjusted = tf.image.adjust_hue(img_data, 0.5)  # 将色相+0.5
    show(adjusted)
    adjusted = tf.image.random_hue(img_data, max_delta=0.5)  # 随机调整色相
    show(adjusted)
  • 1
  • 2
  • 3
  • 4
  • 5

处理标注框

以下代码示范了如何在图像中加入标注框

    # 用draw_bounding_boxes加入标注框
    # 要求图像矩阵类型为实数
    # 输入是一个batch的数据,也就是多张图像,所以需要加一维
    batched = tf.expand_dims(img_data, 0)
    boxes = tf.constant([[[0.05, 0.05, 0.9, 0.7], [0.35, 0.47, 0.5,
                                                   0.56]]])  # 代表图像的相对位置
    result = tf.image.draw_bounding_boxes(batched, boxes)
    show(result)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

还能通过 sample_distorted_bounding_box 函数来随机截取图像

    # 用sample_distorted_bounding_box随机截取图像
    boxes = tf.constant([[[0.05, 0.05, 0.9, 0.7], [0.35, 0.47, 0.5, 0.56]]])
    begin, size, bbox_for_draw = tf.image.sample_distorted_bounding_box(
        tf.shape(img_data), bounding_boxes=boxes)  # 通过标注框告诉算法有信息量的部分
    batched = tf.expand_dims(img_data, 0)
    image_with_box = tf.image.draw_bounding_boxes(batched, bbox_for_draw)
    distorted_image = tf.slice(img_data, begin, size)
    show(distorted_image)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

图像预处理示例


该代码实现自《TensorFlow:实战Google深度学习框架》

img_pre.py 这个示例给出了如何在程序中对图像进行预处理,从而降低不相关因素对训练模型的影响

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.0)
        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.0)
        image = tf.image.random_hue(image, max_delta=0.2)
        image = tf.image.random_contrast(image, lower=0.5, upper=1.5)
        image = tf.image.random_saturation(image, lower=0.5, upper=1.5)
    elif color_ordering == 2:
        # 一共可以有24种排列情况
        pass
    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, min_object_covered=0.1)
    distorted_image = tf.slice(image, bbox_begin, bbox_size)

    # 将随机截取的图像调整为输入层的大小
    distorted_image = tf.image.resize_images(
        distorted_image, size=[height, width], method=np.random.randint(4))

    # 随机左右翻转图像
    distorted_image = tf.image.random_flip_left_right(distorted_image)

    # 使用一种随机顺序调整图像色彩
    distorted_image = distort_color(distorted_image, np.random.randint(2))
    return distorted_image


image_raw_data = tf.gfile.FastGFile('images/1.jpg', 'rb').read()
with tf.Session() as sess:
    img_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]]])
    for i in range(6):
        result = preprocess_for_train(img_data, 300, 300, boxes)
        plt.imshow(result.eval())
        plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

原书中的函数版本有些落后,有些函数会报错

  1. tf.image.sample_distorted_bounding_box()

    
    # 旧版本
    
    bbox_begin,bbox_size,bbox_for_draw=tf.image.sample_distorted_bounding_box(tf.shape(image),bounding_boxes=bbox)
    
    # 新版本
    
    bbox_begin,bbox_size,bbox_for_draw=tf.image.sample_distorted_bounding_box(tf.shape(image),bounding_boxes=bbox,min_object_covered=0.1)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果不显式给 min_object_covered 参数就会报错

    ValueError: Tried to convert ‘min_object_covered’ to a tensor and failed. Error: None values not supported. 
    • 1
  2. tf.image.resize_images()

    
    # 旧版本
    
    distorted_image=tf.image.resize_images(distorted_image,height,width,method=method)
    
    # 新版本
    
    distorted_image = tf.image.resize_images(distorted_image, size=[height, width], method=method)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果不将 size 写为 size=[height,width] 的形式就会报错

    TypeError: resize_images() got multiple values for argument ‘method’

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值