Tensorflow学习笔记----图像预处理

图像预处理

通过对图像的预处理,可以尽量避免模型受到无关因素的影响。在大部分图像识别问题中,通过图像预处理过程可以提高模型的准确率

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

  • 图像读取原始 
    • 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:面积差值法
    • 对于图像缩放算法来说,最近临插值算法是最简单的。最近临插值算法的原理是在原图像中找到最近临的一个点,然后把这个点的像素值插入到目标图像中,最近临插值算法优点是算法简单,易于实现,但是缺点是由于相邻像素点的像素值相同,容易出现色块现象。
    • 那么如何在原图像中找这个目标点呢,算法公式如下:

      src_x = dst_x * (src_width / dst_width);
      src_y = dst_y * (src_height / dst_height);
      

      那么算出来呢,可能会是小数点,需要四舍五入取整,那么下面来看一个例子(一个3*3的矩阵):

      234     38      22
      67      44      12
      89      65      63
      

      这里呢,我们需要将上面的一个3*3矩阵变换成一个4*4的矩阵,我们根据上面的公式来计算一下,首先是目标点为(0,0),那么原图像的坐标点为(0,0),那么这个坐标点的值就应该为234,然后再来看(0,1)这个坐标点,那么纵坐标点还是0,但是横坐标点变成了1*(3/4) = 0.75,四舍五入得1,那么得到的原图像坐标为(0,1),那么这个坐标点值就应该为38,同理,最后得到的矩阵结果如下:

      234	38	22	22	
      67	44	12	12	
      89	65	63	63	
      89	65	63	63
    • 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) 随机截取图像信息

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

'''编码与解码
图像解码与编码:一张RGB三通道的彩色图像可以看成一个三维矩阵,矩阵中的不位置上的数字代表图像的像素值。
然后图像在存储时并不是直接记录这些矩阵中的数字,而是经过了压缩编码。
所以将一张图像还原成一个三维矩阵的过程就是解码的过程,反之就是编码了。
其实如果大家熟悉opencv的话,imread和imwrite就是一个解码和编码的过程。
TensorFlow提供了常用图片格式的解码和编码操作,下面用一个jpeg的图像演示:'''
import matplotlib.pyplot as plt
import tensorflow as tf
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签

#tf.gfile.FastGFile读取或保存图像文件
image_raw_data = tf.gfile.FastGFile("lena.jpeg",'rb').read()

with tf.Session() as sess:    #图形解码(可以解码jpeg, png,编码为encode_jpeg)
    img_data = tf.image.decode_jpeg(image_raw_data)
    print(img_data.eval())
    plt.imshow(img_data.eval())
    plt.title('原图')
    plt.show()

#图像大小调整
import numpy as np
with tf.Session() as sess:
    #设定图片大小,method有4种插值,0-双线性插值 1-最近邻居法 2-双三次插值法 3-面积差值法
    resized = tf.image.resize_images(img_data, [300, 300], method=0)
    print("Digital dtype: %s" % resized.dtype)
    # TensorFlow的函数处理图片后存储的数据是float32格式的,需要转换成uint8才能正确打印图片。
    lena = np.asarray(resized.eval(), dtype="uint8")
    print(resized.get_shape())
    plt.imshow(lena)
    plt.title('调整大小到[300,300]')
    plt.show()


