python目標(biāo)檢測(cè)YoloV4當(dāng)中的Mosaic數(shù)據(jù)增強(qiáng)方法
什么是Mosaic數(shù)據(jù)增強(qiáng)方法
Yolov4的mosaic數(shù)據(jù)增強(qiáng)參考了CutMix數(shù)據(jù)增強(qiáng)方式,理論上具有一定的相似性!
CutMix數(shù)據(jù)增強(qiáng)方式利用兩張圖片進(jìn)行拼接。

但是mosaic利用了四張圖片,根據(jù)論文所說(shuō)其擁有一個(gè)巨大的優(yōu)點(diǎn)是豐富檢測(cè)物體的背景!且在BN計(jì)算的時(shí)候一下子會(huì)計(jì)算四張圖片的數(shù)據(jù)!就像下圖這樣:

實(shí)現(xiàn)思路
1、每次讀取四張圖片。




2、分別對(duì)四張圖片進(jìn)行翻轉(zhuǎn)、縮放、色域變化等,并且按照四個(gè)方向位置擺好。




3、進(jìn)行圖片的組合和框的組合

全部代碼
全部代碼構(gòu)成如下:
from PIL import Image, ImageDraw
import numpy as np
from matplotlib.colors import rgb_to_hsv, hsv_to_rgb
import math
def rand(a=0, b=1):
return np.random.rand()*(b-a) + a
def merge_bboxes(bboxes, cutx, cuty):
merge_bbox = []
for i in range(len(bboxes)):
for box in bboxes[i]:
tmp_box = []
x1,y1,x2,y2 = box[0], box[1], box[2], box[3]
if i == 0:
if y1 > cuty or x1 > cutx:
continue
if y2 >= cuty and y1 <= cuty:
y2 = cuty
if y2-y1 < 5:
continue
if x2 >= cutx and x1 <= cutx:
x2 = cutx
if x2-x1 < 5:
continue
if i == 1:
if y2 < cuty or x1 > cutx:
continue
if y2 >= cuty and y1 <= cuty:
y1 = cuty
if y2-y1 < 5:
continue
if x2 >= cutx and x1 <= cutx:
x2 = cutx
if x2-x1 < 5:
continue
if i == 2:
if y2 < cuty or x2 < cutx:
continue
if y2 >= cuty and y1 <= cuty:
y1 = cuty
if y2-y1 < 5:
continue
if x2 >= cutx and x1 <= cutx:
x1 = cutx
if x2-x1 < 5:
continue
if i == 3:
if y1 > cuty or x2 < cutx:
continue
if y2 >= cuty and y1 <= cuty:
y2 = cuty
if y2-y1 < 5:
continue
if x2 >= cutx and x1 <= cutx:
x1 = cutx
if x2-x1 < 5:
continue
tmp_box.append(x1)
tmp_box.append(y1)
tmp_box.append(x2)
tmp_box.append(y2)
tmp_box.append(box[-1])
merge_bbox.append(tmp_box)
return merge_bbox
def get_random_data(annotation_line, input_shape, random=True, hue=.1, sat=1.5, val=1.5, proc_img=True):
'''random preprocessing for real-time data augmentation'''
h, w = input_shape
min_offset_x = 0.4
min_offset_y = 0.4
scale_low = 1-min(min_offset_x,min_offset_y)
scale_high = scale_low+0.2
image_datas = []
box_datas = []
index = 0
place_x = [0,0,int(w*min_offset_x),int(w*min_offset_x)]
place_y = [0,int(h*min_offset_y),int(w*min_offset_y),0]
for line in annotation_line:
# 每一行進(jìn)行分割
line_content = line.split()
# 打開(kāi)圖片
image = Image.open(line_content[0])
image = image.convert("RGB")
# 圖片的大小
iw, ih = image.size
# 保存框的位置
box = np.array([np.array(list(map(int,box.split(',')))) for box in line_content[1:]])
# image.save(str(index)+".jpg")
# 是否翻轉(zhuǎn)圖片
flip = rand()<.5
if flip and len(box)>0:
image = image.transpose(Image.FLIP_LEFT_RIGHT)
box[:, [0,2]] = iw - box[:, [2,0]]
# 對(duì)輸入進(jìn)來(lái)的圖片進(jìn)行縮放
new_ar = w/h
scale = rand(scale_low, scale_high)
if new_ar < 1:
nh = int(scale*h)
nw = int(nh*new_ar)
else:
nw = int(scale*w)
nh = int(nw/new_ar)
image = image.resize((nw,nh), Image.BICUBIC)
# 進(jìn)行色域變換
hue = rand(-hue, hue)
sat = rand(1, sat) if rand()<.5 else 1/rand(1, sat)
val = rand(1, val) if rand()<.5 else 1/rand(1, val)
x = rgb_to_hsv(np.array(image)/255.)
x[..., 0] += hue
x[..., 0][x[..., 0]>1] -= 1
x[..., 0][x[..., 0]<0] += 1
x[..., 1] *= sat
x[..., 2] *= val
x[x>1] = 1
x[x<0] = 0
image = hsv_to_rgb(x)
image = Image.fromarray((image*255).astype(np.uint8))
# 將圖片進(jìn)行放置,分別對(duì)應(yīng)四張分割圖片的位置
dx = place_x[index]
dy = place_y[index]
new_image = Image.new('RGB', (w,h), (128,128,128))
new_image.paste(image, (dx, dy))
image_data = np.array(new_image)/255
# Image.fromarray((image_data*255).astype(np.uint8)).save(str(index)+"distort.jpg")
index = index + 1
box_data = []
# 對(duì)box進(jìn)行重新處理
if len(box)>0:
np.random.shuffle(box)
box[:, [0,2]] = box[:, [0,2]]*nw/iw + dx
box[:, [1,3]] = box[:, [1,3]]*nh/ih + dy
box[:, 0:2][box[:, 0:2]<0] = 0
box[:, 2][box[:, 2]>w] = w
box[:, 3][box[:, 3]>h] = h
box_w = box[:, 2] - box[:, 0]
box_h = box[:, 3] - box[:, 1]
box = box[np.logical_and(box_w>1, box_h>1)]
box_data = np.zeros((len(box),5))
box_data[:len(box)] = box
image_datas.append(image_data)
box_datas.append(box_data)
img = Image.fromarray((image_data*255).astype(np.uint8))
for j in range(len(box_data)):
thickness = 3
left, top, right, bottom = box_data[j][0:4]
draw = ImageDraw.Draw(img)
for i in range(thickness):
draw.rectangle([left + i, top + i, right - i, bottom - i],outline=(255,255,255))
img.show()
# 將圖片分割,放在一起
cutx = np.random.randint(int(w*min_offset_x), int(w*(1 - min_offset_x)))
cuty = np.random.randint(int(h*min_offset_y), int(h*(1 - min_offset_y)))
new_image = np.zeros([h,w,3])
new_image[:cuty, :cutx, :] = image_datas[0][:cuty, :cutx, :]
new_image[cuty:, :cutx, :] = image_datas[1][cuty:, :cutx, :]
new_image[cuty:, cutx:, :] = image_datas[2][cuty:, cutx:, :]
new_image[:cuty, cutx:, :] = image_datas[3][:cuty, cutx:, :]
# 對(duì)框進(jìn)行進(jìn)一步的處理
new_boxes = merge_bboxes(box_datas, cutx, cuty)
return new_image, new_boxes
def normal_(annotation_line, input_shape):
'''random preprocessing for real-time data augmentation'''
line = annotation_line.split()
image = Image.open(line[0])
box = np.array([np.array(list(map(int,box.split(',')))) for box in line[1:]])
iw, ih = image.size
image = image.transpose(Image.FLIP_LEFT_RIGHT)
box[:, [0,2]] = iw - box[:, [2,0]]
return image, box
if __name__ == "__main__":
with open("2007_train.txt") as f:
lines = f.readlines()
a = np.random.randint(0,len(lines))
# index = 0
# line_all = lines[a:a+4]
# for line in line_all:
# image_data, box_data = normal_(line,[416,416])
# img = image_data
# for j in range(len(box_data)):
# thickness = 3
# left, top, right, bottom = box_data[j][0:4]
# draw = ImageDraw.Draw(img)
# for i in range(thickness):
# draw.rectangle([left + i, top + i, right - i, bottom - i],outline=(255,255,255))
# img.show()
# # img.save(str(index)+"box.jpg")
# index = index+1
line = lines[a:a+4]
image_data, box_data = get_random_data(line,[416,416])
img = Image.fromarray((image_data*255).astype(np.uint8))
for j in range(len(box_data)):
thickness = 3
left, top, right, bottom = box_data[j][0:4]
draw = ImageDraw.Draw(img)
for i in range(thickness):
draw.rectangle([left + i, top + i, right - i, bottom - i],outline=(255,255,255))
img.show()
# img.save("box_all.jpg")
以上就是python目標(biāo)檢測(cè)YoloV4當(dāng)中的Mosaic數(shù)據(jù)增強(qiáng)方法的詳細(xì)內(nèi)容,更多關(guān)于YoloV4 Mosaic數(shù)據(jù)增強(qiáng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Python如何將LabelMe生成的JSON格式轉(zhuǎn)換成YOLOv8支持的TXT格式
- Python+Yolov5人臉口罩識(shí)別的詳細(xì)步驟
- Python3.7 + Yolo3實(shí)現(xiàn)識(shí)別語(yǔ)音播報(bào)功能
- Python Flask搭建yolov3目標(biāo)檢測(cè)系統(tǒng)詳解流程
- opencv-python+yolov3實(shí)現(xiàn)目標(biāo)檢測(cè)
- 對(duì)YOLOv3模型調(diào)用時(shí)候的python接口詳解
- Python+樹(shù)莓派+YOLO打造一款人工智能照相機(jī)
- 使用python和yolo方法實(shí)現(xiàn)yolo標(biāo)簽自動(dòng)標(biāo)注
相關(guān)文章
在python中用print()輸出多個(gè)格式化參數(shù)的方法
今天小編就為大家分享一篇在python中用print()輸出多個(gè)格式化參數(shù)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07
詳解python項(xiàng)目實(shí)戰(zhàn):模擬登陸CSDN
這篇文章主要介紹了python項(xiàng)目實(shí)戰(zhàn):模擬登陸CSDN,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
解決Python 中英文混輸格式對(duì)齊的問(wèn)題
今天小編就為大家分享一篇解決Python 中英文混輸格式對(duì)齊的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07
PyTorch中torch.manual_seed()的用法實(shí)例詳解
在Pytorch中可以通過(guò)相關(guān)隨機(jī)數(shù)來(lái)生成張量,并且可以指定生成隨機(jī)數(shù)的分布函數(shù)等,下面這篇文章主要給大家介紹了關(guān)于PyTorch中torch.manual_seed()用法的相關(guān)資料,需要的朋友可以參考下2022-06-06
基于Python創(chuàng)建可定制的HTTP服務(wù)器
這篇文章主要為大家演示一下如何使用?http.server?模塊來(lái)實(shí)現(xiàn)一個(gè)能夠發(fā)布網(wǎng)頁(yè)的應(yīng)用服務(wù)器,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-05-05
windows上徹底刪除jupyter notebook的實(shí)現(xiàn)
這篇文章主要介紹了windows上徹底刪除jupyter notebook的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-04-04

