import os
import cv2
import numpy as np
import sklearn
import albumentations
from albumentations import (Blur,MotionBlur,MedianBlur,GaussianBlur,GlassBlur,Flip,ShiftScaleRotate,
GridDistortion,ElasticTransform,RandomResizedCrop,
HueSaturationValue,Transpose,RandomBrightnessContrast,CLAHE,
CoarseDropout,Cutout,Normalize,ToFloat,OneOf,Compose)
class MyDataGenerator(keras.utils.Sequence):
def __init__(self, image_names, labels, classes, root_directory='',image_size=(224,224),
batch_size=64,shuffle=True,augment=True,label_smoothing=False,mix_up=False):
self.image_filenames = image_names
self.labels = labels
self.classes = classes
self.root_directory = root_directory
self.batch_size = batch_size
self.image_size = image_size
self.shuffle = shuffle
self.is_label_smoothing = label_smoothing
self.is_mix_up = mix_up
self.augment = augment
if self.augment:
self.generator = Compose([
# OneOf([
# MotionBlur(blur_limit=3,p=0.5),
# MedianBlur(blur_limit=3, p=0.5),
# Blur(blur_limit=3, p=0.5),GaussianBlur(blur_limit=3,p=0.5)]),
Flip(p=0.5),
# Transpose(p=0.5),
#RandomResizedCrop(height=self.image_size[0],width=self.image_size[1],
# scale=(0.8, 1.0), ratio=#(0.8, 1.2),p=0.5),
ShiftScaleRotate(shift_limit=0.2,scale_limit=0.2,rotate_limit=45,p=0.5),
RandomBrightnessContrast(brightness_limit=0.2, contrast_limit=0.2,p=0.5),
# HueSaturationValue(hue_shift_limit=20, sat_shift_limit=30, val_shift_limit=20,p=1.0),
# CLAHE(clip_limit=4.0,tile_grid_size=(8, 8),p=0.5),
# GridDistortion(num_steps=5,distort_limit=0.3,p=0.5),
# ElasticTransform(alpha=1,sigma=50,alpha_affine=50,p=0.5),
Cutout(num_holes=8,max_h_size=8,max_w_size=8, fill_value=0,p=0.5),
Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225),
max_pixel_value=255.0, p=1.0)])
else:
self.generator = Compose([ Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225),
max_pixel_value=255.0, p=1.0)])
count = 0
for i in self.image_filenames:
if os.path.exists(self.root_directory+i):
count+=1
print('Found {} validated image filenames belonging to {} classes.'
.format(count,len(np.unique(self.labels)))
def __len__(self):
return int(np.ceil(len(self.image_filenames) / float(self.batch_size)))
def on_epoch_end(self):
if self.shuffle:
self.image_filenames, self.labels = sklearn.utils.shuffle(self.image_filenames,self.labels)
def __getitem__(self,index):
batch_x = self.image_filenames[index*self.batch_size:(index+1)*self.batch_size]
batch_y = self.labels[index*self.batch_size:(index+1)*self.batch_size]
new_images = []
new_labels = []
for image_name,label in zip(batch_x,batch_y):
image = cv2.imread(os.path.join(self.root_directory,image_name))
image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
image = cv2.resize(image,(self.image_size[1],self.image_size[0]))
image = self.generator(image=image)['image']
new_images.append(image)
new_labels.append(label)
new_images,new_labels = np.array(new_images), np.array(new_labels)
new_labels = keras.utils.to_categorical(new_labels,num_classes=self.classes) #one-hot
if self.is_mix_up:
alpha = 0.2
λ = np.random.beta(alpha,alpha,new_images.shape[0])
λ1 = np.reshape(λ, (new_images.shape[0],1,1,1))
λ2 = np.reshape(λ, (new_images.shape[0],1))
index = np.random.permutation(new_images.shape[0])
image1, label1 = new_images[index],new_labels[index]
image2, label2 = new_images, new_labels
new_images = λ1*image1 + (1 - λ1) * image2
new_labels = λ2*label1 + (1 - λ2) * label2
if self.is_label_smoothing:
factor = 0.1
new_labels *= (1 - factor)
new_labels += (factor / self.classes)
return new_images,new_labels
class TestDataGenerator(keras.utils.Sequence):
def __init__(self, image_names, root_directory='',image_size=(224,224), batch_size=64):
self.image_filenames = image_names
self.root_directory = root_directory
self.batch_size = batch_size
self.image_size = image_size
self.generator = Compose([ToFloat(max_value=255.0,p=1.0)])
count = 0
for i in self.image_filenames:
if os.path.exists(self.root_directory+i):
count+=1
print('Found {} validated image filenames.'.format(count))
def __len__(self):
return int(np.ceil(len(self.image_filenames) / float(self.batch_size)))
def __getitem__(self,index):
batch_x = self.image_filenames[index*self.batch_size:(index+1)*self.batch_size]
new_images = []
for image_name in batch_x:
image = cv2.imread(os.path.join(self.root_directory,image_name))
image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
image = cv2.resize(image,(self.image_size[1],self.image_size[0]))
img = self.generator(image=image)['image']
new_images.append(img)
new_images = np.array(new_images)
return new_images
trainDataGenerator = MyDataGenerator(image_names=train_x,labels=train_y,batch_size=batch_size,
image_size=(height,width),classes=len(classes),augment=True,
label_smoothing=True,mix_up=False,
root_directory='../input/images/')
validDataGenerator = MyDataGenerator(image_names=valid_x,labels=valid_y,batch_size=batch_size,
image_size=(height,width),classes=len(classes),augment=False,
root_directory='../input/images/')
testDataGenerator = TestDataGenerator(image_names=test_x,
batch_size=batch_size,
image_size=image_size,
root_directory='../input/images/')
以EfficientNet(源代码: https://github.com/xuannianz/EfficientDet),coco格式输入数据为例
from albumentations import (Blur,MotionBlur,MedianBlur,GaussianBlur,GlassBlur,Flip,ShiftScaleRotate,
GridDistortion,ElasticTransform,RandomSizedCrop,RandomResizedCrop,
RandomSizedBBoxSafeCrop,RandomScale,Normalize,
HueSaturationValue,Transpose,RandomBrightnessContrast,CLAHE,Resize,
CoarseDropout,Cutout,Normalize,ToFloat,OneOf,Compose)
#Generator是EfficientNet源码里的已继承Sequence的类
class CocoGenerator(Generator):
def __init__(self, data_dir, set_name, img_size=(224,224), classes=1024, augment=False, **kwargs):
self.coco = COCO('/input/instances_Images.json') #读取数据
self.image_ids = self.coco.getImgIds()
self.load_classes()
self.img_size = img_size
self.data_dir = data_dir
self.classes = classes
if augment:
self.generator = Compose([
OneOf([Resize(self.img_size[0], self.img_size[1]),
RandomResizedCrop(height=self.img_size[0],width=self.img_size[1],scale=(0.8,1.2),ratio=(0.8,1.2))],p=1.0),
OneOf([MotionBlur(blur_limit=3,p=0.5), MedianBlur(blur_limit=3, p=0.5),Blur(blur_limit=3, p=0.5),GaussianBlur(blur_limit=3,p=0.5)]),
Flip(p=0.5),
Transpose(p=0.5),
ShiftScaleRotate(shift_limit=0.2,scale_limit=0.2,rotate_limit=45,p=1.0),
RandomBrightnessContrast(brightness_limit=0.4, contrast_limit=0.4,p=1.0),
# HueSaturationValue(hue_shift_limit=20, sat_shift_limit=30, val_shift_limit=20,p=1.0),
CLAHE(clip_limit=4.0,tile_grid_size=(8, 8),p=1.0),
Cutout(num_holes=8,max_h_size=8,max_w_size=8, fill_value=0,p=0.5),
Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225),
max_pixel_value=255.0, p=1.0)],
bbox_params={'format':'pascal_voc','label_fields':['labels']})
else:
self.generator = Compose([
Resize(self.img_size[0], self.img_size[1],p=1.0),
CLAHE(clip_limit=4.0,tile_grid_size=(8, 8),p=1.0),
Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225),
max_pixel_value=255.0, p=1.0)],
bbox_params={'format': 'pascal_voc','label_fields':['labels']})#load_annotations已经将数据从coco格式变为pascal_voc格式
super(CocoGenerator, self).__init__(**kwargs)
def __getitem__(self, index):
"""
Keras sequence method for generating batches.
"""
group = self.groups[index]
inputs, targets = self.compute_inputs_targets(group)
return inputs, targets
def compute_inputs_targets(self, group, debug=False):
"""
Compute inputs and target outputs for the network.
"""
# load images and annotations
# list
image_group = self.load_image_group(group)
annotations_group = self.load_annotations_group(group)
# check validity of annotations
image_group, annotations_group = self.filter_annotations(image_group, annotations_group, group)
# print(annotations_group)
new_image_group = []
new_annotations_group = []
for image, annotations in zip(image_group, annotations_group):
label, bbox = annotations['labels'],annotations['bboxes']
# print(bbox,label)
aug = self.generator(image=image,bboxes=bbox,
labels=label)
image,bbox,label = aug['image'],aug['bboxes'],aug['labels']
if len(bbox) == 0:
continue
new_image_group.append(np.array(image))
bbox = np.array(bbox)
new_annotations_group.append({'labels': np.array(label),
'bboxes': np.array(bbox)})
image_group = new_image_group
annotations_group = new_annotations_group
# print(annotations_group)
# check validity of annotations
image_group, annotations_group = self.clip_transformed_annotations(image_group, annotations_group, group)
assert len(image_group) != 0
assert len(image_group) == len(annotations_group)
if self.detect_quadrangle:
# compute alphas and ratio for targets
self.compute_alphas_and_ratios(annotations_group)
# compute network inputs
inputs = self.compute_inputs(image_group, annotations_group)
# compute network targets
targets = self.compute_targets(image_group, annotations_group)
if debug:
return inputs, targets, annotations_group
return inputs, targets
def load_classes(self):
categories = self.coco.loadCats(self.coco.getCatIds())
categories.sort(key=lambda x: x['id'])
self.classes = {}
self.coco_labels = {}
self.coco_labels_inverse = {}
for c in categories:
self.coco_labels[len(self.classes)] = c['id']
self.coco_labels_inverse[c['id']] = len(self.classes)
self.classes[c['name']] = len(self.classes)
self.labels = {}
for key, value in self.classes.items():
self.labels[value] = key
def size(self):
return len(self.image_ids)
def num_classes(self):
return self.classes
def has_label(self, label):
return label in self.labels
def has_name(self, name):
return name in self.classes
def name_to_label(self, name):
return self.classes[name]
def label_to_name(self, label):
return self.labels[label]
def coco_label_to_label(self, coco_label):
return self.coco_labels_inverse[coco_label]
def coco_label_to_name(self, coco_label):
return self.label_to_name(self.coco_label_to_label(coco_label))
def label_to_coco_label(self, label):
return self.coco_labels[label]
def image_aspect_ratio(self, image_index):
image = self.coco.loadImgs(self.image_ids[image_index])[0]
return float(image['width']) / float(image['height'])
def load_image(self, image_index):
image_info = self.coco.loadImgs(self.image_ids[image_index])[0]
path = os.path.join(self.data_dir, image_info['file_name'])
image = cv2.imread(path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# image = preprocess_image(image)
return image
def load_annotations(self, image_index):
annotations_ids = self.coco.getAnnIds(imgIds=self.image_ids[image_index], iscrowd=False)
annotations = {'labels': np.empty((0,), dtype=np.float32), 'bboxes': np.empty((0, 4), dtype=np.float32)}
if len(annotations_ids) == 0:
return annotations
coco_annotations = self.coco.loadAnns(annotations_ids)
for idx, a in enumerate(coco_annotations):
# some annotations have basically no width / height, skip them
if a['bbox'][2] < 1 or a['bbox'][3] < 1:
continue
annotations['labels'] = np.concatenate(
[annotations['labels'], [a['category_id'] - 1]], axis=0)
annotations['bboxes'] = np.concatenate([annotations['bboxes'], [[
a['bbox'][0],
a['bbox'][1],
a['bbox'][0] + a['bbox'][2],
a['bbox'][1] + a['bbox'][3],
]]], axis=0)
return annotations