通过对图像的预处理,可以避免模型受到无关因素的影响,可以提高模型的准确率。
图像编码处理
图像在存储时并不是直接记录图像矩阵中各个像素值,而是记录经过压缩编码之后的结果。将一张图像还原成矩阵,需要解码的过程。TF提供了对jpeg和png格式图像的编码/解码函数:
import matplotlib.pyplot as plt
import tensorflow as tf
#读取原始图像数据
image_raw_data = tf.gfile.FastGFile('picture.jpeg', 'rb').read()
with tf.Session() as sess:
#tf.image.decode_jpeg对jpeg图像进行解码
#tf.image.decode_png对png图像进行解码,结果均为一张量
img_data = tf.image.decode_jpeg(image_raw_data)
print(sess.run(img_data))
plt.imshow(sess.run(img_data))
plt.show()
#转换数据类型为实数方便处理
img_data = tf.image.convert_image_dtype(img_data, dtype=tf.float32)
#编码为jpeg格式
img_data = tf.image.convert_image_dtype(img_data, dtype=tf.uint16)
encode_img = tf.image.encode_jpeg(img_data)
with tf.gfile.FastGfile('picture_out.png', 'wb') as f:
f.write(sess.run(encode_img))
图像大小调整
图像大小的调整有两种方式,第一种是通过算法使得新的图像尽量保存原始图像上的信息。
#img_data是已经经过解码且进行类型转化的数据
#第二个第三个参数为调整后图像的大小
#method=0 采用双线性插值法
#method=1 采用最近邻居法
#method=2 采用双三次插值法
#method=3 采用面积插值法
resized = tf.image.resize_images(img_data, [300, 300], method=0)
TF也提供了对图像进行裁剪或填充的方法。
#通过tf.image.resize_image_with_crop_or_pad可以实现图像的裁剪和填充
#如果给定尺寸比原图大则填充,否则裁剪原图居中部分
croped = tf.image.resize_image_with_crop_or_pad(img_data, [1000, 1000])
padded = tf.image.resize_image_with_crop_or_pad(img_data, [3000, 3000])
另外tf.image.crop_to_bounding_box函数和tf.image.pad_to_bounding_box函数可以用来剪裁或填充给定区域的图像。
图像翻转
以下代码实现图像上下翻转、左右翻转以及对角线翻转。
fliped = tf.image.flip_up_down(img_data)
fliped = tf.image.flip_left_right(img_data)
transposed = tf.image.transpose_image(img_data)
通过随机翻转训练图像的方式可以使得训练得到的模型可以识别不同角度的实体:
fliped = tf.image.random_flip_up_down(img_data)
fliped = tf.image.random_flip_left_right(img_data)
图像色彩调整
#亮度-0.5 及 +0.5
adjusted = tf.image.adjust_brightness(img_data, -0.5)
adjusted = tf.image.adjust_brightness(img_data, +0.5)
#在[-x,x]范围内随机调整亮度
adjusted = tf.image.random_brightness(img_data, x)
#对比度-0.5 及 +0.5
adjusted = tf.image.adjust_contrast(img_data, -0.5)
adjusted = tf.image.adjust_contrast(img_data, +0.5)
#在[x,y]范围内随机调整对比度
adjusted = tf.image.random_contrast(img_data, x, y)
#色相 +0.1 及 +0.5
adjusted = tf.image.adjust_hue(img_data, 0.1)
adjusted = tf.image.adjust_hue(img_data, 0.5)
#在[-x,x]范围内随机调整色相
adjusted = tf.image.random_hue(img_data, x)
#饱和度 -0.5 及 +0.5
adjusted = tf.image.adjust_saturation(img_data, -0.5)
adjusted = tf.image.adjust_saturation(img_data, 0.5)
#在[-x,x]范围内随机调整饱和度
adjusted = tf.image.random_saturation(img_data, x, y)
#将图像变为均值为0方差为1的图像(二值图?)
adjusted = tf.image.per_image_standardization(img_data)
处理标注框
TF提供了一些工具来标注图像中需要关注的物体,使用tf.image.draw_bounding_boxes可以在图像中加入标注框。
img_data = tf.image.resize_images(img_data, [108, 192], method=0)
#由于tf.image.draw_bounding_boxes函数输入图像为一个四维矩阵,所以解码之后要加一维,其中第一维度表示第几张图片
batched = tf.expand_dims(tf.image.convert_image_dtype(img_data, tf.float32), 0)
#给出图像的标注框,一个标注框有四个数字,分别代表[ymin,xmin,ymax,xmax],其中数字都代表其相对位置
boxes = tf.constant([[[0.1, 0.2, 0.9, 0.7], [0.35, 0.47, 0.5, 0.56]]])
result = tf.image.draw_bounding_boxes(batched, boxes)
plt.imshow(sess.run(result[0]))
plt.show()
另外,也可以通过tf.image.sample_distorted_bounding_box函数实现图像的随机截取,这样可以提高模型的robustness,不受被识别物体大小的影响。
boxes = tf.constant([[[0.1, 0.2, 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(tf.image.convert_image_dtype(img_data, tf.float32), 0)
#绘制标注框
image_with_box = tf.image.draw_bounding_boxes(batched, bbox_for_draw)
#提取截图切片
distorted_image = tf.slice(img_data, begin, size)