def examine_aug_images(filename: str, resized_images_df: pd.DataFrame, augmented_images_df: pd.DataFrame): grouped_resized = resized_images_df.groupby('filename') grouped_augmented = augmented_images_df.groupby('filename') group_r_df = grouped_resized.get_group(filename) group_r_df = group_r_df.reset_index() group_r_df = group_r_df.drop(['index'], axis=1) bb_r_array = group_r_df.drop(['filename', 'width', 'height', 'class'], axis=1).values resized_img = imageio.imread('images_train/' + filename) bbs_r = BoundingBoxesOnImage.from_xyxy_array(bb_r_array, shape=resized_img.shape) group_a_df = grouped_augmented.get_group('aug1_' + filename) group_a_df = group_a_df.reset_index() group_a_df = group_a_df.drop(['index'], axis=1) bb_a_array = group_a_df.drop(['filename', 'width', 'height', 'class'], axis=1).values augmented_img = imageio.imread('images_aug/' + 'aug1_' + filename) bbs_a = BoundingBoxesOnImage.from_xyxy_array(bb_a_array, shape=augmented_img.shape) ia.imshow( np.hstack([ bbs_r.draw_on_image(resized_img, size=2), bbs_a.draw_on_image(augmented_img, size=2) ])) # Examine random example filename = resized_images_df['filename'].unique()[np.random.randint( 0, len(resized_images_df['filename'].unique()), 1)][0] examine_aug_images(filename, resized_images_df, augmented_images_df)
def image_aug(df, images_path, aug_images_path, image_prefix, augmentor): aug_bbs_xy = pd.DataFrame(columns=[ 'filename', 'width', 'height', 'class', 'xmin', 'ymin', 'xmax', 'ymax' ]) grouped = df.groupby('filename') for filename in df['filename'].unique(): group_df = grouped.get_group(filename) group_df = group_df.reset_index() group_df = group_df.drop(['index'], axis=1) image = imageio.imread(images_path + filename) bb_array = group_df.drop(['filename', 'width', 'height', 'class'], axis=1).values bbs = BoundingBoxesOnImage.from_xyxy_array(bb_array, shape=image.shape) image_aug, bbs_aug = augmentor(image=image, bounding_boxes=bbs) bbs_aug = bbs_aug.remove_out_of_image() bbs_aug = bbs_aug.clip_out_of_image() if re.findall('Image...', str(bbs_aug)) == ['Image([]']: pass else: imageio.imwrite(aug_images_path + image_prefix + filename, image_aug) info_df = group_df.drop(['xmin', 'ymin', 'xmax', 'ymax'], axis=1) for index, _ in info_df.iterrows(): info_df.at[index, 'width'] = image_aug.shape[1] info_df.at[index, 'height'] = image_aug.shape[0] info_df['filename'] = info_df['filename'].apply( lambda x: image_prefix + x) bbs_df = bbs_obj_to_df(bbs_aug) aug_df = pd.concat([info_df, bbs_df], axis=1) aug_bbs_xy = pd.concat([aug_bbs_xy, aug_df]) aug_bbs_xy = aug_bbs_xy.reset_index() aug_bbs_xy = aug_bbs_xy.drop(['index'], axis=1) return aug_bbs_xy
def draw_ground_truth_label(labelname, img): yolo_bb = np.loadtxt('Test/' + labelname) H, W = 640, 640 if yolo_bb.size == 0: return yolo_bb imgaug_bb = np.zeros(yolo_bb.shape) if yolo_bb.ndim <= 1: class_id = yolo_bb[0] center_x, center_y, w, h = yolo_bb[1] * W, yolo_bb[2] * H, yolo_bb[ 3] * W, yolo_bb[4] * H x1 = center_x - w / 2 y1 = center_y - h / 2 x2 = center_x + w / 2 y2 = center_y + h / 2 imgaug_bb = np.array([class_id, x1, y1, x2, y2]) imgaug_bb = imgaug_bb.reshape(1, -1) else: for n, bb in enumerate(yolo_bb): class_id = bb[0] center_x, center_y, w, h = bb[1] * W, bb[2] * H, bb[3] * W, bb[ 4] * H x1 = center_x - w / 2 y1 = center_y - h / 2 x2 = center_x + w / 2 y2 = center_y + h / 2 imgaug_bb[n] = np.array([class_id, x1, y1, x2, y2]) gt = BoundingBoxesOnImage.from_xyxy_array(imgaug_bb[:, 1:], shape=img.shape) for n, bb in enumerate(gt): bb.label = imgaug_bb[n, 0].astype('int') return gt.draw_on_image(img, size=2, color=[0, 0, 255])
def __init__(self, df, x_col, x1_col, y1_col, x2_col, y2_col, a_col, dim, batch_size=32, as_floats=False, zero_mean=True, shuffle=True, augment=False, flipV=0.5, flipH=0.5, rotate=0.5, n_others=0, p_other=0.5): # Make sure the df we get has default index df.reset_index(drop=True, inplace=True) self.augment = augment self.as_floats = as_floats self.zero_mean = zero_mean self.flipH = flipH self.flipV = flipV self.rotate = rotate self.n_others = n_others self.p_other = p_other self.batch_size = batch_size self.image_paths = df[x_col] self.angles = df[a_col] self.indices = df.index.tolist() print(df.shape, min(self.indices), max(self.indices), "LEN", len(self)) self.shuffle = shuffle self.x_col = x_col self.dim = dim self.bbs = [] self.resize = iaa.Resize(self.dim) for i in self.indices: bb = np.asarray( [df[x1_col][i], df[y1_col][i], df[x2_col][i], df[y2_col][i]]) # Optionally expect and export relative values as bounding boxes: if as_floats: # bb = [c*self.dim for c in bb] # Convert from pixels to percentages if self.zero_mean: bb = (bb + 1) / 2 bb = bb * self.dim self.bbs.append( BoundingBoxesOnImage.from_xyxy_array(bb.reshape((1, 4)), (self.dim, self.dim))) self.on_epoch_end()
def get_bboxes(df, imgs_name, img_shape): bboxes_iaa = [] for img_name in imgs_name: img_data = df[df.filename == img_name] bboxes = img_data.loc[:, ["xmin", "ymin", "xmax", "ymax"]].to_numpy() bboxes = BoundingBoxesOnImage.from_xyxy_array(bboxes, shape=img_shape) bboxes_iaa.append(bboxes) return bboxes_iaa
def image_aug(df: pd.DataFrame, images_path: str, aug_images_path: str, image_prefix: str, augmentor): # create data frame which we're going to populate with augmented image info aug_bbs_xy = pd.DataFrame(columns=[ 'filename', 'width', 'height', 'class', 'xmin', 'ymin', 'xmax', 'ymax' ]) grouped = df.groupby('filename') for filename in df['filename'].unique(): # get separate data frame grouped by file name group_df = grouped.get_group(filename) group_df = group_df.reset_index() group_df = group_df.drop(['index'], axis=1) # read the image image = imageio.imread(images_path + filename) # get bounding boxes coordinates and write into array bb_array = group_df.drop(['filename', 'width', 'height', 'class'], axis=1).values # pass the array of bounding boxes coordinates to the imgaug library bbs = BoundingBoxesOnImage.from_xyxy_array(bb_array, shape=image.shape) # apply augmentation on image and on the bounding boxes image_aug, bbs_aug = augmentor(image=image, bounding_boxes=bbs) # disregard bounding boxes which have fallen out of image pane bbs_aug = bbs_aug.remove_out_of_image() # clip bounding boxes which are partially outside of image pane bbs_aug = bbs_aug.clip_out_of_image() # don't perform any actions with the image if there are no bounding boxes left in it if re.findall('Image...', str(bbs_aug)) == ['Image([]']: pass # otherwise continue else: # write augmented image to a file imageio.imwrite(aug_images_path + image_prefix + filename, image_aug) # create a data frame with augmented values of image width and height info_df = group_df.drop(['xmin', 'ymin', 'xmax', 'ymax'], axis=1) for index, _ in info_df.iterrows(): info_df.at[index, 'width'] = image_aug.shape[1] info_df.at[index, 'height'] = image_aug.shape[0] # rename filenames by adding the predifined prefix info_df['filename'] = info_df['filename'].apply( lambda x: image_prefix + x) # create a data frame with augmented bounding boxes coordinates using the function we created earlier bbs_df = bbs_obj_to_df(bbs_aug) # concat all new augmented info into new data frame aug_df = pd.concat([info_df, bbs_df], axis=1) # append rows to aug_bbs_xy data frame aug_bbs_xy = pd.concat([aug_bbs_xy, aug_df]) # return dataframe with updated images and bounding boxes annotations aug_bbs_xy = aug_bbs_xy.reset_index() aug_bbs_xy = aug_bbs_xy.drop(['index'], axis=1) return aug_bbs_xy
def aug_with_imgaug(self,image, bboxes,aug = aug): if random.random() < 0.5: bbs = BoundingBoxesOnImage.from_xyxy_array(bboxes[:,:-1], shape= image.shape) image, bbs = aug(image=image, bounding_boxes=bbs) #disregard bounding boxes which have fallen out of image pane bbs = bbs.remove_out_of_image() #clip bounding boxes which are partially outside of image pane bbs = bbs.clip_out_of_image() bboxes = np.column_stack((bbs.to_xyxy_array(),bboxes[:,-1][:bbs.to_xyxy_array().shape[0],np.newaxis])).astype(int) return image, bboxes
def resize_imgaug(df, images_path, aug_images_path, image_prefix): # create data frame which we're going to populate with augmented image info aug_bbs_xy = pd.DataFrame(columns=[ 'filename', 'width', 'height', 'class', 'xmin', 'ymin', 'xmax', 'ymax' ]) grouped = df.groupby('filename') for filename in df['filename'].unique(): # Get separate data frame grouped by file name group_df = grouped.get_group(filename) group_df = group_df.reset_index() group_df = group_df.drop(['index'], axis=1) # The only difference between if and elif statements below is the use of height_resize and width_resize augmentors # deffined previously. # If image height is greater than or equal to image width # AND greater than 600px perform resizing augmentation shrinking image height to 600px. # if group_df['height'].unique()[0] >= group_df['width'].unique()[0] and group_df['height'].unique()[0] <1024: # read the image image = imageio.imread(images_path + filename) # get bounding boxes coordinates and write into array bb_array = group_df.drop(['filename', 'width', 'height', 'class'], axis=1).values # pass the array of bounding boxes coordinates to the imgaug library bbs = BoundingBoxesOnImage.from_xyxy_array(bb_array, shape=image.shape) # apply augmentation on image and on the bounding boxes image_aug, bbs_aug = height_resize(image=image, bounding_boxes=bbs) # write augmented image to a file imageio.imwrite(aug_images_path + image_prefix + filename, image_aug) # create a data frame with augmented values of image width and height info_df = group_df.drop(['xmin', 'ymin', 'xmax', 'ymax'], axis=1) for index, _ in info_df.iterrows(): info_df.at[index, 'width'] = image_aug.shape[1] info_df.at[index, 'height'] = image_aug.shape[0] # rename filenames by adding the predifined prefix info_df['filename'] = info_df['filename'].apply( lambda x: image_prefix + x) # create a data frame with augmented bounding boxes coordinates using the function we created earlier bbs_df = bbs_obj_to_df(bbs_aug) # concat all new augmented info into new data frame aug_df = pd.concat([info_df, bbs_df], axis=1) # append rows to aug_bbs_xy data frame aug_bbs_xy = pd.concat([aug_bbs_xy, aug_df]) # if image width is greater than image height # AND greater than 600px perform resizing augmentation shrinking image width to 600px # return dataframe with updated images and bounding boxes annotations aug_bbs_xy = aug_bbs_xy.reset_index() aug_bbs_xy = aug_bbs_xy.drop(['index'], axis=1) return aug_bbs_xy
def prepare_images(labels_raw_validate_path: str, images_raw_path: str, images_validate_path: str, height: int, width: int): """ :param labels_raw_validate_path: path of folder containing original xml labels for images :param images_raw_path: path of folder containing raw images :param images_validate_path: path of folder containing images that were labelled for training + later augmented images :param height: height of resized image :param width: width of resized image :return: labels_df = dataframe of original images xml labels resize_images_df = dataframe of resized images xml labels """ # apply the function to convert all XML files in images/ folder into labels_validate.csv labels_df = xml_to_csv(os.path.dirname(labels_raw_validate_path)) labels_df.to_csv('labels_validate.csv', index=False) print('Successfully converted xml to csv.') # Copy images that were labelled files = glob.glob(labels_raw_validate_path + '/*.xml') files = [re.findall(r'\d+', x)[0] for x in files] files = [images_raw_path + '/frame' + str(x) + '.jpg' for x in files] for file in files: shutil.copy(file, images_validate_path) # file, destination # apply resizing augmentation to our images and write the updated images and bounding boxes annotations to the # DataFrame. we will not apply prefix to our files and will overwrite images in the same directory resized_images_validate_df = resize_imgaug( df=labels_df, images_path=images_validate_path, aug_images_path=images_validate_path, # source & aug folders same image_prefix='', height=height, width=width) resized_images_validate_df.to_csv('resized_images_validate.csv', index=False) # visualise the resized valentin-petkov-loL9nnBK-fE-unsplash.jpg image with bounding boxes # to make sure our bounding boxes were resized correctly as well grouped = resized_images_validate_df.groupby('filename') group_df = grouped.get_group('frame243.jpg') group_df = group_df.reset_index() group_df = group_df.drop(['index'], axis=1) bb_array = group_df.drop(['filename', 'width', 'height', 'class'], axis=1).values image = imageio.imread('images_validate/frame243.jpg') bbs = BoundingBoxesOnImage.from_xyxy_array(bb_array, shape=image.shape) ia.imshow(bbs.draw_on_image(image, size=2)) return labels_df, resized_images_validate_df
def resize_imgaug(df, images_path, aug_images_path, image_prefix): aug_bbs_xy = pd.DataFrame(columns= ['filename', 'xmin', 'ymin', 'xmax', 'ymax', 'label'] ) grouped = df.groupby('filename') for filename in df['filename'].unique(): group_df = grouped.get_group(filename) group_df = group_df.reset_index() group_df = group_df.drop(['index'], axis=1) image = imageio.imread(filename) height=image.shape[0] width=image.shape[1] fil=filename.split('/') fil1=fil[0] fil2=fil[1] if(group_df['label'].isnull().values.any()): image = imageio.imread(images_path+filename) image_aug = height_resize(image=image) imageio.imwrite(aug_images_path+'/'+fil1+'/'+image_prefix+fil2, image_aug) group_df['xmin'] ='' group_df['xmax'] ='' group_df['ymin'] ='' group_df['ymax'] ='' info_df = group_df info_df['filename'] = info_df['filename'].apply(lambda x: aug_images_path+fil1+'/'+image_prefix+fil2) aug_bbs_xy = pd.concat([aug_bbs_xy, info_df]) else: image = imageio.imread(images_path+filename) bb_array = group_df.drop(['filename', 'label'], axis=1).values bbs = BoundingBoxesOnImage.from_xyxy_array(bb_array, shape=image.shape) image_aug, bbs_aug = height_resize(image=image, bounding_boxes=bbs) imageio.imwrite(aug_images_path+'/'+fil1+'/'+image_prefix+fil2, image_aug) info_df = group_df.drop(['xmin', 'ymin', 'xmax', 'ymax'], axis=1) info_df['filename'] = info_df['filename'].apply(lambda x: aug_images_path+fil1+'/'+image_prefix+fil2) bbs_df = bbs_obj_to_df(bbs_aug) aug_df = pd.concat([info_df, bbs_df], axis=1) aug_bbs_xy = pd.concat([aug_bbs_xy, aug_df]) aug_bbs_xy = aug_bbs_xy.reset_index() aug_bbs_xy = aug_bbs_xy.drop(['index'], axis=1) return aug_bbs_xy
def analyze_pred_gt_image(data, i, threshold): filename, img, single_image_yolo_pred = read_ith_pred_result_yolo( data, i, threshold) single_image_imgaug_pred = convertYOLO2Other(single_image_yolo_pred) imgaug_bbox_single_img = BoundingBoxesOnImage.from_xyxy_array( single_image_imgaug_pred[:, 1:5], shape=img.shape) for n, bb in enumerate(imgaug_bbox_single_img): bb.label = single_image_imgaug_pred[n, 0].astype('int') print(filename) print(single_image_yolo_pred) print(imgaug_bbox_single_img) img_with_yolo = imgaug_bbox_single_img.draw_on_image(img, size=2) # draw the ground truth label_file = filename.split('.jpg')[0] + '.txt' img_with_gt = draw_ground_truth_label(label_file, img) ia.imshow(np.hstack([img_with_yolo, img_with_gt])) imageio.imwrite("sampleImages/pred_vs_gt_bbox_" + filename, np.hstack([img_with_yolo, img_with_gt]))
def augment_image(df, images_path, aug_dest_dir, image_suffix, augmentor): aug_bbs_xy = pandas.DataFrame(columns=[ 'filename', 'width', 'height', 'class', 'xmin', 'ymin', 'xmax', 'ymax' ]) grouped = df.groupby('filename') for filename in df['filename'].unique(): group_df = grouped.get_group(filename) group_df = group_df.reset_index() group_df = group_df.drop(['index'], axis=1) image = imageio.imread("{}/{}".format(images_path, filename)) bb_array = group_df.drop(['filename', 'width', 'height', 'class'], axis=1).values bbs = BoundingBoxesOnImage.from_xyxy_array(bb_array, shape=image.shape) image_aug, bbs_aug = augmentor(image=image, bounding_boxes=bbs) bbs_aug = bbs_aug.remove_out_of_image() bbs_aug = bbs_aug.clip_out_of_image() if re.findall('Image...', str(bbs_aug)) == ['Image([]']: pass else: filename_data = Path(filename) filename_final = "{}{}{}".format(filename_data.stem, image_suffix, filename_data.suffix) imageio.imwrite("{}/{}".format(aug_dest_dir, filename_final), image_aug) info_df = group_df.drop(['xmin', 'ymin', 'xmax', 'ymax'], axis=1) for index, _ in info_df.iterrows(): info_df.at[index, 'width'] = image_aug.shape[1] info_df.at[index, 'height'] = image_aug.shape[0] info_df['filename'] = filename_final bbs_df = bbs_obj_to_df(bbs_aug) aug_df = pandas.concat([info_df, bbs_df], axis=1) aug_bbs_xy = pandas.concat([aug_bbs_xy, aug_df]) aug_bbs_xy = aug_bbs_xy.reset_index() aug_bbs_xy = aug_bbs_xy.drop(['index'], axis=1) return aug_bbs_xy
def resize_imgaug(df: pd.DataFrame, images_path: str, aug_images_path: str, image_prefix: str, height: int, width: int = None): # to resize the images we create two augmenters # one is used when the image height is more than 416px and the other when the width is more than 416px if width is None: width = 'keep-aspect-ratio' height_resize = iaa.Sequential( [iaa.Resize({ "height": height, "width": width })]) width_resize = iaa.Sequential( [iaa.Resize({ "height": width, "width": height })]) # create data frame which we're going to populate with augmented image info aug_bbs_xy = pd.DataFrame(columns=[ 'filename', 'width', 'height', 'class', 'xmin', 'ymin', 'xmax', 'ymax' ]) grouped = df.groupby('filename') for filename in df['filename'].unique(): # Get separate data frame grouped by file name group_df = grouped.get_group(filename) group_df = group_df.reset_index() group_df = group_df.drop(['index'], axis=1) # The only difference between if and elif statements below is the use of height_resize and width_resize # augmentors defined previously. # If image height is greater than or equal to image width # AND greater than 416px perform resizing augmentation shrinking image height to 416px. if group_df['height'].unique()[0] >= group_df['width'].unique( )[0] and group_df['height'].unique()[0] > 416: # read the image image = imageio.imread(images_path + filename) # get bounding boxes coordinates and write into array bb_array = group_df.drop(['filename', 'width', 'height', 'class'], axis=1).values # pass the array of bounding boxes coordinates to the imgaug library bbs = BoundingBoxesOnImage.from_xyxy_array(bb_array, shape=image.shape) # apply augmentation on image and on the bounding boxes image_aug, bbs_aug = height_resize(image=image, bounding_boxes=bbs) # write augmented image to a file imageio.imwrite(aug_images_path + image_prefix + filename, image_aug) # create a data frame with augmented values of image width and height info_df = group_df.drop(['xmin', 'ymin', 'xmax', 'ymax'], axis=1) for index, _ in info_df.iterrows(): info_df.at[index, 'width'] = image_aug.shape[1] info_df.at[index, 'height'] = image_aug.shape[0] # rename filenames by adding the predifined prefix info_df['filename'] = info_df['filename'].apply( lambda x: image_prefix + x) # create a data frame with augmented bounding boxes coordinates using the function we created earlier bbs_df = bbs_obj_to_df(bbs_aug) # concat all new augmented info into new data frame aug_df = pd.concat([info_df, bbs_df], axis=1) # append rows to aug_bbs_xy data frame aug_bbs_xy = pd.concat([aug_bbs_xy, aug_df]) # if image width is greater than image height # AND greater than 416px perform resizing augmentation shrinking image width to 416px elif group_df['width'].unique()[0] > group_df['height'].unique( )[0] and group_df['width'].unique()[0] > 416: # read the image image = imageio.imread(images_path + filename) # get bounding boxes coordinates and write into array bb_array = group_df.drop(['filename', 'width', 'height', 'class'], axis=1).values # pass the array of bounding boxes coordinates to the imgaug library bbs = BoundingBoxesOnImage.from_xyxy_array(bb_array, shape=image.shape) # apply augmentation on image and on the bounding boxes image_aug, bbs_aug = width_resize(image=image, bounding_boxes=bbs) # write augmented image to a file imageio.imwrite(aug_images_path + image_prefix + filename, image_aug) # create a data frame with augmented values of image width and height info_df = group_df.drop(['xmin', 'ymin', 'xmax', 'ymax'], axis=1) for index, _ in info_df.iterrows(): info_df.at[index, 'width'] = image_aug.shape[1] info_df.at[index, 'height'] = image_aug.shape[0] # rename filenames by adding the predifined prefix info_df['filename'] = info_df['filename'].apply( lambda x: image_prefix + x) # create a data frame with augmented bounding boxes coordinates using the function we created earlier bbs_df = bbs_obj_to_df(bbs_aug) # concat all new augmented info into new data frame aug_df = pd.concat([info_df, bbs_df], axis=1) # append rows to aug_bbs_xy data frame aug_bbs_xy = pd.concat([aug_bbs_xy, aug_df]) # append image info without any changes if it's height and width are both less than 416px else: aug_bbs_xy = pd.concat([aug_bbs_xy, group_df]) # return dataframe with updated images and bounding boxes annotations aug_bbs_xy = aug_bbs_xy.reset_index() aug_bbs_xy = aug_bbs_xy.drop(['index'], axis=1) return aug_bbs_xy
def get_inner_bbs(image_path, dst_img_dir, array_info, p_numbers): ''' :param image_path: src img path :param dst_img_dir: img save path :param coor_array: label coor array :param p_numbers: Numbers of images to enhance :return: [(bbs_array, img_info), (bbs_array, img_info)] ''' try: assert array_info.shape[1] == 5 coor_array = array_info[:, :-1] cls_array = array_info[:, -1] image = Image.open(image_path) image = np.array(image) img_name = os.path.split(image_path)[-1].split(".")[0] bbs = BoundingBoxesOnImage.from_xyxy_array(coor_array, shape=image.shape) except Exception as e: print(f"err:{e}") print(array_info.shape) print(image_path) return None # # Draw the original picture # image_before = draw_bbs(image, bbs, 100) # ia.imshow(image_before) # Image augmentation sequence seq = iaa.Sequential( [ iaa.Fliplr(0.5), iaa.Crop(percent=(0, 0.1)), iaa.Sometimes(0.5, iaa.GaussianBlur(sigma=(0, 0.5))), # Strengthen or weaken the contrast in each image. iaa.LinearContrast((0.75, 1.5)), iaa.AdditiveGaussianNoise( loc=0, scale=(0.0, 0.05 * 255), per_channel=0.5), # change illumination iaa.Multiply((0.3, 1.2), per_channel=0.2), # affine transformation iaa.Affine(scale={ "x": (0.8, 1.2), "y": (0.8, 1.2) }, translate_percent={ "x": (-0.2, 0.2), "y": (-0.2, 0.2) }, rotate=(-5, 5), shear=(-8, 8)) ], random_order=True) # apply augmenters in random order res_list = [] # gen img and coor try: for epoch in range(p_numbers): image_aug, bbs_aug = seq(image=image, bounding_boxes=bbs) # bbs_aug = bbs_aug.remove_out_of_image().clip_out_of_image() # # draw aug img and label image_after = bbs_aug.draw_on_image(image_aug, size=2, color=[0, 0, 255]) ia.imshow(image_after) # save img h, w, c = image_aug.shape img_aug_name = rf'{dst_img_dir}/{img_name}_{epoch}.jpg' im = Image.fromarray(image_aug) im.save(img_aug_name) bbs_array = bbs_aug.to_xyxy_array() result_array = np.column_stack((bbs_array, cls_array)) res_list.append([result_array, (img_aug_name, h, w, c)]) except Exception as e: print(e) print(img_aug_name) return None # return coor and img info return res_list
def image_aug(df, images_path, aug_images_path, image_prefix, augmentor): aug_bbs_xy = pd.DataFrame( columns=['filename', 'xmin', 'ymin', 'xmax', 'ymax', 'label']) grouped = df.groupby(['label']) grouped2 = df.groupby(['filename']) for label in grouped.size().index: print(label) group_df = grouped.get_group(label) group_df = group_df.reset_index() group_df = group_df.drop(['index'], axis=1) counter = 0 counter3 = 0 counter2 = 0 while (group_df['filename'].unique().size + counter) < 1000: if ((group_df['filename'].unique().size + counter) > 999): break for filename in group_df['filename'].unique(): if ((group_df['filename'].unique().size + counter) > 999): break group_df2 = grouped2.get_group(filename) group_df2 = group_df2.reset_index() group_df2 = group_df2.drop(['index'], axis=1) counter += 1 yolo = str(counter) fil = filename.split('/') fil1 = fil[0] fil2 = fil[1] fil3 = fil[2] if (group_df['label'].isnull().values.any()): image = imageio.imread(filename) image_aug = augmentor(image=image) yolo = str(counter) imageio.imwrite( aug_images_path + '/' + image_prefix + yolo + '_' + fil3, image_aug) group_df2['xmin'] = '' group_df2['xmax'] = '' group_df2['ymin'] = '' group_df2['ymax'] = '' info_df = group_df2 info_df['filename'] = info_df['filename'].apply( lambda x: aug_images_path + fil1 + '/' + image_prefix + fil2) aug_bbs_xy = pd.concat([aug_bbs_xy, info_df]) counter2 += 1 else: image = imageio.imread(filename) bb_array = group_df2.drop(['filename', 'label'], axis=1).values bbs = BoundingBoxesOnImage.from_xyxy_array( bb_array, shape=image.shape) image_aug, bbs_aug = augmentor(image=image, bounding_boxes=bbs) bbs_aug = bbs_aug.remove_out_of_image() bbs_aug = bbs_aug.clip_out_of_image() if re.findall('Image...', str(bbs_aug)) == ['Image([]']: pass else: imageio.imwrite( aug_images_path + fil2 + '/' + image_prefix + yolo + '_' + fil3, image_aug) counter3 += 1 info_df = group_df2.drop( ['xmin', 'ymin', 'xmax', 'ymax'], axis=1) info_df['filename'] = info_df['filename'].apply( lambda x: aug_images_path + fil2 + '/' + image_prefix + yolo + '_' + fil3) bbs_df = bbs_obj_to_df(bbs_aug) aug_df = pd.concat([info_df, bbs_df], axis=1) aug_bbs_xy = pd.concat([aug_bbs_xy, aug_df]) aug_bbs_xy = aug_bbs_xy.reset_index() aug_bbs_xy = aug_bbs_xy.drop(['index'], axis=1) return aug_bbs_xy
def transform(csv_input_path, src_dir, dest_dir, area_threshold, csv_output_path=None, num_transform=5, test_mode=False, keep_orig_img=False): df = pd.read_csv(csv_input_path) df_drop_duplicates = df.drop_duplicates() print(">>> Original df: {} objects".format(df.shape[0])) print(">>> Dropped-duplicates df: {} objects".format( df_drop_duplicates.shape[0])) df_out = pd.DataFrame(columns=df.columns) img_list = sorted(df.filename.unique()) skip_gen_img = 0 sequence = create_sequence() if test_mode: img_list = img_list[:30] print(">>> Testing with 30 images.") else: expected = ( num_transform + 1) * df.shape[0] if keep_orig_img else num_transform * df.shape[0] print('>>> Number of expected objects: {}'.format(expected)) with tqdm(img_list, unit="imgs") as t: for img in t: t.set_postfix(skipped_gen_imgs=skip_gen_img) if not img.lower().endswith("jpg"): continue name, ext = os.path.splitext(img) img_data = df_drop_duplicates[df_drop_duplicates.filename == img] num_duplicates = int(df[df.filename == img].shape[0] / img_data.shape[0]) img_shape = (img_data.iloc[0, 2], img_data.iloc[0, 1]) img_area = img_shape[0] * img_shape[1] bboxes = np.asarray(img_data.iloc[:, 4:], dtype=np.int) bboxes_iaa = BoundingBoxesOnImage.from_xyxy_array(bboxes, shape=img_shape) suffix = 0 img_array = cv2.imread(os.path.join(src_dir, img)) # If keeping original image and the bounding boxes satisfy the threshold condition. if keep_orig_img and all( cal_bboxes_fraction(img_area, bboxes) >= area_threshold): df_out = df_out.append(img_data, ignore_index=True) cv2.imwrite(os.path.join(dest_dir, img), img_array) for _ in range(num_transform * num_duplicates): transformed_img, transformed_bboxes = sequence( image=img_array, bounding_boxes=bboxes_iaa) for transformed_bbox in transformed_bboxes.bounding_boxes: if not transformed_bbox.is_fully_within_image( transformed_img): skip_gen_img += 1 break else: transformed_bboxes = transformed_bboxes.to_xyxy_array( dtype=np.int) if any( cal_bboxes_fraction(img_area, transformed_bboxes) < area_threshold): skip_gen_img += 1 continue transformed_name = name + "_{}".format(suffix) + ext transformed_path = os.path.join(dest_dir, transformed_name) # When the file exists while os.path.isfile(transformed_path): suffix += 1 transformed_name = name + "_{}".format(suffix) + ext transformed_path = os.path.join( dest_dir, transformed_name) transformed_data = copy_data(img_data, transformed_name, transformed_bboxes) df_out = df_out.append(transformed_data, ignore_index=True) cv2.imwrite(os.path.join(dest_dir, transformed_name), transformed_img) suffix += 1 print(''' ================================= Total images processed: {} Total images generated: {} Total generated images skipped: {} ================================= '''.format(len(img_list), len(os.listdir(dest_dir)), skip_gen_img)) # Shuffle the DataFrame df_out = df_out.sample(frac=1.0).reset_index(drop=True) if csv_output_path is not None: df_out.to_csv(csv_output_path, index=False) return df
def up_sample_positives(self): def ia_format_bbox(bbox): return [bbox[0], bbox[1], bbox[0] + bbox[2], bbox[1] + bbox[3]] def reverse_ia_format_bbox(bbox): new_bbox = bbox new_bbox[2] = bbox[2] - bbox[0] new_bbox[3] = bbox[3] - bbox[1] return new_bbox augmented_annotations = {} augmentor = iaa.SomeOf(2, [ iaa.Affine(scale=(0.5, 1.5)), iaa.Affine(rotate=(-60, 60)), iaa.Affine(translate_percent={ "x": (-0.3, 0.3), "y": (-0.3, 0.3) }), iaa.Fliplr(1), iaa.Multiply((0.5, 1.5)), iaa.GaussianBlur(sigma=(1.0, 3.0)), iaa.AdditiveGaussianNoise(scale=(0.03 * 255, 0.05 * 255)) ]) positive_annotations = self.positive_annotations() for _, image_filename in enumerate(positive_annotations.keys()): metadata = positive_annotations[image_filename] bboxes = [] for triplet in metadata: tomato = self.mapping[triplet["id"]] assert tomato bbox = triplet["box"] bboxes.append(ia_format_bbox(bbox)) img_file_path = os.path.join(self.data_dir_path, image_filename) image = imageio.imread(img_file_path) ia_boxxes = BoundingBoxesOnImage.from_xyxy_array(np.array(bboxes), shape=image.shape) for epoch in range(self.upsampling_factor): aug_img, aug_bboxes = augmentor(image=image, bounding_boxes=ia_boxxes) aug_bboxes = aug_bboxes.remove_out_of_image() aug_bboxes = aug_bboxes.clip_out_of_image() aug_bboxes = aug_bboxes.to_xyxy_array() if aug_bboxes.size == 0: continue aug_bboxes = aug_bboxes.tolist() aug_bboxes = [ reverse_ia_format_bbox(aug_bbox) for aug_bbox in aug_bboxes ] aug_img_filename = '{}_aug_{}.jpg'.format( os.path.splitext(image_filename)[0], epoch) aug_img_filepath = os.path.join(self.formated_data_dir_path, 'JPEGImages', aug_img_filename) imageio.imwrite(aug_img_filepath, aug_img) augmented_annotations.setdefault(aug_img_filename, []) for aug_bbox in aug_bboxes: augmented_annotations[aug_img_filename].append({ "box": aug_bbox, "id": "9f2c42629209f86b2d5fbe152eb54803_lab", "is_background": False }) return augmented_annotations
t.append(coords[i].split(',')) t = np.array(t).astype(np.uint32) coords = t[:,0:4] class_idx = t[:,-1] class_det = np.take(classes, class_idx) #% #ia.seed(1) # for giving one box # bbs = BoundingBoxesOnImage([ # BoundingBox(x1=coords[0], x2=coords[2], y1=coords[1], y2=coords[3]) # ], shape=img.shape) bbs = BoundingBoxesOnImage.from_xyxy_array(coords, shape=img.shape) for i in range(len(bbs)): bbs[i].label = class_det[i] #ia.imshow(bbs.draw_on_image(img, color=[255, 0, 0], size=10)) ''' Start applying augmentations ''' num = np.random.randint(1, 100) if (num % 2) == 0: image_aug, bbs_aug = seq_1.augment(image=img, bounding_boxes=bbs) elif (num % 2) != 0: image_aug, bbs_aug = seq_2.augment(image=img, bounding_boxes=bbs) # disregard bounding boxes which have fallen out of image pane bbs_aug = bbs_aug.remove_out_of_image() # clip bounding boxes which are partially outside of image pane
def normalize_bounding_boxes(inputs, shapes=None): # TODO get rid of this deferred import from imgaug.augmentables.bbs import BoundingBox, BoundingBoxesOnImage shapes = _preprocess_shapes(shapes) ntype = estimate_bounding_boxes_norm_type(inputs) _assert_exactly_n_shapes_partial = functools.partial( _assert_exactly_n_shapes, from_ntype=ntype, to_ntype="List[BoundingBoxesOnImage]", shapes=shapes) if ntype == "None": return None elif ntype in ["array[float]", "array[int]", "array[uint]"]: _assert_single_array_ndim(inputs, 3, "(N,B,4)", "BoundingBoxesOnImage") _assert_single_array_last_dim_exactly(inputs, 4, "BoundingBoxesOnImage") _assert_exactly_n_shapes_partial(n=len(inputs)) return [ BoundingBoxesOnImage.from_xyxy_array(attr_i, shape=shape) for attr_i, shape in zip(inputs, shapes) ] elif ntype == "tuple[number,size=4]": _assert_exactly_n_shapes_partial(n=1) return [ BoundingBoxesOnImage([ BoundingBox( x1=inputs[0], y1=inputs[1], x2=inputs[2], y2=inputs[3]) ], shape=shapes[0]) ] elif ntype == "BoundingBox": _assert_exactly_n_shapes_partial(n=1) return [BoundingBoxesOnImage([inputs], shape=shapes[0])] elif ntype == "BoundingBoxesOnImage": return [inputs] elif ntype == "iterable[empty]": return None elif ntype in [ "iterable-array[float]", "iterable-array[int]", "iterable-array[uint]" ]: _assert_many_arrays_ndim(inputs, 2, "(B,4)", "BoundingBoxesOnImage") _assert_many_arrays_last_dim_exactly(inputs, 4, "BoundingBoxesOnImage") _assert_exactly_n_shapes_partial(n=len(inputs)) return [ BoundingBoxesOnImage.from_xyxy_array(attr_i, shape=shape) for attr_i, shape in zip(inputs, shapes) ] elif ntype == "iterable-tuple[number,size=4]": _assert_exactly_n_shapes_partial(n=1) return [ BoundingBoxesOnImage([ BoundingBox(x1=x1, y1=y1, x2=x2, y2=y2) for x1, y1, x2, y2 in inputs ], shape=shapes[0]) ] elif ntype == "iterable-BoundingBox": _assert_exactly_n_shapes_partial(n=1) return [BoundingBoxesOnImage(inputs, shape=shapes[0])] elif ntype == "iterable-BoundingBoxesOnImage": return inputs elif ntype == "iterable-iterable[empty]": return None elif ntype == "iterable-iterable-tuple[number,size=4]": _assert_exactly_n_shapes_partial(n=len(inputs)) return [ BoundingBoxesOnImage.from_xyxy_array(np.array(attr_i, dtype=np.float32), shape=shape) for attr_i, shape in zip(inputs, shapes) ] else: assert ntype == "iterable-iterable-BoundingBox", ( "Got unknown normalization type '%s'." % (ntype, )) _assert_exactly_n_shapes_partial(n=len(inputs)) return [ BoundingBoxesOnImage(attr_i, shape=shape) for attr_i, shape in zip(inputs, shapes) ]
def normalize_bounding_boxes(inputs, shapes=None): # TODO get rid of this deferred import from imgaug.augmentables.bbs import BoundingBox, BoundingBoxesOnImage shapes = _preprocess_shapes(shapes) ntype = estimate_bounding_boxes_norm_type(inputs) _assert_exactly_n_shapes_partial = functools.partial( _assert_exactly_n_shapes, from_ntype=ntype, to_ntype="List[BoundingBoxesOnImage]", shapes=shapes) if ntype == "None": return None elif ntype in ["array[float]", "array[int]", "array[uint]"]: _assert_single_array_ndim(inputs, 3, "(N,B,4)", "BoundingBoxesOnImage") _assert_single_array_last_dim_exactly(inputs, 4, "BoundingBoxesOnImage") _assert_exactly_n_shapes_partial(n=len(inputs)) return [ BoundingBoxesOnImage.from_xyxy_array(attr_i, shape=shape) for attr_i, shape in zip(inputs, shapes) ] elif ntype == "tuple[number,size=4]": _assert_exactly_n_shapes_partial(n=1) return [ BoundingBoxesOnImage( [BoundingBox( x1=inputs[0], y1=inputs[1], x2=inputs[2], y2=inputs[3])], shape=shapes[0]) ] elif ntype == "BoundingBox": _assert_exactly_n_shapes_partial(n=1) return [BoundingBoxesOnImage([inputs], shape=shapes[0])] elif ntype == "BoundingBoxesOnImage": return [inputs] elif ntype == "iterable[empty]": return None elif ntype in ["iterable-array[float]", "iterable-array[int]", "iterable-array[uint]"]: _assert_many_arrays_ndim(inputs, 2, "(B,4)", "BoundingBoxesOnImage") _assert_many_arrays_last_dim_exactly(inputs, 4, "BoundingBoxesOnImage") _assert_exactly_n_shapes_partial(n=len(inputs)) return [ BoundingBoxesOnImage.from_xyxy_array(attr_i, shape=shape) for attr_i, shape in zip(inputs, shapes) ] elif ntype == "iterable-tuple[number,size=4]": _assert_exactly_n_shapes_partial(n=1) return [ BoundingBoxesOnImage( [BoundingBox(x1=x1, y1=y1, x2=x2, y2=y2) for x1, y1, x2, y2 in inputs], shape=shapes[0]) ] elif ntype == "iterable-BoundingBox": _assert_exactly_n_shapes_partial(n=1) return [BoundingBoxesOnImage(inputs, shape=shapes[0])] elif ntype == "iterable-BoundingBoxesOnImage": return inputs elif ntype == "iterable-iterable[empty]": return None elif ntype == "iterable-iterable-tuple[number,size=4]": _assert_exactly_n_shapes_partial(n=len(inputs)) return [ BoundingBoxesOnImage.from_xyxy_array( np.array(attr_i, dtype=np.float32), shape=shape) for attr_i, shape in zip(inputs, shapes) ] else: assert ntype == "iterable-iterable-BoundingBox", ( "Got unknown normalization type '%s'." % (ntype,)) _assert_exactly_n_shapes_partial(n=len(inputs)) return [BoundingBoxesOnImage(attr_i, shape=shape) for attr_i, shape in zip(inputs, shapes)]