(self)
Implements DatasetConverter.create_dataset_specification_and_records.
Implements DatasetConverter.create_dataset_specification_and_records.
Implements DatasetConverter . create_dataset_specification_and_records .
def create_dataset_specification_and_records(self):
    """Implements DatasetConverter.create_dataset_specification_and_records."""
    splits = self.get_splits()
    self.classes_per_split[learning_spec.Split.TRAIN] = len(splits['train'])
    self.classes_per_split[learning_spec.Split.VALID] = len(splits['valid'])
    self.classes_per_split[learning_spec.Split.TEST] = len(splits['test'])
    all_classes = list(
        itertools.chain(splits['train'], splits['valid'], splits['test']))

    # Map original COCO "id" to class ids that conform to DatasetConverter's
    # contract.
    coco_id_to_class_id = {}
    for class_id, class_name in enumerate(all_classes):
      self.class_names[class_id] = class_name
      category = self.coco_name_to_category[class_name]
      coco_id_to_class_id[category['id']] = class_id

    def get_image_crop_and_class_id(annotation):
      """Gets image crop and its class label."""
      image_id = annotation['image_id']
      image_path = os.path.join(self.image_dir, '%012d.jpg' % image_id)
      # The bounding box is represented as (x_topleft, y_topleft, width, height)
      bbox = annotation['bbox']
      coco_class_id = annotation['category_id']
      class_id = coco_id_to_class_id[coco_class_id]

      with tf.io.gfile.GFile(image_path, 'rb') as f:
        # The image shape is [?, ?, 3] and the type is uint8.
        image = Image.open(f)
        image = image.convert(mode='RGB')
        image_w, image_h = image.size

        def scale_box(bbox, scale_ratio):
          x, y, w, h = bbox
          x = x - 0.5 * w * (scale_ratio - 1.0)
          y = y - 0.5 * h * (scale_ratio - 1.0)
          w = w * scale_ratio
          h = h * scale_ratio
          return [x, y, w, h]

        x, y, w, h = scale_box(bbox, self.box_scale_ratio)
        # Convert half-integer to full-integer representation.
        # The Python Imaging Library uses a Cartesian pixel coordinate system,
        # with (0,0) in the upper left corner. Note that the coordinates refer
        # to the implied pixel corners; the centre of a pixel addressed as
        # (0, 0) actually lies at (0.5, 0.5). Since COCO uses the later
        # convention and we use PIL to crop the image, we need to convert from
        # half-integer to full-integer representation.
        xmin = max(int(round(x - 0.5)), 0)
        ymin = max(int(round(y - 0.5)), 0)
        xmax = min(int(round(x + w - 0.5)) + 1, image_w)
        ymax = min(int(round(y + h - 0.5)) + 1, image_h)
        image_crop = image.crop((xmin, ymin, xmax, ymax))
        crop_width, crop_height = image_crop.size
        if crop_width <= 0 or crop_height <= 0:
          raise ValueError('crops are not valid.')
      return image_crop, class_id

    class_tf_record_writers = []
    for class_id in range(self.num_all_classes):
      output_path = os.path.join(
          self.records_path, self.dataset_spec.file_pattern.format(class_id))
      class_tf_record_writers.append(tf.python_io.TFRecordWriter(output_path))

    for i, annotation in enumerate(self.coco_instance_annotations):
      try:
        image_crop, class_id = get_image_crop_and_class_id(annotation)
      except IOError:
        logging.warning('Image can not be opened and will be skipped.')
        continue
      except ValueError:
        logging.warning('Image can not be cropped and will be skipped.')
        continue

      logging.info('writing image %d/%d', i,
                   len(self.coco_instance_annotations))

      # TODO(manzagop): refactor this, e.g. use write_tfrecord_from_image_files.
      image_crop_bytes = io.BytesIO()
      image_crop.save(image_crop_bytes, format='JPEG')
      image_crop_bytes.seek(0)

      write_example(image_crop_bytes.getvalue(), class_id,
                    class_tf_record_writers[class_id])
      self.images_per_class[class_id] += 1

    for writer in class_tf_record_writers:
      writer.close()
