RLE格式標註檔案轉為PNG格式(Run Length Encode)
阿新 • • 發佈:2018-12-19
一、什麼是 RLE 格式
在機器視覺領域的深度學習中,每個資料集都有一份標註好的資料用於訓練神經網路。
但是神經網路的輸入一定是一張圖片,為此必須把RLE格式的檔案轉變為影象格式。
影象格式主要又分為 .jpg 和 .png 兩種格式,其中label資料一定不能使用 .jpg,因為它因為壓縮算演算法的原因,會造成影象失真,影象各個畫素的值可能會發生變化。分割任務的資料集的 label 影象中每一個畫素都代表了該畫素點所屬的類別,所以這樣的失真是無法接受的。為此只能使用 .png 格式作為label,pascol voc 和 coco 資料集正是這樣做的。
二、如何轉化為 .png
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import numpy as np # linear algebra import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv) from PIL import Image # ref: https://www.kaggle.com/paulorzp/run-length-encode-and-decode #將圖片編碼成rle格式 def rle_encode(img, min_max_threshold=1e-3, max_mean_threshold=None): ''' img: numpy array, 1 - mask, 0 - background Returns run length as string formated ''' if np.max(img) < min_max_threshold: return '' ## no need to encode if it's all zeros if max_mean_threshold and np.mean(img) > max_mean_threshold: return '' ## ignore overfilled mask pixels = img.T.flatten() pixels = np.concatenate([[0], pixels, [0]]) runs = np.where(pixels[1:] != pixels[:-1])[0] + 1 runs[1::2] -= runs[::2] return ' '.join(str(x) for x in runs) #將圖片從rle解碼 def rle_decode(mask_rle, shape=(768, 768)): ''' mask_rle: run-length as string formated (start length) shape: (height,width) of array to return Returns numpy array, 1 - mask, 0 - background ''' s = mask_rle.split() starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])] starts -= 1 ends = starts + lengths img = np.zeros(shape[0]*shape[1], dtype=np.uint8) for lo, hi in zip(starts, ends): img[lo:hi] = 1 return img.reshape(shape).T # Needed to align to RLE direction def masks_as_image(in_mask_list): # Take the individual ship masks and create a single mask array for all ships all_masks = np.zeros((768, 768), dtype = np.uint8) for mask in in_mask_list: if isinstance(mask, str): all_masks |= rle_decode(mask) return all_masks #將目標路徑下的rle檔案中所包含的所有rle編碼,儲存到save_img_dir中去 def rle_2_img(train_rle_dir,save_img_dir): masks = pd.read_csv(train_rle_dir) not_empty = pd.notna(masks.EncodedPixels) print(not_empty.sum(), 'masks in', masks[not_empty].ImageId.nunique(), 'images') print((~not_empty).sum(), 'empty images in', masks.ImageId.nunique(), 'total images') all_batchs = list(masks.groupby('ImageId')) train_images = [] train_masks = [] i = 0 for img_id, mask in all_batchs: c_mask = masks_as_image(mask['EncodedPixels'].values) im = Image.fromarray(c_mask) im.save(save_img_dir+img_id.split('.')[0] + '.png') print(i,img_id.split('.')[0] + '.png') i += 1 return train_images, train_masks if __name__ == '__main__': rle_2_img('D://DL//airbus-kaggle//dataset_V2//train_ship_segmentations_v2.csv', 'D://DL//airbus-kaggle//dataset_V2//mask//')