def _patch(self, one, two): """Build the full 4 patch of images from sets of 2 images.""" image = tf.concat([one['image'], two['image']], axis=-3) boxes = tf.concat([one['groundtruth_boxes'], two['groundtruth_boxes']], axis=0) classes = tf.concat( [one['groundtruth_classes'], two['groundtruth_classes']], axis=0) is_crowd = tf.concat( [one['groundtruth_is_crowd'], two['groundtruth_is_crowd']], axis=0) area = tf.concat([one['groundtruth_area'], two['groundtruth_area']], axis=0) if self._mosaic_crop_mode is not None: image, boxes, classes, is_crowd, area, _ = self._mosaic_crop_image( image, boxes, classes, is_crowd, area) sample = one height, width = preprocessing_ops.get_image_shape(image) sample['image'] = tf.cast(image, tf.uint8) sample['groundtruth_boxes'] = boxes sample['groundtruth_area'] = area sample['groundtruth_classes'] = tf.cast(classes, sample['groundtruth_classes'].dtype) sample['groundtruth_is_crowd'] = tf.cast(is_crowd, tf.bool) sample['width'] = tf.cast(width, sample['width'].dtype) sample['height'] = tf.cast(height, sample['height'].dtype) sample['num_detections'] = tf.shape(sample['groundtruth_boxes'])[1] sample['is_mosaic'] = tf.cast(1.0, tf.bool) del sample['shiftx'] del sample['shifty'] del sample['crop_points'] return sample
def letterbox(image: tf.Tensor, desired_size: List[int], letter_box: bool = True) -> Tuple[tf.Tensor, tf.Tensor]: """Letter box an image for image serving.""" with tf.name_scope('letter_box'): image_size = tf.cast(preprocessing_ops.get_image_shape(image), tf.float32) scaled_size = tf.cast(desired_size, image_size.dtype) if letter_box: scale = tf.minimum(scaled_size[0] / image_size[0], scaled_size[1] / image_size[1]) scaled_size = tf.round(image_size * scale) else: scale = 1.0 # Computes 2D image_scale. image_scale = scaled_size / image_size image_offset = tf.cast((desired_size - scaled_size) * 0.5, tf.int32) offset = (scaled_size - desired_size) * 0.5 scaled_image = tf.image.resize( image, tf.cast(scaled_size, tf.int32), method='nearest') output_image = tf.image.pad_to_bounding_box(scaled_image, image_offset[0], image_offset[1], desired_size[0], desired_size[1]) image_info = tf.stack([ image_size, tf.cast(desired_size, dtype=tf.float32), image_scale, tf.cast(offset, tf.float32) ]) return output_image, image_info
def _mosaic_crop_image(self, image, boxes, classes, is_crowd, area): """Process a patched image in preperation for final output.""" if self._mosaic_crop_mode != 'crop': shape = tf.cast(preprocessing_ops.get_image_shape(image), tf.float32) center = shape * self._mosaic_center # shift the center of the image by applying a translation to the whole # image ch = tf.math.round( preprocessing_ops.random_uniform_strong(-center[0], center[0], seed=self._seed)) cw = tf.math.round( preprocessing_ops.random_uniform_strong(-center[1], center[1], seed=self._seed)) # clip the boxes to those with in the image image = tfa.image.translate(image, [cw, ch], fill_value=self._pad_value) boxes = box_ops.denormalize_boxes(boxes, shape[:2]) boxes = boxes + tf.cast([ch, cw, ch, cw], boxes.dtype) boxes = box_ops.clip_boxes(boxes, shape[:2]) inds = box_ops.get_non_empty_box_indices(boxes) boxes = box_ops.normalize_boxes(boxes, shape[:2]) boxes, classes, is_crowd, area = self._select_ind( inds, boxes, classes, # pylint:disable=unbalanced-tuple-unpacking is_crowd, area) # warp and scale the fully stitched sample image, _, affine = preprocessing_ops.affine_warp_image( image, [self._output_size[0], self._output_size[1]], scale_min=self._aug_scale_min, scale_max=self._aug_scale_max, translate=self._aug_rand_translate, degrees=self._aug_rand_angle, perspective=self._aug_rand_perspective, random_pad=self._random_pad, seed=self._seed) height, width = self._output_size[0], self._output_size[1] image = tf.image.resize(image, (height, width)) # clip and clean boxes boxes, inds = preprocessing_ops.transform_and_clip_boxes( boxes, None, affine=affine, area_thresh=self._area_thresh, seed=self._seed) classes, is_crowd, area = self._select_ind(inds, classes, is_crowd, area) # pylint:disable=unbalanced-tuple-unpacking return image, boxes, classes, is_crowd, area, area
def _reorg_boxes(self, boxes, num_detections, image): """Scale and Clean boxes prior to Evaluation.""" # Build a prediciton mask to take only the number of detections mask = tf.sequence_mask(num_detections, maxlen=tf.shape(boxes)[1]) mask = tf.cast(tf.expand_dims(mask, axis=-1), boxes.dtype) # Denormalize the boxes by the shape of the image inshape = tf.cast(preprocessing_ops.get_image_shape(image), boxes.dtype) boxes = box_ops.denormalize_boxes(boxes, inshape) # Mask the boxes for usage boxes *= mask boxes += (mask - 1) return boxes
def testGetImageShape(self, image_height, image_width): image = tf.convert_to_tensor(np.random.rand(image_height, image_width, 3)) image_shape = preprocessing_ops.get_image_shape(image) self.assertAllEqual((image_height, image_width), image_shape)