def create_dataset_specification_and_records ( self ) : splits = self . get_splits ( ) self . classes_per_split [ learning_spec . Split . TRAIN ] = len ( splits [ 'train' ] ) self . classes_per_split [ learning_spec . Split . VALID ] = len ( splits [ 'valid' ] ) self . classes_per_split [ learning_spec . Split . TEST ] = len ( splits [ 'test' ] ) all_classes = list ( itertools . chain ( splits [ 'train' ] , splits [ 'valid' ] , splits [ 'test' ] ) ) # Map original COCO "id" to class ids that conform to DatasetConverter's # contract. coco_id_to_class_id = { } for class_id , class_name in enumerate ( all_classes ) : self . class_names [ class_id ] = class_name category = self . coco_name_to_category [ class_name ] coco_id_to_class_id [ category [ 'id' ] ] = class_id def get_image_crop_and_class_id ( annotation ) : """Gets image crop and its class label.""" image_id = annotation [ 'image_id' ] image_path = os . path . join ( self . image_dir , '%012d.jpg' % image_id ) # The bounding box is represented as (x_topleft, y_topleft, width, height) bbox = annotation [ 'bbox' ] coco_class_id = annotation [ 'category_id' ] class_id = coco_id_to_class_id [ coco_class_id ] with tf . io . gfile . GFile ( image_path , 'rb' ) as f : # The image shape is [?, ?, 3] and the type is uint8. image = Image . open ( f ) image = image . convert ( mode = 'RGB' ) image_w , image_h = image . size def scale_box ( bbox , scale_ratio ) : x , y , w , h = bbox x = x - 0.5 * w * ( scale_ratio - 1.0 ) y = y - 0.5 * h * ( scale_ratio - 1.0 ) w = w * scale_ratio h = h * scale_ratio return [ x , y , w , h ] x , y , w , h = scale_box ( bbox , self . box_scale_ratio ) # Convert half-integer to full-integer representation. # The Python Imaging Library uses a Cartesian pixel coordinate system, # with (0,0) in the upper left corner. Note that the coordinates refer # to the implied pixel corners; the centre of a pixel addressed as # (0, 0) actually lies at (0.5, 0.5). Since COCO uses the later # convention and we use PIL to crop the image, we need to convert from # half-integer to full-integer representation. xmin = max ( int ( round ( x - 0.5 ) ) , 0 ) ymin = max ( int ( round ( y - 0.5 ) ) , 0 ) xmax = min ( int ( round ( x + w - 0.5 ) ) + 1 , image_w ) ymax = min ( int ( round ( y + h - 0.5 ) ) + 1 , image_h ) image_crop = image . crop ( ( xmin , ymin , xmax , ymax ) ) crop_width , crop_height = image_crop . size if crop_width <= 0 or crop_height <= 0 : raise ValueError ( 'crops are not valid.' ) return image_crop , class_id class_tf_record_writers = [ ] for class_id in range ( self . num_all_classes ) : output_path = os . path . join ( self . records_path , self . dataset_spec . file_pattern . format ( class_id ) ) class_tf_record_writers . append ( tf . python_io . TFRecordWriter ( output_path ) ) for i , annotation in enumerate ( self . coco_instance_annotations ) : try : image_crop , class_id = get_image_crop_and_class_id ( annotation ) except IOError : logging . warning ( 'Image can not be opened and will be skipped.' ) continue except ValueError : logging . warning ( 'Image can not be cropped and will be skipped.' ) continue logging . info ( 'writing image %d/%d' , i , len ( self . coco_instance_annotations ) ) # TODO(manzagop): refactor this, e.g. use write_tfrecord_from_image_files. image_crop_bytes = io . BytesIO ( ) image_crop . save ( image_crop_bytes , format = 'JPEG' ) image_crop_bytes . seek ( 0 ) write_example ( image_crop_bytes . getvalue ( ) , class_id , class_tf_record_writers [ class_id ] ) self . images_per_class [ class_id ] += 1 for writer in class_tf_record_writers : writer . close ( )