Tensorflow 圖片數據增強(二): 圖片處理函數

LUFOR129
8 min readJun 24, 2019

今天來說一說一些tensorflow自帶的圖片處理函數吧! 我整理了一些tensorflow圖片處理函數,使用這些函數可以很快速輕鬆的對圖片進行預處理。

要注意的是經過tensorflow圖片處理後格式會變成”tensor”。也就是說,圖片輸入函數的當下並不會立即執行,而是會等到Session才會一起執行。

今天的主角就選用,美心小妹妹當範例:

#使用opencv讀取圖片
img = cv2.imdecode(np.fromfile(r"./美心.jpg",dtype=np.uint8),-1)
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

一、圖片大小改變

with tf.Session() as sess:
img_data = tf.image.resize_images(img,[277,277],method=0)
#method = 0 雙線程插植法
#method = 1 鄰近法
#method = 2 雙三次插植法
#method = 3 面積插植法
#我認為默認的雙線程插值法對一般情況最夠用

二、圖片裁剪與填充

img_data = tf.image.resize_image_with_crop_or_pad(img,1000,1000)
img_data = tf.image.resize_image_with_crop_or_pad(img,200,200)
img_data = tf.image.central_crop(img,0.5)
#tf.image.resize_image_with_crop_or_pad
#會根據原始圖片大小進行填充或裁切(中心點向外裁)
#tf.image.central_crop
#會擷取中心點N%的圖片,例如0.5=中心點50%,因此圖片出來是原圖的長寬比例

三、圖片翻轉

在訓練過程中,假如我們訓練的是狗,狗向左看向右看都應該要被機器正確辨認,因此使用發轉可以增加機器辨識率。#上下翻轉
img_data = tf.image.flip_up_down(img)
#左右翻轉
img_data = tf.image.flip_left_right(img)
#對角線翻轉
img_data = tf.image.transpose_image(img)
當然我們更希望圖片預處理時增加圖片的隨機性,tensorflow翻轉有自帶random的函數,可以以50%機率做翻轉
img_data = tf.image.random_flip_left_right(img)
img_data = tf.image.random_flip_up_down(img)

四、亮度、對比、色相、飽和

為了隨機性,我們通常會將這些圖片以隨機的方式處理
1. 亮度 -0.5~0.5
img_data = tf.image.random_brightness(img,max_delta=0.5)
2. 對比 0.8~3
img_data = tf.image.random_contrast(img,lower=0.8,upper=3)
3. 色相 0~0.2
img_data = tf.image.random_hue(img,max_delta=0.2)
4. 飽和 0~4
img_data = tf.image.random_saturation(img,lower=0,upper=4)

五、隨機裁切

隨機裁切是有意義的,就像盲人摸象,電腦不論看到象腿、象鼻、象尾都應該要知道這是一頭大象,同理我們也要給電腦不同裁切圖片做辨識。bbox = [[[0.3,0.3,0.6,0.8]]]     #只能為三維
height,width,channel = img.shape
cv2.rectangle(img, (int(0.3*width), int(0.3*height)), (int(0.6*width), int(0.8*height)), (0, 255, 0), 2)
plt.imshow(img)
plt.show()
with tf.Session() as sess:
begin,size,bbox_for_draw = tf.image.sample_distorted_bounding_box(tf.shape(img),bounding_boxes=bbox,min_object_covered=0.6)
distorted_img = tf.slice(img,begin,size)
plt.imshow(distorted_img.eval())
plt.show()
  1. 想要裁切先要建立 bounding_box 告訴電腦圖片中有訊息的是哪一部分,其中bbox分別對應[width_min,height_min,width_max,height_max]的比例關係,好比一張(width=180,height=270) 放上bbox = (0.3,0.3,0.6,0.8)代表著(54,81)到(108,216)的框框。
利用rectangle框出

2. 放入tf.image.sample_distorted_bounding_box,其中重要參數min_object_covered代表隨機切出的圖片應該要"最少"包含bbox多大部分。

切出後可以看到至少包含超過0.6的bbox

六、完整實作preprocess

上面講了那麼多,實際上該如何寫呢?我們會頃向寫入進一個函數之中。

def train_preprocess(image,bbox):
begin,size,bbox_for_draw = tf.image.sample_distorted_bounding_box(tf.shape(image),bounding_boxes=bbox,min_object_covered=0.8)
_img = tf.slice(image,begin,size)
_img = tf.image.random_brightness(_img,max_delta=0.3)
_img = tf.image.random_contrast(_img,lower=0.8,upper=1.2)
_img = tf.image.random_hue(_img,max_delta=0.1)
_img = tf.image.random_saturation(_img,lower=0,upper=2)
_img = tf.image.random_flip_left_right(_img)
return _img

執行:

with tf.Session() as sess:
bbox = [[[0.3,0.3,0.6,0.8]]]
for i in range(6):
distorted_img = train_preprocess(img,bbox)
plt.imshow(distorted_img.eval())
plt.show()

結果如下:

七、完整程式碼

由於圖片檔案太大了,將ipynb檔放在gist會一直無法完成渲染,因此直接放程式碼

八、 下一篇

--

--