crowdhuman.py 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. import os
  2. import cv2
  3. import random
  4. import numpy as np
  5. from torch.utils.data import Dataset
  6. try:
  7. from pycocotools.coco import COCO
  8. except:
  9. print("It seems that the COCOAPI is not installed.")
  10. try:
  11. from .data_augment.yolov5_augment import yolov5_mosaic_augment, yolov5_mixup_augment, yolox_mixup_augment
  12. except:
  13. from data_augment.yolov5_augment import yolov5_mosaic_augment, yolov5_mixup_augment, yolox_mixup_augment
  14. crowd_class_labels = ('person',)
  15. class CrowdHumanDataset(Dataset):
  16. def __init__(self,
  17. img_size :int = 640,
  18. data_dir :str = None,
  19. image_set :str = 'train',
  20. trans_config = None,
  21. transform = None,
  22. is_train :bool = False
  23. ):
  24. # ----------- Basic parameters -----------
  25. self.img_size = img_size
  26. self.image_set = image_set
  27. self.is_train = is_train
  28. # ----------- Path parameters -----------
  29. self.data_dir = data_dir
  30. self.json_file = '{}.json'.format(image_set)
  31. # ----------- Data parameters -----------
  32. self.coco = COCO(os.path.join(self.data_dir, 'annotations', self.json_file))
  33. self.ids = self.coco.getImgIds()
  34. self.class_ids = sorted(self.coco.getCatIds())
  35. # ----------- Transform parameters -----------
  36. self.transform = transform
  37. self.mosaic_prob = trans_config['mosaic_prob'] if trans_config else 0.0
  38. self.mixup_prob = trans_config['mixup_prob'] if trans_config else 0.0
  39. self.trans_config = trans_config
  40. print('==============================')
  41. print('use Mosaic Augmentation: {}'.format(self.mosaic_prob))
  42. print('use Mixup Augmentation: {}'.format(self.mixup_prob))
  43. print('==============================')
  44. # ------------ Basic dataset function ------------
  45. def __len__(self):
  46. return len(self.ids)
  47. def __getitem__(self, index):
  48. return self.pull_item(index)
  49. # ------------ Mosaic & Mixup ------------
  50. def load_mosaic(self, index):
  51. # load 4x mosaic image
  52. index_list = np.arange(index).tolist() + np.arange(index+1, len(self.ids)).tolist()
  53. id1 = index
  54. id2, id3, id4 = random.sample(index_list, 3)
  55. indexs = [id1, id2, id3, id4]
  56. # load images and targets
  57. image_list = []
  58. target_list = []
  59. for index in indexs:
  60. img_i, target_i = self.load_image_target(index)
  61. image_list.append(img_i)
  62. target_list.append(target_i)
  63. # Mosaic
  64. if self.trans_config['mosaic_type'] == 'yolov5_mosaic':
  65. image, target = yolov5_mosaic_augment(
  66. image_list, target_list, self.img_size, self.trans_config, self.is_train)
  67. return image, target
  68. def load_mixup(self, origin_image, origin_target):
  69. # YOLOv5 type Mixup
  70. if self.trans_config['mixup_type'] == 'yolov5_mixup':
  71. new_index = np.random.randint(0, len(self.ids))
  72. new_image, new_target = self.load_mosaic(new_index)
  73. image, target = yolov5_mixup_augment(
  74. origin_image, origin_target, new_image, new_target)
  75. # YOLOX type Mixup
  76. elif self.trans_config['mixup_type'] == 'yolox_mixup':
  77. new_index = np.random.randint(0, len(self.ids))
  78. new_image, new_target = self.load_image_target(new_index)
  79. image, target = yolox_mixup_augment(
  80. origin_image, origin_target, new_image, new_target, self.img_size, self.trans_config['mixup_scale'])
  81. return image, target
  82. # ------------ Load data function ------------
  83. def load_image_target(self, index):
  84. # load an image
  85. image, _ = self.pull_image(index)
  86. height, width, channels = image.shape
  87. # load a target
  88. bboxes, labels = self.pull_anno(index)
  89. target = {
  90. "boxes": bboxes,
  91. "labels": labels,
  92. "orig_size": [height, width]
  93. }
  94. return image, target
  95. def pull_item(self, index):
  96. if random.random() < self.mosaic_prob:
  97. # load a mosaic image
  98. mosaic = True
  99. image, target = self.load_mosaic(index)
  100. else:
  101. mosaic = False
  102. # load an image and target
  103. image, target = self.load_image_target(index)
  104. # MixUp
  105. if random.random() < self.mixup_prob:
  106. image, target = self.load_mixup(image, target)
  107. # augment
  108. image, target, deltas = self.transform(image, target, mosaic)
  109. return image, target, deltas
  110. def pull_image(self, index):
  111. id_ = self.ids[index]
  112. im_ann = self.coco.loadImgs(id_)[0]
  113. img_id = im_ann["file_name"][:-4]
  114. img_file = os.path.join(
  115. self.data_dir, 'CrowdHuman_{}'.format(self.image_set), 'Images', im_ann["file_name"])
  116. image = cv2.imread(img_file)
  117. return image, img_id
  118. def pull_anno(self, index):
  119. img_id = self.ids[index]
  120. im_ann = self.coco.loadImgs(img_id)[0]
  121. anno_ids = self.coco.getAnnIds(imgIds=[int(img_id)], iscrowd=0)
  122. annotations = self.coco.loadAnns(anno_ids)
  123. # image infor
  124. width = im_ann['width']
  125. height = im_ann['height']
  126. #load a target
  127. bboxes = []
  128. labels = []
  129. for anno in annotations:
  130. if 'bbox' in anno and anno['area'] > 0:
  131. # bbox
  132. x1 = np.max((0, anno['bbox'][0]))
  133. y1 = np.max((0, anno['bbox'][1]))
  134. x2 = np.min((width - 1, x1 + np.max((0, anno['bbox'][2] - 1))))
  135. y2 = np.min((height - 1, y1 + np.max((0, anno['bbox'][3] - 1))))
  136. if x2 <= x1 or y2 <= y1:
  137. continue
  138. # class label
  139. cls_id = self.class_ids.index(anno['category_id'])
  140. bboxes.append([x1, y1, x2, y2])
  141. labels.append(cls_id)
  142. # guard against no boxes via resizing
  143. bboxes = np.array(bboxes).reshape(-1, 4)
  144. labels = np.array(labels).reshape(-1)
  145. return bboxes, labels
  146. if __name__ == "__main__":
  147. import time
  148. import argparse
  149. from build import build_transform
  150. parser = argparse.ArgumentParser(description='CrowdHuman-Dataset')
  151. # opt
  152. parser.add_argument('--root', default='/Users/liuhaoran/Desktop/python_work/object-detection/dataset/CrowdHuman/',
  153. help='data root')
  154. parser.add_argument('-size', '--img_size', default=640, type=int,
  155. help='input image size.')
  156. parser.add_argument('--aug_type', type=str, default='ssd',
  157. help='augmentation type')
  158. parser.add_argument('--mosaic', default=0., type=float,
  159. help='mosaic augmentation.')
  160. parser.add_argument('--mixup', default=0., type=float,
  161. help='mixup augmentation.')
  162. parser.add_argument('--mixup_type', type=str, default='yolov5_mixup',
  163. help='mixup augmentation.')
  164. parser.add_argument('--is_train', action="store_true", default=False,
  165. help='mixup augmentation.')
  166. args = parser.parse_args()
  167. trans_config = {
  168. 'aug_type': args.aug_type, # optional: ssd, yolov5
  169. # Basic Augment
  170. 'degrees': 0.0,
  171. 'translate': 0.2,
  172. 'scale': [0.1, 2.0],
  173. 'shear': 0.0,
  174. 'perspective': 0.0,
  175. 'hsv_h': 0.015,
  176. 'hsv_s': 0.7,
  177. 'hsv_v': 0.4,
  178. 'use_ablu': True,
  179. # Mosaic & Mixup
  180. 'mosaic_prob': args.mosaic,
  181. 'mixup_prob': args.mixup,
  182. 'mosaic_type': 'yolov5_mosaic',
  183. 'mixup_type': args.mixup_type, # optional: yolov5_mixup, yolox_mixup
  184. 'mixup_scale': [0.5, 1.5]
  185. }
  186. transform, trans_cfg = build_transform(args, trans_config, 32, args.is_train)
  187. dataset = CrowdHumanDataset(
  188. img_size=args.img_size,
  189. data_dir=args.root,
  190. image_set='val',
  191. transform=transform,
  192. trans_config=trans_config,
  193. )
  194. np.random.seed(0)
  195. class_colors = [(np.random.randint(255),
  196. np.random.randint(255),
  197. np.random.randint(255)) for _ in range(80)]
  198. print('Data length: ', len(dataset))
  199. for i in range(1000):
  200. t0 = time.time()
  201. image, target, deltas = dataset.pull_item(i)
  202. print("Load data: {} s".format(time.time() - t0))
  203. # to numpy
  204. image = image.permute(1, 2, 0).numpy()
  205. # to uint8
  206. image = image.astype(np.uint8)
  207. image = image.copy()
  208. img_h, img_w = image.shape[:2]
  209. boxes = target["boxes"]
  210. labels = target["labels"]
  211. for box, label in zip(boxes, labels):
  212. x1, y1, x2, y2 = box
  213. cls_id = int(label)
  214. color = class_colors[cls_id]
  215. # class name
  216. label = crowd_class_labels[cls_id]
  217. image = cv2.rectangle(image, (int(x1), int(y1)), (int(x2), int(y2)), (0,0,255), 2)
  218. # put the test on the bbox
  219. cv2.putText(image, label, (int(x1), int(y1 - 5)), 0, 0.5, color, 1, lineType=cv2.LINE_AA)
  220. cv2.imshow('gt', image)
  221. # cv2.imwrite(str(i)+'.jpg', img)
  222. cv2.waitKey(0)