Python基於域相關實現圖像增強的方法教程
介紹
當在圖像上訓練深度神經網絡模型時,通過對由數據增強生成的更多圖像進行訓練,可以使模型更好地泛化。常用的增強包括水平和垂直翻轉/移位、以一定角度和方向(順時針/逆時針)隨機旋轉、亮度、飽和度、對比度和縮放增強。
Python中一個非常流行的圖像增強庫是albumentations(https://albumentations.ai/),通過直觀的函數和優秀的文檔,可以輕松地增強圖像。它也可以與PyTorch和TensorFlow等流行的深度學習框架一起使用。
域相關的數據增強
直覺
背後的想法來自於在現實中可能遇到的圖像。例如,像雪或雨滴這樣的增強是不應該在x射線圖像中發現的增強,但胸管和起搏器是可以在x射線圖像中發現的增強。
這個想法從何而來
改變瞭Roman (@ nroman on Kaggle)為SIIM-ISIC黑色素瘤分類比賽做增強的方法。有關他的方法的詳細信息,請參見:https://www.kaggle.com/c/siim-isic-melanoma-classification/discussion/159176. 增強的一個片段如下所示:
原始圖像(左上方)和頭發增強圖像(右上方)
此文確實在我們的模型訓練中使用瞭他的增強函數,這有助於提高我們大多數模型的交叉驗證(CV)分數。
想說的是,這種形式的增強可能在我們的最終排名中發揮瞭關鍵作用!從那時起,使用頭發(或一般的人工制品)來增強圖像數據的想法在我參加的後續比賽中非常接近,並盡可能地加以應用。
特別是,該方法被推廣並應用於全球小麥檢測、木薯葉病分類挑戰賽。
昆蟲增強
正如標題所示,這種方法包括用昆蟲增強圖像。這可以是數據中的一種自然設置,因為昆蟲通常在空中或地面上被發現。
在本例中,在木薯和全球小麥檢測競賽中,蜜蜂被用作增強葉片圖像時的首選昆蟲。以下是增強圖像的外觀示例:
蜜蜂在葉子周圍飛翔的增強圖像
我們還可以使用掩碼形式,導致圖像中出現黑點(類似於相冊中的脫落),即沒有顏色和黑色的蜜蜂:
增強圖像,黑色/黑色蜜蜂圍繞樹葉飛行
以下以Albumentations風格編寫的代碼允許增強函數與來自Albumentations庫的其他增強函數一起輕松使用:
from albumentations.core.transforms_interface import ImageOnlyTransform class InsectAugmentation(ImageOnlyTransform): """ 將昆蟲的圖像強加到目標圖像上 ----------------------------------------------- 參數: insects (int): 昆蟲的最大數量 insects_folder (str): 昆蟲圖片文件夾的路徑 """ def __init__(self, insects=2, dark_insect=False, always_apply=False, p=0.5): super().__init__(always_apply, p) self.insects = insects self.dark_insect = dark_insect self.insects_folder = "/kaggle/input/bee-augmentation/" def apply(self, image, **kwargs): """ 參數: image (PIL Image): 畫昆蟲的圖像。 Returns: PIL Image: 帶昆蟲的圖像。 """ n_insects = random.randint(1, self.insects) # 在這個例子中,我用1而不是0來說明增強效果 if not n_insects: return image height, width, _ = image.shape # 目標圖像的寬度和高度 insects_images = [im for im in os.listdir(self.insects_folder) if 'png' in im] for _ in range(n_insects): insect = cv2.cvtColor(cv2.imread(os.path.join(self.insects_folder, random.choice(insects_images))), cv2.COLOR_BGR2RGB) insect = cv2.flip(insect, random.choice([-1, 0, 1])) insect = cv2.rotate(insect, random.choice([0, 1, 2])) h_height, h_width, _ = insect.shape # 昆蟲圖像的寬度和高度 roi_ho = random.randint(0, image.shape[0] - insect.shape[0]) roi_wo = random.randint(0, image.shape[1] - insect.shape[1]) roi = image[roi_ho:roi_ho + h_height, roi_wo:roi_wo + h_width] # 創建掩碼和反掩碼 img2gray = cv2.cvtColor(insect, cv2.COLOR_BGR2GRAY) ret, mask = cv2.threshold(img2gray, 10, 255, cv2.THRESH_BINARY) mask_inv = cv2.bitwise_not(mask) # 現在黑掉的區域是昆蟲 img_bg = cv2.bitwise_and(roi, roi, mask=mask_inv) # 從昆蟲圖像中隻選取昆蟲區域。 if self.dark_insect: img_bg = cv2.bitwise_and(roi, roi, mask=mask_inv) insect_fg = cv2.bitwise_and(img_bg, img_bg, mask=mask) else: insect_fg = cv2.bitwise_and(insect, insect, mask=mask) # 添加 dst = cv2.add(img_bg, insect_fg, dtype=cv2.CV_64F) image[roi_ho:roi_ho + h_height, roi_wo:roi_wo + h_width] = dst return image
如果你希望使用黑色版本,請將dark_insect設置為True。在這個Kaggle筆記本中可以找到一個示例實現:https://www.kaggle.com/khoongweihao/insect-augmentation-with-efficientdet-d6/notebook
使用針的增強
在這種方法中,使用針來增強圖像,例如可以是x射線圖像。以下是增強圖像的外觀示例:
x光片左側帶針頭的增強圖像
類似地,我們可以使用黑色版本的針,從而生成以下增強圖像:
x射線兩側帶有黑色/黑色針頭的增強圖像
作為上述擴展模塊的代碼片段如下所示:
def NeedleAugmentation(image, n_needles=2, dark_needles=False, p=0.5, needle_folder='../input/xray-needle-augmentation'): aug_prob = random.random() if aug_prob < p: height, width, _ = image.shape # 目標圖像的寬度和高度 needle_images = [im for im in os.listdir(needle_folder) if 'png' in im] for _ in range(1, n_needles): needle = cv2.cvtColor(cv2.imread(os.path.join(needle_folder, random.choice(needle_images))), cv2.COLOR_BGR2RGB) needle = cv2.flip(needle, random.choice([-1, 0, 1])) needle = cv2.rotate(needle, random.choice([0, 1, 2])) h_height, h_width, _ = needle.shape # 針圖像的寬度和高度 roi_ho = random.randint(0, abs(image.shape[0] - needle.shape[0])) roi_wo = random.randint(0, abs(image.shape[1] - needle.shape[1])) roi = image[roi_ho:roi_ho + h_height, roi_wo:roi_wo + h_width] # 創建掩碼和反掩碼 img2gray = cv2.cvtColor(needle, cv2.COLOR_BGR2GRAY) ret, mask = cv2.threshold(img2gray, 10, 255, cv2.THRESH_BINARY) mask_inv = cv2.bitwise_not(mask) # 現在黑掉的區域是針 img_bg = cv2.bitwise_and(roi, roi, mask=mask_inv) # 隻選取針區域。 if dark_needles: img_bg = cv2.bitwise_and(roi, roi, mask=mask_inv) needle_fg = cv2.bitwise_and(img_bg, img_bg, mask=mask) else: needle_fg = cv2.bitwise_and(needle, needle, mask=mask) # 添加 dst = cv2.add(img_bg, needle_fg, dtype=cv2.CV_64F) image[roi_ho:roi_ho + h_height, roi_wo:roi_wo + h_width] = dst return image
請註意,以上內容不是Albumentations格式,不能直接應用於常規Albumentations增強。必須進行一些調整,使其與上述昆蟲/蜜蜂增強中的格式相同。但變化應該很小!
同樣,如果你希望使用黑色版本,請將dark_Piners設置為True。在我的Kaggle筆記本中可以找到一個示例實現:https://www.kaggle.com/khoongweihao/x-ray-needle-augmentation-et-al/notebook.
實驗結果
總的來說,局部CV結果有所改善,大部分略有改善(如0.001–0.003)。但在某些情況下,使用這種增強方法在訓練過程中“失敗”。
例如,在全球小麥檢測競賽中,任務涉及檢測小麥頭部,即目標檢測任務。盡管進行瞭大量的超參數調整,但使用原始蜜蜂的蜜蜂增強導致訓練驗證損失波動很大。
雖然使用增強器確實提高瞭CV,但可以說這確實是一個幸運的機會。使用僅保留黑色像素的增強被證明在應用程序的各個領域是穩定的。特別是,CV的提升是實質性的,也是一致的。
到目前為止,尚未找到蜜蜂數量增加導致不同epoch之間出現這種訓練結果的原因,但有一種假設是蜜蜂的顏色接近某些麥頭,因此“混淆”瞭檢測算法,該算法隨後在同一邊界框內捕獲麥頭和最近的蜜蜂。
在一些邊界框預測中觀察到瞭這一點,但沒有足夠的觀察案例可以肯定地說這一假設是正確的。在任何情況下,還應該考慮圖像屬性(顏色)是否具有接近目標(例如小麥頭)的分佈。
另一方面,使用針的增強被證明(原始及其黑色/黑色版本)都相對穩定。在該示例中,預測的目標雖然在顏色分佈上相似,但可能具有明顯的特征(例如,胸管看起來與針頭大不相同),因此分類算法不會混淆針頭是否是正確的目標。
到此這篇關於Python基於域相關實現圖像增強的方法教程的文章就介紹到這瞭,更多相關Python圖像增強內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 使用python和opencv的mask實現摳圖疊加
- Python深度學習albumentations數據增強庫
- python中opencv圖像疊加、圖像融合、按位操作的具體實現
- Python圖像運算之圖像點運算與灰度化處理詳解
- Python+OpenCV數字圖像處理之ROI區域的提取