automan_archiver.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #!/usr/bin/env python
  2. import argparse
  3. import json
  4. import os
  5. import sys
  6. import re
  7. import requests
  8. import shutil
  9. sys.path.append(os.path.join(os.path.dirname(__file__), '../libs'))
  10. from core.storage_client_factory import StorageClientFactory
  11. from core.automan_client import AutomanClient
  12. TEMP_DIR = '/temp'
  13. def get_cv_color(colors, name):
  14. color = colors[name]
  15. cv_color = (int(color[5:7], 16), int(color[3:5], 16), int(color[1:3], 16))
  16. return cv_color
  17. class AutomanArchiver(object):
  18. @classmethod
  19. def archive(cls, automan_info, archive_info):
  20. print(archive_info)
  21. annotations_dir = os.path.join(TEMP_DIR, 'Annotations')
  22. images_dir = os.path.join(TEMP_DIR, 'Images')
  23. image_annotations_dir = os.path.join(TEMP_DIR, 'Images_Annotations')
  24. # whether or not to write image in bag file to image files
  25. is_including_image = archive_info.get('include_image', False)
  26. max_frame = cls.__get_frame_range(
  27. automan_info, archive_info['project_id'], archive_info['annotation_id'])
  28. colors = cls.__get_annotation_color(automan_info, archive_info['project_id'])
  29. candidates = cls.__get_candidates(
  30. automan_info, archive_info['project_id'], archive_info['original_id'])
  31. for i in range(max_frame):
  32. annotation = cls.__get_annotation(
  33. automan_info, archive_info['project_id'], archive_info['annotation_id'], i + 1, annotations_dir)
  34. if is_including_image:
  35. for candidate in candidates:
  36. file_name = cls.__get_annotation_image(
  37. automan_info, archive_info['project_id'],
  38. archive_info['dataset_id'], candidate['id'], i + 1, candidate['ext'], images_dir)
  39. if file_name is not None:
  40. cls.__draw_annotation(file_name, annotation, colors, images_dir, image_annotations_dir)
  41. @staticmethod
  42. def __get_frame_range(automan_info, project_id, annotation_id):
  43. path = '/projects/' + str(project_id) + '/annotations/' + str(annotation_id) + '/'
  44. res = AutomanClient.send_get(automan_info, path).json()
  45. dataset_path = '/projects/' + str(project_id) + '/datasets/' + str(res['dataset_id']) + '/'
  46. dataset = AutomanClient.send_get(automan_info, dataset_path).json()
  47. return dataset['frame_count']
  48. @staticmethod
  49. def __get_candidates(automan_info, project_id, original_id):
  50. path = '/projects/' + str(project_id) + '/originals/' + str(original_id) + '/candidates/'
  51. res = AutomanClient.send_get(automan_info, path).json()
  52. candidates = []
  53. for record in res['records']:
  54. ext = '.jpg' if record['data_type'] == 'IMAGE' else '.pcd'
  55. candidates.append({'id': record['candidate_id'], 'ext': ext})
  56. return candidates
  57. @staticmethod
  58. def __get_annotation(automan_info, project_id, annotation_id, frame, annotations_dir):
  59. path = '/projects/' + str(project_id) + '/annotations/' + str(annotation_id) \
  60. + '/frames/' + str(frame) + '/objects/'
  61. res = AutomanClient.send_get(automan_info, path).json()
  62. # TODO format to "kitti format"
  63. # ensure directory
  64. os.makedirs(annotations_dir, exist_ok=True)
  65. with open(os.path.join( annotations_dir, str(frame).zfill(6) + '.json'), mode='w') as frame:
  66. frame.write(json.dumps(res))
  67. return res
  68. @staticmethod
  69. def __get_annotation_image(automan_info, project_id, dataset_id, candidate_id, frame, ext, images_dir):
  70. path = '/projects/' + str(project_id) + '/datasets/' + str(dataset_id) \
  71. + '/candidates/' + str(candidate_id) + '/frames/' + str(frame) + '/'
  72. img_url = AutomanClient.send_get(automan_info, path).text
  73. if re.search(automan_info['host'], img_url):
  74. headers = {
  75. 'Authorization': 'JWT ' + automan_info['jwt'],
  76. }
  77. else:
  78. headers = {}
  79. res = requests.get(img_url, headers=headers)
  80. if 200 > res.status_code >= 300:
  81. print(f'get annotation image status_code = {res.status_code}. body = {res.text}')
  82. return None
  83. # write images
  84. os.makedirs(images_dir, exist_ok=True)
  85. file_name = str(candidate_id) + '_' + str(frame).zfill(6) + ext
  86. img_path = os.path.join(images_dir, file_name)
  87. with open(img_path, mode='wb') as frame:
  88. frame.write(res.content)
  89. if ext == '.jpg':
  90. return file_name
  91. return None
  92. @staticmethod
  93. def __draw_annotation(file_name, annotation, colors, images_dir, image_annotations_dir):
  94. import cv2
  95. if annotation['count'] == 0:
  96. return 0
  97. os.makedirs(image_annotations_dir, exist_ok=True)
  98. img = cv2.imread(os.path.join(images_dir, file_name))
  99. for a in annotation['records']:
  100. for c in a['content']:
  101. if 'min_x_2d' not in a['content'][c]:
  102. continue
  103. bbox = ((a['content'][c]['min_x_2d'], a['content'][c]['min_y_2d']),
  104. (a['content'][c]['max_x_2d'], a['content'][c]['max_y_2d']))
  105. cv_color = get_cv_color(colors, a['name'])
  106. cv2.rectangle(img, bbox[0], bbox[1], cv_color, 2)
  107. cv2.imwrite(os.path.join(image_annotations_dir, file_name), img)
  108. @staticmethod
  109. def __get_annotation_color(automan_info, project_id):
  110. path = '/projects/' + str(project_id) + '/'
  111. res = AutomanClient.send_get(automan_info, path).json()
  112. colors = {}
  113. for record in res['klassset']['records']:
  114. config = json.loads(record['config'])
  115. colors[record['name']] = config['color']
  116. return colors
  117. def main(automan_info, archive_info, storage_type, storage_info):
  118. automan_info = json.loads(automan_info)
  119. archive_info = json.loads(archive_info)
  120. archive_dir = archive_info['archive_dir'].rstrip('/') + '/'
  121. storage_client = StorageClientFactory.create(
  122. storage_type,
  123. json.loads(storage_info),
  124. archive_info
  125. )
  126. AutomanArchiver.archive(automan_info, archive_info)
  127. shutil.make_archive(
  128. archive_dir + archive_info['archive_name'],
  129. 'gztar',
  130. root_dir=TEMP_DIR)
  131. if storage_type == 'AWS_S3':
  132. storage_client.upload(automan_info, archive_dir)
  133. # TODO post : ArchiviedLabelDataset
  134. data = {
  135. 'file_path': archive_info['archive_dir'],
  136. 'file_name': archive_info['archive_name'] + '.tar.gz',
  137. 'annotation_id': archive_info['annotation_id'],
  138. }
  139. AutomanClient.send_result(automan_info, data)
  140. if __name__ == '__main__':
  141. parser = argparse.ArgumentParser()
  142. parser.add_argument('--storage_type', required=False)
  143. parser.add_argument('--storage_info', required=False)
  144. parser.add_argument('--automan_info', required=True)
  145. parser.add_argument('--archive_info', required=True)
  146. args = parser.parse_args()
  147. main(args.automan_info, args.archive_info, args.storage_type, args.storage_info)