1. 程式人生 > >tensorflow資料增強

tensorflow資料增強

    相信大家都聽說過資料增強(Data Augmentation),這是在做神經網路時非常極其重要的trick, 因為資料是寶貴的,稀有的,通過資料增強我們能讓我們的資料量迅速增大,並且能使訓練的模型具有一定抗噪能力。這篇文章主要探討一下 tensorflow 關於資料增強的API.
    先讀取圖片資料, 並輸出我們的圖片資訊
import numpy as np
from PIL import Image

# #***************案例1*numpy讀取圖片資料**********************#
img = Image.open("5.jpg", 'r')
img.show()
a = np.asarray(img, 
dtype=float) print(img.mode) # output RGB (1601, 1002)
沒錯,就是一個漂亮的小姐姐,hh

        再先來個題外話,叫做 圖片資料的編碼, tensorflow能支援的格式不多, jpg,png,gif,bmp這些常用格式倒是可以的,如果你的圖片格式是很特殊的格式的話, 恐怕你就需要用其他處理方式先進行預處理了, 比如常用的醫學影象 .nii格式 你就需要用nibable, 一些tiff,DICOM,等你可能可以用 PIL,cv2,openslide , libvips等等。
# ***# 讀取圖片,進行圖片解碼
# 讀取影象的原始資料 返回值:
<class 'bytes'> # 也就是讀取圖片,將其轉換成一串二進位制串 image_raw_data = tf.gfile.FastGFile("5.jpg", 'rb').read() with tf.Session() as sess: # img_data--> <class 'tensorflow.python.framework.ops.Tensor'> img_data = tf.image.decode_jpeg(image_raw_data) print(img_data.eval()) # RGB模式輸出一個三維陣列
# py_plot展示圖片 plt.imshow(img_data.eval()) plt.show() # 將資料型別轉化為uint8 img_data = tf.image.convert_image_dtype(img_data, dtype=tf.uint8) # ***# 讀取資料,進行圖片編碼 encoded_image = tf.image.encode_png(img_data) with tf.gfile.GFile("6.png", 'wb') as f: f.write(encoded_image.eval())

        接下來我們就一個個來看看,首先讀取圖片資料,並轉化成float32

image_raw_data = tf.gfile.FastGFile("5.jpg", 'rb').read()  # 500x500
with tf.Session() as sess:
    # img_data--> <class 'tensorflow.python.framework.ops.Tensor'>
img_data = tf.image.decode_jpeg(image_raw_data)
    img_data = tf.image.convert_image_dtype(img_data, dtype=tf.float32)
 
print(type(img_data) # class 'tensorflow.python.framework.ops.Tensor'>

(一)調整圖片大小resize

    一般來說網路上的影象大小不確定,但是神經網路的輸入節點的個數是固定的。所以與處理是需要統一圖片大小

    調整大小方法有以下幾個:
    # 1、雙線性插值法
    # 2、最近鄰居法
    # 3、雙三次插值法
    # 4、面積插值法

resize_img = tf.image.resize_images(img_data, [300, 300], method=0)  # 一共提供了四種方法
# <class 'tensorflow.python.framework.ops.Tensor'>
plt.imshow(resize_img.eval())
plt.show()

# 0代表ResizeMethod.BILINEAR,依次類推

  輸出結果:

(二)圖片剪下填充

# 放大圖片就自動周圍填充黑色;縮小圖片就自動從圖片中間剪下
resize_img = tf.image.resize_image_with_crop_or_pad(img_data, 600, 600)
plt.imshow(resize_img.eval())
plt.show()



    輸出結果:

    (三)圖片按比例大小縮小圖片(也是一種剪下,類似上一種方式)

central_cropped = tf.image.central_crop(img_data, 0.5)  
plt.imshow(central_cropped.eval())
plt.show()

    輸出結果:

    

    (四)方框剪下

# # bounding_box_crop
# # similar func:tf.image.pad_to_bounding_box
# 圖片(0 0)位置在左上角, (50,50)指heightwidth在圖片左上角的偏移量
resize_img = tf.image.crop_to_bounding_box(img_data, 50, 50, 300, 300)

    (五)翻轉以及隨機翻轉

# #影象翻轉# 資料增強
# 上下翻轉、左右翻轉、對角線翻轉
# tf.image.transpose_image(img_data)
    # tf.image.flip_left_right(img_data)
flip_img = tf.image.flip_up_down(img_data)
    plt.imshow(flip_img.eval())
    plt.show()
    # 隨機翻轉 推薦應用這個方法
# 隨機上下左右、亮度、對比度、色相、飽和度
# tf.image.random_flip_up_down(img_data)
    # tf.image.random_brightness()
    # tf.image.random_contrast()
    # tf.image.random_hue()
    # tf.image.random_saturation()
rand_flip_img = tf.image.random_flip_left_right(img_data, seed=1)
    plt.imshow(rand_flip_img.eval())
    plt.show()

    (六)影象色彩調整(五 中包含了一些色彩調整函式,不過是隨機的就直接列在上面了,方便大家總結理解)

# 調整圖片亮度、對比度、gamma、色相、飽和度
# tf.image.adjust_contrast()
# tf.image.adjust_gamma()
# tf.image.adjust_hue()
# tf.image.adjust_saturation()
adjust_img = tf.image.adjust_brightness(img_data, -0.5)
# 將圖片亮度變為均值為0,方差為1
adjust_img = tf.image.per_image_standardization(img_data)
print(img_data.eval())

    (七)影象標註

# # tf.image.draw_bounding_boxes函式的輸入是一個batch的資料,也就是
#   多張影象組成的四維矩陣
#   第一個輸入引數img_data中資料型別應該是實數,前面最初已經轉換成了tf.float32
batched = tf.expand_dims(img_data, 0)
#  [0.2, 0.3, 0.5, 0.8]給出的是影象中的相對位置 [y_min, x_min, y_max, x_max]
boxes = tf.constant([[[0.2, 0.3, 0.48, 0.65]]])
res = tf.image.draw_bounding_boxes(batched, boxes, name='bounding_box')
plt.subplot(121), plt.imshow(img_data.eval()), plt.title('original')
plt.subplot(122), plt.imshow(np.asarray(res.eval())[0]), plt.title('result')
# plt.imsave(fname="save.jpg", arr=np.asarray(res.eval())[0])  # 儲存圖片
plt.show()
    上面圖片做標註不是很明顯,換張女神圖片來碼程式碼~

    

    (八)擷取標記部分

# 隨機擷取影象上有資訊含量的部分,也可以提高模型健壯性
# 此函式為影象生成單個隨機變形的邊界框。函式輸出的是可用於裁剪原始影象的單個邊框。
# 返回值為3個張量:beginsize bboxes。前2個張量用於 tf.slice 剪裁影象。
# 後者可以用於 tf.image.draw_bounding_boxes 函式來畫出邊界框。
boxes = tf.constant([[[0.2, 0.3, 0.48, 0.65]]])
print(np.asarray(img_data).shape)
begin, size, bbox_for_draw = tf.image.sample_distorted_bounding_box(tf.shape(img_data),
bounding_boxes=boxes,
min_object_covered=0.1)
# 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)
plt.imshow(distorted_image.eval())
plt.show()

 tensorflow 資料增強處理基本上就這些啦~用起來,訓練神經網路才是關鍵。