├── Helpers.py ├── README.md ├── aug.py ├── background ├── img00000.jpg ├── img00000.txt ├── img00001.jpg └── img00001.txt ├── break ├── img00000.jpg ├── img00000.txt ├── img00001.jpg └── img00001.txt ├── createTrain.sh ├── crops ├── 0000003_crop_39.jpg ├── 0000003_crop_60.jpg ├── 0000003_crop_73.jpg ├── 0000003_crop_74.jpg ├── 0000003_crop_87.jpg ├── 0000004_crop_28.jpg ├── 0000004_crop_30.jpg ├── 0000004_crop_5.jpg ├── 0000004_crop_6.jpg ├── 0000004_crop_7.jpg ├── 0000004_crop_8.jpg ├── 0000005_crop_5.jpg ├── 0000014_crop_15.jpg ├── 0000024_crop_5.jpg ├── 0000188_crop_44.jpg ├── 0000189_crop_76.jpg ├── 0000189_crop_77.jpg ├── 0000190_crop_28.jpg ├── 0000239_crop_23.jpg └── 0000242_crop_15.jpg ├── demo.py ├── figs ├── 2018-11-03_07_45_09_1_augment.jpg └── 2018-11-03_07_45_09_1_augment.txt ├── img ├── 2018-11-03_07_45_09_1.jpg └── 2018-11-03_07_45_09_1.txt ├── save ├── img00000_augment.jpg ├── img00000_augment.txt ├── img00001_augment.jpg └── img00001_augment.txt ├── small.txt ├── train.txt └── util.py /Helpers.py: -------------------------------------------------------------------------------- 1 | import glob 2 | import cv2 as cv2 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | # import random 6 | import math 7 | from tqdm import tqdm 8 | 9 | 10 | def load_images(path): 11 | image_list = [] 12 | images = glob.glob(path) 13 | for index in range(len(images)): 14 | image = cv2.cvtColor(cv2.imread(images[index]), cv2.COLOR_BGR2RGB) 15 | image_list.append(image) 16 | # image_list.append(cv2.resize(image,(1280,720))) 17 | 18 | return image_list 19 | 20 | 21 | def read_images(path): 22 | images = glob.glob(path) 23 | return images 24 | 25 | 26 | def load_images_from_path(path): 27 | image_list = [] 28 | for p in tqdm(path): 29 | image = cv2.cvtColor(cv2.imread(p), cv2.COLOR_BGR2RGB) 30 | image_list.append(image) 31 | return image_list 32 | 33 | 34 | def replace_labels(path): 35 | labelpath = [] 36 | for p in path: 37 | labelpath.append(p.replace('.jpg', '.txt')) 38 | return labelpath 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Simple python implementation of Augmentation for small object detection, as described in [Augmentation for small object detection 2 | ](https://arxiv.org/pdf/1902.07296.pdf). 3 | 4 | ![img1](https://github.com/gmayday1997/SmallObjectAugmentation/blob/master/img/2018-11-03_07_45_09_1.jpg) 5 | ![img2](https://github.com/gmayday1997/SmallObjectAugmentation/blob/master/figs/2018-11-03_07_45_09_1_augment.jpg) 6 | 7 | ## Demo 8 | ```shell 9 | cd $ROOT 10 | python demo.py 11 | ``` 12 | -------------------------------------------------------------------------------- /aug.py: -------------------------------------------------------------------------------- 1 | # import glob 2 | import cv2 as cv2 3 | import numpy as np 4 | # from PIL import Image 5 | import random 6 | import math 7 | from os.path import basename, split, join, dirname 8 | from util import * 9 | 10 | 11 | def find_str(filename): 12 | if 'train' in filename: 13 | return dirname(filename[filename.find('train'):]) 14 | else: 15 | return dirname(filename[filename.find('val'):]) 16 | 17 | 18 | def convert_all_boxes(shape, anno_infos, yolo_label_txt_dir): 19 | height, width, n = shape 20 | label_file = open(yolo_label_txt_dir, 'w') 21 | for anno_info in anno_infos: 22 | target_id, x1, y1, x2, y2 = anno_info 23 | b = (float(x1), float(x2), float(y1), float(y2)) 24 | bb = convert((width, height), b) 25 | label_file.write(str(target_id) + " " + " ".join([str(a) for a in bb]) + '\n') 26 | 27 | 28 | def save_crop_image(save_crop_base_dir, image_dir, idx, roi): 29 | crop_save_dir = join(save_crop_base_dir, find_str(image_dir)) 30 | check_dir(crop_save_dir) 31 | crop_img_save_dir = join(crop_save_dir, basename(image_dir)[:-3] + '_crop_' + str(idx) + '.jpg') 32 | cv2.imwrite(crop_img_save_dir, roi) 33 | 34 | 35 | def copysmallobjects(image_dir, label_dir, save_base_dir, save_crop_base_dir=None, 36 | save_annoation_base_dir=None): 37 | image = cv2.imread(image_dir) 38 | 39 | labels = read_label_txt(label_dir) 40 | if len(labels) == 0: return 41 | rescale_labels = rescale_yolo_labels(labels, image.shape) # 转换坐标表示 42 | all_boxes = [] 43 | 44 | for idx, rescale_label in enumerate(rescale_labels): 45 | 46 | all_boxes.append(rescale_label) 47 | # 目标的长宽 48 | rescale_label_height, rescale_label_width = rescale_label[4] - rescale_label[2], rescale_label[3] - \ 49 | rescale_label[1] 50 | 51 | if (issmallobject((rescale_label_height, rescale_label_width), thresh=64 * 64) and rescale_label[0] == '1'): 52 | roi = image[rescale_label[2]:rescale_label[4], rescale_label[1]:rescale_label[3]] 53 | 54 | new_bboxes = random_add_patches(rescale_label, rescale_labels, image.shape, paste_number=2, iou_thresh=0.2) 55 | count = 0 56 | 57 | # 将新生成的位置加入到label,并在相应位置画出物体 58 | for new_bbox in new_bboxes: 59 | count += 1 60 | all_boxes.append(new_bbox) 61 | cl, bbox_left, bbox_top, bbox_right, bbox_bottom = new_bbox[0], new_bbox[1], new_bbox[2], new_bbox[3], \ 62 | new_bbox[4] 63 | try: 64 | if (count > 1): 65 | roi = flip_bbox(roi) 66 | image[bbox_top:bbox_bottom, bbox_left:bbox_right] = roi 67 | except ValueError: 68 | continue 69 | 70 | dir_name = find_str(image_dir) 71 | save_dir = join(save_base_dir, dir_name) 72 | check_dir(save_dir) 73 | yolo_txt_dir = join(save_dir, basename(image_dir.replace('.jpg', '_augment.txt'))) 74 | cv2.imwrite(join(save_dir, basename(image_dir).replace('.jpg', '_augment.jpg')), image) 75 | convert_all_boxes(image.shape, all_boxes, yolo_txt_dir) 76 | 77 | 78 | def GaussianBlurImg(image): 79 | # 高斯模糊 80 | ran = random.randint(0, 9) 81 | if ran % 2 == 1: 82 | image = cv2.GaussianBlur(image, ksize=(ran, ran), sigmaX=0, sigmaY=0) 83 | else: 84 | pass 85 | return image 86 | 87 | 88 | def suo_fang(image, area_max=2000, area_min=1000): 89 | # 改变图片大小 90 | height, width, channels = image.shape 91 | 92 | while (height*width) > area_max: 93 | image = cv2.resize(image, (int(width * 0.9),int(height * 0.9))) 94 | height, width, channels = image.shape 95 | height,width = int(height*0.9),int(width*0.9) 96 | 97 | while (height*width) < area_min: 98 | image = cv2.resize(image, (int(width * 1.1),int(height * 1.1))) 99 | height, width, channels = image.shape 100 | height,width = int(height*1.1),int(width*1.1) 101 | 102 | return image 103 | 104 | 105 | def copysmallobjects2(image_dir, label_dir, save_base_dir, small_img_dir): 106 | image = cv2.imread(image_dir) 107 | labels = read_label_txt(label_dir) 108 | if len(labels) == 0: 109 | return 110 | rescale_labels = rescale_yolo_labels(labels, image.shape) # 转换坐标表示 111 | all_boxes = [] 112 | for _, rescale_label in enumerate(rescale_labels): 113 | all_boxes.append(rescale_label) 114 | 115 | for small_img_dirs in small_img_dir: 116 | image_bbox = cv2.imread(small_img_dirs) 117 | #roi = image_bbox 118 | roi = suo_fang(image_bbox,area_max=3000,area_min=1500) 119 | 120 | new_bboxes = random_add_patches2(roi.shape, rescale_labels, image.shape, paste_number=1, iou_thresh=0) 121 | count = 0 122 | for new_bbox in new_bboxes: 123 | count += 1 124 | 125 | cl, bbox_left, bbox_top, bbox_right, bbox_bottom = new_bbox[0], new_bbox[1], new_bbox[2], new_bbox[3], \ 126 | new_bbox[4] 127 | #roi = GaussianBlurImg(roi) # 高斯模糊 128 | height, width, channels = roi.shape 129 | center = (int(width / 2),int(height / 2)) 130 | #ran_point = (int((bbox_top+bbox_bottom)/2),int((bbox_left+bbox_right)/2)) 131 | mask = 255 * np.ones(roi.shape, roi.dtype) 132 | 133 | try: 134 | if count > 1: 135 | roi = flip_bbox(roi) 136 | #image[bbox_top:bbox_bottom, bbox_left:bbox_right] = roi 137 | #image[bbox_top:bbox_bottom, bbox_left:bbox_right] = cv2.addWeighted(image[bbox_top:bbox_bottom, bbox_left:bbox_right], 138 | # 0.5,roi,0.5,0) #图片融合 139 | 140 | # 泊松融合 141 | #image = cv2.seamlessClone(roi, image, mask, ran_point, cv2.NORMAL_CLONE) 142 | #print(str(bbox_bottom-bbox_top) + "|" + str(bbox_right-bbox_left)) 143 | #print(roi.shape) 144 | #print(mask.shape) 145 | image[bbox_top:bbox_bottom, bbox_left:bbox_right] = cv2.seamlessClone(roi, image[bbox_top:bbox_bottom, bbox_left:bbox_right], 146 | mask, center, cv2.NORMAL_CLONE) 147 | all_boxes.append(new_bbox) 148 | rescale_labels.append(new_bbox) 149 | except ValueError: 150 | print("---") 151 | continue 152 | dir_name = find_str(image_dir) 153 | save_dir = join(save_base_dir, dir_name) 154 | check_dir(save_dir) 155 | yolo_txt_dir = join(save_dir, basename(image_dir.replace('.jpg', '_augment.txt'))) 156 | cv2.imwrite(join(save_dir, basename(image_dir).replace('.jpg', '_augment.jpg')), image) 157 | convert_all_boxes(image.shape, all_boxes, yolo_txt_dir) 158 | -------------------------------------------------------------------------------- /background/img00000.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/background/img00000.jpg -------------------------------------------------------------------------------- /background/img00000.txt: -------------------------------------------------------------------------------- 1 | 0 0.265364583333 0.139130434783 0.0151041666667 0.0369565217391 2 | 0 0.284114583333 0.151086956522 0.0119791666667 0.0173913043478 3 | 0 0.3515625 0.179347826087 0.015625 0.0239130434783 4 | -------------------------------------------------------------------------------- /background/img00001.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/background/img00001.jpg -------------------------------------------------------------------------------- /background/img00001.txt: -------------------------------------------------------------------------------- 1 | 0 0.2671875 0.139130434783 0.021875 0.0434782608696 2 | 0 0.284114583333 0.154891304348 0.0119791666667 0.025 3 | 0 0.350520833333 0.179347826087 0.0177083333333 0.0239130434783 4 | -------------------------------------------------------------------------------- /break/img00000.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/break/img00000.jpg -------------------------------------------------------------------------------- /break/img00000.txt: -------------------------------------------------------------------------------- 1 | 0 0.265364583333 0.139130434783 0.0151041666667 0.0369565217391 2 | 0 0.284114583333 0.151086956522 0.0119791666667 0.0173913043478 3 | 0 0.3515625 0.179347826087 0.015625 0.0239130434783 4 | -------------------------------------------------------------------------------- /break/img00001.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/break/img00001.jpg -------------------------------------------------------------------------------- /break/img00001.txt: -------------------------------------------------------------------------------- 1 | 0 0.2671875 0.139130434783 0.021875 0.0434782608696 2 | 0 0.284114583333 0.154891304348 0.0119791666667 0.025 3 | 0 0.350520833333 0.179347826087 0.0177083333333 0.0239130434783 4 | -------------------------------------------------------------------------------- /createTrain.sh: -------------------------------------------------------------------------------- 1 | find ./background -maxdepth 4 -name "*.jpg" | sort > train.txt 2 | find ./crops -maxdepth 4 -name "*.jpg" | sort > small.txt 3 | -------------------------------------------------------------------------------- /crops/0000003_crop_39.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000003_crop_39.jpg -------------------------------------------------------------------------------- /crops/0000003_crop_60.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000003_crop_60.jpg -------------------------------------------------------------------------------- /crops/0000003_crop_73.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000003_crop_73.jpg -------------------------------------------------------------------------------- /crops/0000003_crop_74.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000003_crop_74.jpg -------------------------------------------------------------------------------- /crops/0000003_crop_87.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000003_crop_87.jpg -------------------------------------------------------------------------------- /crops/0000004_crop_28.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000004_crop_28.jpg -------------------------------------------------------------------------------- /crops/0000004_crop_30.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000004_crop_30.jpg -------------------------------------------------------------------------------- /crops/0000004_crop_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000004_crop_5.jpg -------------------------------------------------------------------------------- /crops/0000004_crop_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000004_crop_6.jpg -------------------------------------------------------------------------------- /crops/0000004_crop_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000004_crop_7.jpg -------------------------------------------------------------------------------- /crops/0000004_crop_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000004_crop_8.jpg -------------------------------------------------------------------------------- /crops/0000005_crop_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000005_crop_5.jpg -------------------------------------------------------------------------------- /crops/0000014_crop_15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000014_crop_15.jpg -------------------------------------------------------------------------------- /crops/0000024_crop_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000024_crop_5.jpg -------------------------------------------------------------------------------- /crops/0000188_crop_44.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000188_crop_44.jpg -------------------------------------------------------------------------------- /crops/0000189_crop_76.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000189_crop_76.jpg -------------------------------------------------------------------------------- /crops/0000189_crop_77.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000189_crop_77.jpg -------------------------------------------------------------------------------- /crops/0000190_crop_28.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000190_crop_28.jpg -------------------------------------------------------------------------------- /crops/0000239_crop_23.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000239_crop_23.jpg -------------------------------------------------------------------------------- /crops/0000242_crop_15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/crops/0000242_crop_15.jpg -------------------------------------------------------------------------------- /demo.py: -------------------------------------------------------------------------------- 1 | import aug as am 2 | import Helpers as hp 3 | from util import * 4 | import os 5 | from os.path import join 6 | from tqdm import tqdm 7 | import random 8 | 9 | base_dir = os.getcwd() 10 | 11 | save_base_dir = join(base_dir, 'save') 12 | 13 | check_dir(save_base_dir) 14 | 15 | imgs_dir = [f.strip() for f in open(join(base_dir, 'train.txt')).readlines()] 16 | labels_dir = hp.replace_labels(imgs_dir) 17 | 18 | small_imgs_dir = [f.strip() for f in open(join(base_dir, 'small.txt')).readlines()] 19 | random.shuffle(small_imgs_dir) 20 | 21 | for image_dir, label_dir in tqdm(zip(imgs_dir, labels_dir)): 22 | small_img = [] 23 | for x in range(8): 24 | if small_imgs_dir == []: 25 | #exit() 26 | small_imgs_dir = [f.strip() for f in open(join(base_dir,'small.txt')).readlines()] 27 | random.shuffle(small_imgs_dir) 28 | small_img.append(small_imgs_dir.pop()) 29 | am.copysmallobjects2(image_dir, label_dir, save_base_dir,small_img) 30 | -------------------------------------------------------------------------------- /figs/2018-11-03_07_45_09_1_augment.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/figs/2018-11-03_07_45_09_1_augment.jpg -------------------------------------------------------------------------------- /figs/2018-11-03_07_45_09_1_augment.txt: -------------------------------------------------------------------------------- 1 | 1 0.6 0.5898148148148148 0.0125 0.061111111111111116 2 | 1 0.346875 0.5916666666666667 0.0125 0.061111111111111116 3 | 1 0.2708333333333333 0.5750000000000001 0.0125 0.061111111111111116 4 | 0 0.3046875 0.44537037037037036 0.065625 0.1388888888888889 5 | 0 0.10625 0.8481481481481482 0.19375 0.3 6 | 0 0.6140625 0.40740740740740744 0.026041666666666668 0.037037037037037035 7 | 0 0.6359375 0.375 0.036458333333333336 0.07222222222222223 8 | -------------------------------------------------------------------------------- /img/2018-11-03_07_45_09_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/img/2018-11-03_07_45_09_1.jpg -------------------------------------------------------------------------------- /img/2018-11-03_07_45_09_1.txt: -------------------------------------------------------------------------------- 1 | 1 0.602083333333 0.591666666667 0.0125 0.0611111111111 2 | 0 0.306770833333 0.449074074074 0.065625 0.138888888889 3 | 0 0.108333333333 0.85 0.19375 0.3 4 | 0 0.616145833333 0.411111111111 0.0260416666667 0.037037037037 5 | 0 0.636979166667 0.376851851852 0.0364583333333 0.0722222222222 6 | -------------------------------------------------------------------------------- /save/img00000_augment.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/save/img00000_augment.jpg -------------------------------------------------------------------------------- /save/img00000_augment.txt: -------------------------------------------------------------------------------- 1 | 0 0.2643229166666667 0.13804347826086957 0.015104166666666667 0.03695652173913044 2 | 0 0.2830729166666667 0.15 0.011979166666666666 0.017391304347826087 3 | 0 0.35104166666666664 0.1782608695652174 0.015625 0.02391304347826087 4 | 1 0.8265625 0.6293478260869565 0.011458333333333333 0.06739130434782609 5 | 1 0.5752604166666666 0.7494565217391305 0.021354166666666667 0.07934782608695652 6 | 1 0.6140625 0.8445652173913044 0.014583333333333334 0.09565217391304348 7 | 1 0.72890625 0.6347826086956522 0.015104166666666667 0.09130434782608696 8 | 1 0.43515624999999997 0.7663043478260869 0.022395833333333334 0.0782608695652174 9 | 1 0.7671875 0.5396739130434782 0.017708333333333333 0.0923913043478261 10 | 1 0.5122395833333333 0.9032608695652175 0.0203125 0.08695652173913043 11 | 1 0.53046875 0.5679347826086957 0.018229166666666668 0.08586956521739131 12 | 1 0.6596354166666667 0.7711956521739131 0.021354166666666667 0.07282608695652174 13 | 1 0.490625 0.8190217391304347 0.01875 0.08804347826086957 14 | -------------------------------------------------------------------------------- /save/img00001_augment.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmayday1997/SmallObjectAugmentation/63c59a3a57e0be96594509fa6c0ef4aed85d805f/save/img00001_augment.jpg -------------------------------------------------------------------------------- /save/img00001_augment.txt: -------------------------------------------------------------------------------- 1 | 0 0.26666666666666666 0.13804347826086957 0.021875 0.043478260869565216 2 | 0 0.2830729166666667 0.15380434782608696 0.011979166666666666 0.025 3 | 0 0.3494791666666667 0.1782608695652174 0.017708333333333333 0.02391304347826087 4 | 1 0.94296875 0.6923913043478261 0.013020833333333334 0.07608695652173914 5 | 1 0.47031249999999997 0.8630434782608696 0.015625 0.07173913043478261 6 | 1 0.62265625 0.5782608695652174 0.024479166666666666 0.08478260869565217 7 | 1 0.29921875 0.5173913043478261 0.0203125 0.07173913043478261 8 | 1 0.7361979166666667 0.5119565217391304 0.013020833333333334 0.06304347826086956 9 | 1 0.3963541666666667 0.6402173913043478 0.016666666666666666 0.1 10 | 1 0.4236979166666667 0.7717391304347826 0.0171875 0.08260869565217391 11 | 1 0.9356770833333333 0.8913043478260869 0.0203125 0.09782608695652174 12 | 1 0.8783854166666667 0.5608695652173913 0.015104166666666667 0.09130434782608696 13 | 1 0.8260416666666667 0.5233695652173913 0.019791666666666666 0.08369565217391305 14 | -------------------------------------------------------------------------------- /small.txt: -------------------------------------------------------------------------------- 1 | ./crops/0000003_crop_39.jpg 2 | ./crops/0000003_crop_60.jpg 3 | ./crops/0000003_crop_73.jpg 4 | ./crops/0000003_crop_74.jpg 5 | ./crops/0000003_crop_87.jpg 6 | ./crops/0000004_crop_28.jpg 7 | ./crops/0000004_crop_30.jpg 8 | ./crops/0000004_crop_5.jpg 9 | ./crops/0000004_crop_6.jpg 10 | ./crops/0000004_crop_7.jpg 11 | ./crops/0000004_crop_8.jpg 12 | ./crops/0000005_crop_5.jpg 13 | ./crops/0000014_crop_15.jpg 14 | ./crops/0000024_crop_5.jpg 15 | ./crops/0000188_crop_44.jpg 16 | ./crops/0000189_crop_76.jpg 17 | ./crops/0000189_crop_77.jpg 18 | ./crops/0000190_crop_28.jpg 19 | ./crops/0000239_crop_23.jpg 20 | ./crops/0000242_crop_15.jpg 21 | -------------------------------------------------------------------------------- /train.txt: -------------------------------------------------------------------------------- 1 | ./background/img00000.jpg 2 | ./background/img00001.jpg 3 | -------------------------------------------------------------------------------- /util.py: -------------------------------------------------------------------------------- 1 | import os 2 | import cv2 3 | import numpy as np 4 | from os.path import join, split 5 | import random 6 | 7 | 8 | def convert(size, box): 9 | dw = 1. / (size[0]) 10 | dh = 1. / (size[1]) 11 | x = (box[0] + box[1]) / 2.0 - 1 12 | y = (box[2] + box[3]) / 2.0 - 1 13 | w = box[1] - box[0] 14 | h = box[3] - box[2] 15 | x = x * dw 16 | w = w * dw 17 | y = y * dh 18 | h = h * dh 19 | return (x, y, w, h) 20 | 21 | 22 | def issmallobject(bbox, thresh): 23 | if bbox[0] * bbox[1] <= thresh: 24 | return True 25 | else: 26 | return False 27 | 28 | 29 | def read_label_txt(label_dir): 30 | labels = [] 31 | with open(label_dir) as fp: 32 | for f in fp.readlines(): 33 | labels.append(f.strip().split(' ')) 34 | return labels 35 | 36 | 37 | def load_txt_label(label_dir): 38 | return np.loadtxt(label_dir, dtype=str) 39 | 40 | 41 | def load_txt_labels(label_dir): 42 | labels = [] 43 | for l in label_dir: 44 | la = load_txt_label(l) 45 | labels.append(la) 46 | return labels 47 | 48 | 49 | def check_dir(dir): 50 | if not os.path.exists(dir): 51 | os.makedirs(dir) 52 | 53 | 54 | def rescale_yolo_labels(labels, img_shape): 55 | height, width, nchannel = img_shape 56 | rescale_boxes = [] 57 | for box in list(labels): 58 | x_c = float(box[1]) * width 59 | y_c = float(box[2]) * height 60 | w = float(box[3]) * width 61 | h = float(box[4]) * height 62 | x_left = x_c - w * .5 63 | y_left = y_c - h * .5 64 | x_right = x_c + w * .5 65 | y_right = y_c + h * .5 66 | rescale_boxes.append([box[0], int(x_left), int(y_left), int(x_right), int(y_right)]) 67 | return rescale_boxes 68 | 69 | 70 | def draw_annotation_to_image(img, annotation, save_img_dir): 71 | for anno in annotation: 72 | cl, x1, y1, x2, y2 = anno 73 | cv2.rectangle(img, pt1=(x1, y1), pt2=(x2, y2), color=(255, 0, 0)) 74 | font = cv2.FONT_HERSHEY_SIMPLEX 75 | cv2.putText(img, cl, (int((x1 + x2) / 2), y1 - 5), font, fontScale=0.8, color=(0, 0, 255)) 76 | cv2.imwrite(save_img_dir, img) 77 | 78 | 79 | def bbox_iou(box1, box2): 80 | cl, b1_x1, b1_y1, b1_x2, b1_y2 = box1 81 | cl, b2_x1, b2_y1, b2_x2, b2_y2 = box2 82 | # get the corrdinates of the intersection rectangle 83 | inter_rect_x1 = max(b1_x1, b2_x1) 84 | inter_rect_y1 = max(b1_y1, b2_y1) 85 | inter_rect_x2 = min(b1_x2, b2_x2) 86 | inter_rect_y2 = min(b1_y2, b2_y2) 87 | # Intersection area 88 | inter_width = inter_rect_x2 - inter_rect_x1 + 1 89 | inter_height = inter_rect_y2 - inter_rect_y1 + 1 90 | if inter_width > 0 and inter_height > 0: # strong condition 91 | inter_area = inter_width * inter_height 92 | # Union Area 93 | b1_area = (b1_x2 - b1_x1 + 1) * (b1_y2 - b1_y1 + 1) 94 | b2_area = (b2_x2 - b2_x1 + 1) * (b2_y2 - b2_y1 + 1) 95 | iou = inter_area / (b1_area + b2_area - inter_area) 96 | else: 97 | iou = 0 98 | return iou 99 | 100 | 101 | def swap(x1, x2): 102 | if (x1 > x2): 103 | temp = x1 104 | x1 = x2 105 | x2 = temp 106 | return x1, x2 107 | 108 | 109 | def norm_sampling(search_space): 110 | # 随机生成点 111 | search_x_left, search_y_left, search_x_right, search_y_right = search_space 112 | new_bbox_x_center = random.randint(search_x_left, search_x_right) 113 | new_bbox_y_center = random.randint(search_y_left, search_y_right) 114 | return [new_bbox_x_center, new_bbox_y_center] 115 | 116 | 117 | def flip_bbox(roi): 118 | roi = roi[:, ::-1, :] 119 | return roi 120 | 121 | 122 | def sampling_new_bbox_center_point(img_shape, bbox): 123 | #### sampling space #### 124 | height, width, nc = img_shape 125 | cl, x_left, y_left, x_right, y_right = bbox 126 | bbox_w, bbox_h = x_right - x_left, y_right - y_left 127 | ### left top ### 128 | if x_left <= width / 2: 129 | search_x_left, search_y_left, search_x_right, search_y_right = width * 0.6, height / 2, width * 0.75, height * 0.75 130 | if x_left > width / 2: 131 | search_x_left, search_y_left, search_x_right, search_y_right = width * 0.25, height / 2, width * 0.5, height * 0.75 132 | return [search_x_left, search_y_left, search_x_right, search_y_right] 133 | 134 | 135 | def random_add_patches(bbox, rescale_boxes, shape, paste_number, iou_thresh): 136 | temp = [] 137 | for rescale_bbox in rescale_boxes: 138 | temp.append(rescale_bbox) 139 | cl, x_left, y_left, x_right, y_right = bbox 140 | bbox_w, bbox_h = x_right - x_left, y_right - y_left 141 | center_search_space = sampling_new_bbox_center_point(shape, bbox) 142 | success_num = 0 143 | new_bboxes = [] 144 | while success_num < paste_number: 145 | new_bbox_x_center, new_bbox_y_center = norm_sampling(center_search_space) 146 | print(norm_sampling(center_search_space)) 147 | new_bbox_x_left, new_bbox_y_left, new_bbox_x_right, new_bbox_y_right = new_bbox_x_center - 0.5 * bbox_w, \ 148 | new_bbox_y_center - 0.5 * bbox_h, \ 149 | new_bbox_x_center + 0.5 * bbox_w, \ 150 | new_bbox_y_center + 0.5 * bbox_h 151 | new_bbox = [cl, int(new_bbox_x_left), int(new_bbox_y_left), int(new_bbox_x_right), int(new_bbox_y_right)] 152 | ious = [bbox_iou(new_bbox, bbox_t) for bbox_t in rescale_boxes] 153 | if max(ious) <= iou_thresh: 154 | # for bbox_t in rescale_boxes: 155 | # iou = bbox_iou(new_bbox[1:],bbox_t[1:]) 156 | # if(iou <= iou_thresh): 157 | success_num += 1 158 | temp.append(new_bbox) 159 | new_bboxes.append(new_bbox) 160 | else: 161 | continue 162 | return new_bboxes 163 | 164 | 165 | def sampling_new_bbox_center_point2(img_shape, bbox): 166 | #### sampling space #### 167 | height, width, nc = img_shape 168 | bbox_h, bbox_w, bbox_c = bbox 169 | ### left top ### 170 | ''' 171 | search_x_left, search_y_left, search_x_right, search_y_right = width * 0.55 , height * 0.5 , \ 172 | width * 0.9 , height * 0.95 173 | ''' 174 | search_x_left, search_y_left, search_x_right, search_y_right = width * 0.35 , height * 0.6 , \ 175 | width * 1 , height * 0.95 176 | 177 | return [search_x_left, search_y_left, search_x_right, search_y_right] 178 | 179 | 180 | def random_add_patches2(bbox_img, rescale_boxes, shape, paste_number, iou_thresh): 181 | temp = [] 182 | for rescale_bbox in rescale_boxes: 183 | temp.append(rescale_bbox) 184 | bbox_h, bbox_w, bbox_c = bbox_img 185 | img_h,img_w,img_c = shape 186 | center_search_space = sampling_new_bbox_center_point2(shape, bbox_img) # 选取生成随机点区域 187 | success_num = 0 188 | new_bboxes = [] 189 | cl = 1 190 | while success_num < paste_number: 191 | new_bbox_x_center, new_bbox_y_center = norm_sampling(center_search_space) # 随机生成点坐标 192 | if new_bbox_x_center-0.5*bbox_w < 0 or new_bbox_x_center+0.5*bbox_w > img_w: 193 | continue 194 | if new_bbox_y_center-0.5*bbox_h < 0 or new_bbox_y_center+0.5*bbox_h > img_h: 195 | continue 196 | new_bbox_x_left, new_bbox_y_left, new_bbox_x_right, new_bbox_y_right = new_bbox_x_center - 0.5 * bbox_w, \ 197 | new_bbox_y_center - 0.5 * bbox_h, \ 198 | new_bbox_x_center + 0.5 * bbox_w, \ 199 | new_bbox_y_center + 0.5 * bbox_h 200 | new_bbox = [cl, int(new_bbox_x_left), int(new_bbox_y_left), int(new_bbox_x_right), int(new_bbox_y_right)] 201 | 202 | ious = [bbox_iou(new_bbox, bbox_t) for bbox_t in rescale_boxes] 203 | ious2 = [bbox_iou(new_bbox,bbox_t1) for bbox_t1 in new_bboxes] 204 | if ious2 == []: 205 | ious2.append(0) 206 | if max(ious) <= iou_thresh and max(ious2) <= iou_thresh: 207 | success_num += 1 208 | temp.append(new_bbox) 209 | new_bboxes.append(new_bbox) 210 | else: 211 | continue 212 | 213 | return new_bboxes 214 | --------------------------------------------------------------------------------