目标检测常见数据增强算法汇总讲解(Mixup,Cutout,CutMix,Mosaic)
? ? ? ?在學(xué)習(xí)目標(biāo)檢測(cè)算法的過(guò)程中,發(fā)現(xiàn)了一些有趣的目標(biāo)檢測(cè)算法,打算簡(jiǎn)單寫個(gè)筆記,不足之處還望諒解,可以在評(píng)論中指出來(lái)。
? ? ? ? 目標(biāo)檢測(cè)作為需要大量數(shù)據(jù)的算法,在實(shí)際情況中經(jīng)常面臨數(shù)據(jù)不足的情況,事實(shí)上很多時(shí)候數(shù)據(jù)確實(shí)對(duì)于開發(fā)者來(lái)說(shuō)非常難搞,因此大佬們開發(fā)了各式各樣的通過(guò)軟件的方式將我們的數(shù)據(jù)變的多樣化的方法。(Mixup,Cutout,CutMix,Mosaic)就是四種最為經(jīng)典的算法,下面我們逐一進(jìn)行講解。
Mixup數(shù)據(jù)增強(qiáng)算法:
? ? ? ? ?隨機(jī)混合圖像:將兩個(gè)圖像按一定比例混合生成新的圖像,(與其他數(shù)據(jù)增強(qiáng)方式不同的是這里還會(huì)生成新標(biāo)簽),然后使用新的圖像和標(biāo)簽參與訓(xùn)練,整個(gè)過(guò)程中原始圖像不參與訓(xùn)練。?
??圖1
圖2
? ?
混合后的圖像
?圖像混合的數(shù)學(xué)方法(mixup數(shù)學(xué)公式)如下:
(x? , y?),(x??, y?)是隨機(jī)選擇的兩個(gè)樣本及對(duì)應(yīng)標(biāo)簽。其中,圖像x?(標(biāo)簽為y?)和圖像x?(標(biāo)簽為y?),λ為從beta分布中隨機(jī)采樣的數(shù)。
個(gè)人感覺他這個(gè)算法思想還是很easy的就是根據(jù)從beta中采樣的隨機(jī)數(shù),然后根據(jù)隨機(jī)數(shù)的比例對(duì)圖像進(jìn)行混合,同時(shí)標(biāo)簽也是按照相應(yīng)的比例混合,從何得到混合后的新圖像和新標(biāo)簽。
mixup源代碼:
import matplotlib.pyplot as plt
import matplotlib.image as Image
import cv2
im1 = Image.imread("cat1.jpg") #輸入圖片1的路徑
im1 = im1/255.
im2 = Image.imread("cat2.jpg") #輸入圖片2的路徑
im2 = im2/255.lam= 4*0.1 #融合比例
im_mixup = (im1*lam+im2*(1-lam))
cv2.imwrite('mixup.jpg', im_mixup) #把融合之后的圖片保存到當(dāng)前文件夾
plt.imshow(im_mixup)
plt.show()
Cutout數(shù)據(jù)增強(qiáng)算法:?
? ? ? ?隨機(jī)裁剪圖像的一塊區(qū)域,并在圖像中對(duì)裁剪后的區(qū)域進(jìn)行補(bǔ)0,與mixup不同的是,它不改變label。如下圖所示,很簡(jiǎn)單和容易理解的方法,這個(gè)有點(diǎn)類似神經(jīng)網(wǎng)絡(luò)的dropout,我們隨時(shí)扔掉一些神經(jīng)元,可緩解神經(jīng)網(wǎng)絡(luò)的過(guò)擬合達(dá)到更好的效果。
? ? ? ??
Cutout源代碼:?
import cv2
from torchvision import transforms
import matplotlib.pyplot as plt
import numpy as np
import torch
class Cutout(object):"""Randomly mask out one or more patches from an image.Args:n_holes (int): Number of patches to cut out of each image.length (int): The length (in pixels) of each square patch."""def __init__(self, n_holes=1, length=16):self.n_holes = n_holesself.length = lengthdef __call__(self, img):"""Args:img (Tensor): Tensor image of size (C, H, W).Returns:Tensor: Image with n_holes of dimension length x length cut out of it."""h = img.size(1)w = img.size(2)mask = np.ones((h, w), np.float32)for n in range(self.n_holes):y = np.random.randint(h)x = np.random.randint(w)y1 = np.clip(y - self.length // 2, 0, h)y2 = np.clip(y + self.length // 2, 0, h)x1 = np.clip(x - self.length // 2, 0, w)x2 = np.clip(x + self.length // 2, 0, w)mask[y1: y2, x1: x2] = 0.mask = torch.from_numpy(mask)mask = mask.expand_as(img)img = img * maskreturn img
# 執(zhí)行cutout
img = cv2.imread('cat.1.jpg')#圖片路徑
img = transforms.ToTensor()(img)cut = Cutout(length=100)
img = cut(img)# cutout圖像寫入本地
img = img.mul(255).byte()
img = img.numpy().transpose((1, 2, 0))
cv2.imwrite('cutout.jpg', img) #把隨機(jī)裁剪之后的圖片保存到當(dāng)前文件夾
plt.imshow(img)
plt.show()
? ? ? ??
CutMix數(shù)據(jù)增強(qiáng)算法:?
? ? ? CutMix算法其實(shí)也可以顧名思義理解,Cutout和Mixup的結(jié)合體,思想很簡(jiǎn)單,我們首先使用Cutout對(duì)圖像隨機(jī)選擇一塊兒區(qū)域進(jìn)行裁剪,然后使用Mixup圖像跟裁剪后的圖像進(jìn)行混合。
數(shù)學(xué)上實(shí)現(xiàn)方法如下:
Cutmix代碼:
代碼懶得自己寫了,參考這位
數(shù)據(jù)增強(qiáng)---CutMix - hikari_1994 - 博客園大佬的修改了一下。可以自動(dòng)將輸入的圖片resize成同樣大小的,這樣可以隨意輸入兩個(gè)不同大小的圖片,和效果圖可以自動(dòng)保存到本地。
import matplotlib.pyplot as plt
import numpy as npplt.rcParams['figure.figsize'] = [10, 10]import cv2def rand_bbox(size, lamb):"""生成隨機(jī)的bounding box:param size::param lamb::return:"""W = size[0]H = size[1]# 得到一個(gè)bbox和原圖的比例cut_ratio = np.sqrt(1.0 - lamb)cut_w = int(W * cut_ratio)cut_h = int(H * cut_ratio)# 得到bbox的中心點(diǎn)cx = np.random.randint(W)cy = np.random.randint(H)bbx1 = np.clip(cx - cut_w // 2, 0, W)bby1 = np.clip(cy - cut_h // 2, 0, H)bbx2 = np.clip(cx + cut_w // 2, 0, W)bby2 = np.clip(cy + cut_h // 2, 0, H)#隨機(jī)生成遮擋框return bbx1, bby1, bbx2, bby2def cutmix(image_batch, image_batch_labels, alpha=1.0):# 決定bbox的大小,服從beta分布lam = np.random.beta(alpha, alpha)# permutation: 如果輸入x是一個(gè)整數(shù),那么輸出相當(dāng)于打亂的range(x)rand_index = np.random.permutation(len(image_batch))# 對(duì)應(yīng)公式中的y_a,y_btarget_a = image_batch_labelstarget_b = image_batch_labels[rand_index]# 根據(jù)圖像大小隨機(jī)生成bboxbbx1, bby1, bbx2, bby2 = rand_bbox(image_batch[0].shape, lam)image_batch_updated = image_batch.copy()# image_batch的維度分別是 batch x 寬 x 高 x 通道# 將所有圖的bbox對(duì)應(yīng)位置, 替換為其他任意一張圖像# 第一個(gè)參數(shù)rand_index是一個(gè)list,可以根據(jù)這個(gè)list里索引去獲得image_batch的圖像,也就是將圖片亂序的對(duì)應(yīng)起來(lái)image_batch_updated[:, bbx1: bbx2, bby1:bby2, :] = image_batch[rand_index, bbx1:bbx2, bby1:bby2, :]# 計(jì)算 1 - bbox占整張圖像面積的比例lam = 1 - ((bbx2 - bbx1) * (bby2 - bby1)) / (image_batch.shape[1] * image_batch.shape[2])# 根據(jù)公式計(jì)算labellabel = target_a * lam + target_b * (1. - lam)return image_batch_updated, labelif __name__ == '__main__':cat = cv2.cvtColor(cv2.imread("cat.1.jpg"), cv2.COLOR_BGR2RGB)dog = cv2.cvtColor(cv2.imread("cat.2.jpg"), cv2.COLOR_BGR2RGB)data = [cat , dog]a = 0H, W = cat.shape[0], cat.shape[1]width = 400 # 需要縮放成多大,這里直接修改就行,我這里是縮放成400*400,根據(jù)自己的需要修改成響應(yīng)的數(shù)值即可height = 400 #博主源代碼只能輸入大小相同兩張圖片進(jìn)行cutmix,我這里可以自動(dòng)將兩張圖片調(diào)整成相同大小,避免了還需要手動(dòng)調(diào)節(jié)圖片大小輸入的尷尬cat= cv2.resize(cat, (width, height), interpolation=cv2.INTER_AREA)H, W = dog.shape[0], dog.shape[1]width = 400 # 需要縮放成多大,這里直接修改就行,我這里是縮放成400*400,根據(jù)自己的需要修改成響應(yīng)的數(shù)值即可height = 400dog= cv2.resize(dog, (width, height), interpolation=cv2.INTER_AREA)updated_img, label = cutmix(np.array([cat, dog]), np.array([[0, 1], [1, 0]]), 0.5)print(label)#輸出融合后的標(biāo)簽fig, axs = plt.subplots(nrows=1, ncols=2, squeeze=False)ax1 = axs[0, 0]ax2 = axs[0, 1]ax1.imshow(updated_img[0])cv2.imwrite('cutmix_1.jpg', updated_img[0])ax2.imshow(updated_img[1])cv2.imwrite('cutmix_2.jpg', updated_img[1])plt.show()
Mosaic數(shù)據(jù)增強(qiáng)算法:?
更像是Cutmix的改進(jìn),四張圖片拼接到一起,這樣使得在訓(xùn)練的時(shí)候可以一次性訓(xùn)練四張圖,
據(jù)說(shuō)是在BN層計(jì)算的時(shí)候效果更好,到底好不好咱也不知道,作者說(shuō)好就是好把。不過(guò)極大的豐富了目標(biāo)背景這個(gè)倒是真的,畢竟一個(gè)目標(biāo)有了四個(gè)背景不是?
?我這效果圖不好可能是因?yàn)檫x的圖片尺寸有點(diǎn)問題,懶得調(diào)了,知道啥意思就行。
一句話看懂思路的就是這位大佬的
目標(biāo)檢測(cè): 一文讀懂 Mosaic 數(shù)據(jù)增強(qiáng)_大林兄的博客-CSDN博客_mosaic數(shù)據(jù)增強(qiáng)
的這部分
?好的,我想這里已經(jīng)表達(dá)的很清楚了。當(dāng)然細(xì)節(jié)的地方得注意一下,圖像拼接的時(shí)候,是需要分別對(duì)圖片進(jìn)行增光操作的。
????????1、翻轉(zhuǎn)(對(duì)原始圖片進(jìn)行左右的翻轉(zhuǎn));
????????2、縮放(對(duì)原始圖片進(jìn)行大小的縮放);
????????3、色域變化(對(duì)原始圖片的明亮度、飽和度、色調(diào)進(jìn)行改變)等操作。這也是為了豐富一下數(shù)據(jù)多樣性
并且按照四個(gè)方向位置擺好
代碼看B導(dǎo)的:睿智的目標(biāo)檢測(cè)28——YoloV4當(dāng)中的Mosaic數(shù)據(jù)增強(qiáng)方法_Bubbliiiing的博客-CSDN博客_睿智yolov4
b導(dǎo)已經(jīng)寫的很好了,我就不寫了
好的 目標(biāo)檢測(cè)數(shù)據(jù)增強(qiáng)篇就到這里了,兄弟們覺得有用的麻煩點(diǎn)個(gè)贊!感謝!
? ? ? ? ??
總結(jié)
以上是生活随笔為你收集整理的目标检测常见数据增强算法汇总讲解(Mixup,Cutout,CutMix,Mosaic)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在 eclipse 中 设置 jvm 的
- 下一篇: SE 多人游戏《Foamstars》公开