#图形剪切或填充
with tf.Session() as sess:
    #自动裁剪或者填充(都是操作图片中间部分)
    croped = tf.image.resize_image_with_crop_or_pad(img_data, 300,200)
    padded = tf.image.resize_image_with_crop_or_pad(img_data, 700, 500)
    # 按比例调整图像大小,第二个参数为(0,1]的实数。
    center_crop=tf.image.central_crop(img_data, 0.5)
    #裁剪给定区域{起点高度,起点宽度,框高,框宽}
    crop_to_bounding_box=tf.image.crop_to_bounding_box(img_data,0,0,200,300)
    plt.imshow(croped.eval())
    # 填充给定区域
    pad_to_bounding_box=tf.image.pad_to_bounding_box(img_data,0,0,200,300)

    plt.title('cropped')
    plt.show()
    plt.imshow(padded.eval())
    plt.title('padded')
    plt.show()
    plt.imshow(center_crop.eval())
    plt.title('center_crop')
    plt.show()
    plt.imshow(crop_to_bounding_box.eval())
    plt.title('crop_to_bounding_box')
    plt.show()
    plt.imshow(pad_to_bounding_box.eval())
    plt.title('pad_to_bounding_box')
    plt.show()




#图形翻转变换
with tf.Session() as sess:
    #上下翻转
    flipped = tf.image.flip_up_down(img_data)
    #左右反转
    flipped1 = tf.image.flip_left_right(img_data)
    #对角翻转
    transposed = tf.image.transpose_image(img_data)

    plt.imshow(flipped.eval())
    plt.title('上下翻转')
    plt.show()
    plt.imshow(flipped1.eval())
    plt.title('左右反转')
    plt.show()
    plt.imshow(transposed.eval())
    plt.title('对角翻转')
    plt.show()


#调整亮度
with tf.Session() as sess:
    #亮度调整
    adjusted = tf.image.adjust_brightness(img_data, -0.5)
    adjusted1 = tf.image.adjust_brightness(img_data, 0.5)
    #随机亮度调整
    adjusted2 = tf.image.random_brightness(img_data, max_delta=0.5)

    plt.imshow(adjusted.eval())
    plt.title('亮度调整-0.5')
    plt.show()
    plt.imshow(adjusted1.eval())
    plt.title('亮度调整+0.5')
    plt.show()
    plt.imshow(adjusted2.eval())
    plt.title('随机亮度调整')
    plt.show()



#调整对比度
with tf.Session() as sess:
    #对比度调整
    adjusted = tf.image.adjust_contrast(img_data, -5)
    adjusted1 = tf.image.adjust_contrast(img_data, 5)
    #随机调整对比度
    adjusted2 = tf.image.random_contrast(img_data, 0,5)

    plt.imshow(adjusted.eval())
    plt.title('对比度-5')
    plt.show()
    plt.imshow(adjusted1.eval())
    plt.title('对比度+5')
    plt.show()
    plt.imshow(adjusted2.eval())
    plt.title('对比度随机调整,在[-max_delta,max_delta]范围内')
    plt.show()


#调整色相
with tf.Session() as sess:
    # 在[-maxdelta,maxdelta]范围内随机调整图像的色相 maxdelat 在0-0.5的范围内
    adjusted3 = tf.image.random_hue(img_data, max_delta=0.4)

    plt.imshow(adjusted.eval())
    plt.title('调整色相')
    plt.show()

 
 
#调整饱和度
with tf.Session() as sess:
    adjusted = tf.image.adjust_saturation(img_data, -5)
    adjusted1 = tf.image.adjust_saturation(img_data, 5)
    adjusted2 = tf.image.random_saturation(img_data,3,7)

    plt.imshow(adjusted2.eval())
    plt.title('调整饱和度')
    plt.show()

 
 
#处理标注框
with tf.Session() as sess:
    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(tf.image.convert_image_dtype(img_data, tf.float32), 0)
    image_with_box = tf.image.draw_bounding_boxes(batched, bbox_for_draw)


    plt.imshow(image_with_box[0].eval())
    plt.title('通过标注框可视化随机截取得到的图像')
    plt.show()
    # 截取随机出来的图像,因为算法带有随机成分,所以每次的结果都可能不相同
    distorted_image = tf.slice(img_data, begin, size)
    plt.imshow(distorted_image.eval())
    plt.title('截取出来的图像')
    plt.show()





猜你喜欢

转载自blog.csdn.net/weixin_39881922/article/details/80056487