def testShapeIsCorrectAfterOp(self): batch = 2 image_height = 3 image_width = 4 crop_height = 4 crop_width = 5 depth = 2 num_boxes = 2 image_shape = [batch, image_height, image_width, depth] crop_size = [crop_height, crop_width] crops_shape = [num_boxes, crop_height, crop_width, depth] image = np.arange(0, batch * image_height * image_width * depth).reshape(image_shape).astype(np.float32) boxes = np.array([[0, 0, 1, 1], [.1, .2, .7, .8]], dtype=np.float32) box_ind = np.array([0, 1], dtype=np.int32) crops = image_ops.crop_and_resize( constant_op.constant(image, shape=image_shape), constant_op.constant(boxes, shape=[num_boxes, 4]), constant_op.constant(box_ind, shape=[num_boxes]), constant_op.constant(crop_size, shape=[2])) with self.session(use_gpu=True) as sess: self.assertEqual(crops_shape, list(crops.get_shape())) crops = self.evaluate(crops) self.assertEqual(crops_shape, list(crops.shape))
def testShapeIsCorrectAfterOp(self): batch = 2 image_height = 3 image_width = 4 crop_height = 4 crop_width = 5 depth = 2 num_boxes = 2 image_shape = [batch, image_height, image_width, depth] crop_size = [crop_height, crop_width] crops_shape = [num_boxes, crop_height, crop_width, depth] image = np.arange(0, batch * image_height * image_width * depth).reshape(image_shape).astype(np.float32) boxes = np.array([[0, 0, 1, 1], [.1, .2, .7, .8]], dtype=np.float32) box_ind = np.array([0, 1], dtype=np.int32) with self.test_session(use_gpu=True) as sess: crops = image_ops.crop_and_resize( constant_op.constant( image, shape=image_shape), constant_op.constant( boxes, shape=[num_boxes, 4]), constant_op.constant( box_ind, shape=[num_boxes]), constant_op.constant( crop_size, shape=[2])) self.assertEqual(crops_shape, list(crops.get_shape())) crops = sess.run(crops) self.assertEqual(crops_shape, list(crops.shape))
def forward(self, inputs, rois, im_info): """ :param inputs: features :param rois: regions of interest, shape with [batch, 5] format as (img_id, x0, y0, x1, y1) img_id is index of image inside batch :param im_info: scales of image, shape with [batch, 2] format as (height, width) :return: """ assert F.ndim(rois) == 2 and F.int_shape(rois)[-1] == 5 assert F.ndim(im_info) == 2 and F.int_shape(im_info)[-1] == 2 indices = F.int32(rois[:, 0]) boxes = rois[:, 1:] norm = F.float32( array_ops.stack( [im_info[:, 1], im_info[:, 0], im_info[:, 1], im_info[:, 0]], axis=1)) boxes = boxes / norm # (x0, y0, x1, y1) -> (y0, x0, y1, x1) boxes = array_ops.stack( [boxes[:, 1], boxes[:, 0], boxes[:, 3], boxes[:, 2]], axis=1) crop_size = array_ops.constant(self.crop_size) if self.data_format[-1] == 'C': kernel_size = (1, ) + self._kernel_size + (1, ) strides = (1, ) + self._strides + (1, ) else: kernel_size = (1, 1) + self._kernel_size strides = (1, 1) + self._strides inputs = F.transpose_to_channels_last(inputs) outputs = image_ops.crop_and_resize(image=inputs, boxes=boxes, box_ind=indices, crop_size=crop_size) if self.data_format[-1] != 'C': outputs = F.transpose_to_channels_first(outputs) outputs = nn.max_pool2d(input=outputs, ksize=kernel_size, strides=strides, data_format=self.data_format, padding='SAME') return outputs
def crop_resize(image_tensor, boxes_tensor): # pylint: disable=cell-var-from-loop return image_ops.crop_and_resize( image_tensor, boxes_tensor, box_ind_tensor, constant_op.constant(crop_size, shape=[2]))
def testGradRandomBoxes(self): """Test that the gradient is correct for randomly generated boxes. The mapping is piecewise differentiable with respect to the box coordinates. The points where the function is not differentiable are those which are mapped to image pixels, i.e., the normalized y coordinates in np.linspace(0, 1, image_height) and normalized x coordinates in np.linspace(0, 1, image_width). Make sure that the box coordinates are sufficiently far away from those rectangular grid centers that are points of discontinuity, so that the finite difference Jacobian is close to the computed one. """ np.random.seed(1) # Make it reproducible. delta = 1e-3 radius = 2 * delta low, high = -0.5, 1.5 # Also covers the case of extrapolation. image_height = 4 for image_width in range(1, 3): for crop_height in range(1, 3): for crop_width in range(2, 4): for depth in range(1, 3): for num_boxes in range(1, 3): batch = num_boxes image_shape = [batch, image_height, image_width, depth] crop_size = [crop_height, crop_width] crops_shape = [num_boxes, crop_height, crop_width, depth] boxes_shape = [num_boxes, 4] image = np.arange(0, batch * image_height * image_width * depth).reshape(image_shape).astype(np.float32) boxes = [] for _ in range(num_boxes): # pylint: disable=unbalanced-tuple-unpacking y1, y2 = self._randomUniformAvoidAnchors( low, high, np.linspace(0, 1, image_height), radius, 2) x1, x2 = self._randomUniformAvoidAnchors( low, high, np.linspace(0, 1, image_width), radius, 2) # pylint: enable=unbalanced-tuple-unpacking boxes.append([y1, x1, y2, x2]) boxes = np.array(boxes, dtype=np.float32) box_ind = np.arange(batch, dtype=np.int32) with self.test_session(use_gpu=True): image_tensor = constant_op.constant(image, shape=image_shape) boxes_tensor = constant_op.constant(boxes, shape=[num_boxes, 4]) box_ind_tensor = constant_op.constant( box_ind, shape=[num_boxes]) crops = image_ops.crop_and_resize( image_tensor, boxes_tensor, box_ind_tensor, constant_op.constant( crop_size, shape=[2])) err = gradient_checker.compute_gradient_error( [image_tensor, boxes_tensor], [image_shape, boxes_shape], crops, crops_shape, delta=delta, x_init_value=[image, boxes]) self.assertLess(err, 2e-3)
def testGradRandomBoxes(self): """Test that the gradient is correct for randomly generated boxes. The mapping is piecewise differentiable with respect to the box coordinates. The points where the function is not differentiable are those which are mapped to image pixels, i.e., the normalized y coordinates in np.linspace(0, 1, image_height) and normalized x coordinates in np.linspace(0, 1, image_width). Make sure that the box coordinates are sufficiently far away from those rectangular grid centers that are points of discontinuity, so that the finite difference Jacobian is close to the computed one. """ np.random.seed(1) # Make it reproducible. delta = 1e-3 radius = 2 * delta low, high = -0.5, 1.5 # Also covers the case of extrapolation. image_height = 4 for image_width in range(1, 3): for crop_height in range(1, 3): for crop_width in range(2, 4): for depth in range(1, 3): for num_boxes in range(1, 3): batch = num_boxes image_shape = [ batch, image_height, image_width, depth ] crop_size = [crop_height, crop_width] crops_shape = [ num_boxes, crop_height, crop_width, depth ] boxes_shape = [num_boxes, 4] image = np.arange( 0, batch * image_height * image_width * depth).reshape(image_shape).astype(np.float32) boxes = [] for _ in range(num_boxes): # pylint: disable=unbalanced-tuple-unpacking y1, y2 = self._randomUniformAvoidAnchors( low, high, np.linspace(0, 1, image_height), radius, 2) x1, x2 = self._randomUniformAvoidAnchors( low, high, np.linspace(0, 1, image_width), radius, 2) # pylint: enable=unbalanced-tuple-unpacking boxes.append([y1, x1, y2, x2]) boxes = np.array(boxes, dtype=np.float32) box_ind = np.arange(batch, dtype=np.int32) with self.test_session(use_gpu=True): image_tensor = constant_op.constant( image, shape=image_shape) boxes_tensor = constant_op.constant( boxes, shape=[num_boxes, 4]) box_ind_tensor = constant_op.constant( box_ind, shape=[num_boxes]) crops = image_ops.crop_and_resize( image_tensor, boxes_tensor, box_ind_tensor, constant_op.constant(crop_size, shape=[2])) err = gradient_checker.compute_gradient_error( [image_tensor, boxes_tensor], [image_shape, boxes_shape], crops, crops_shape, delta=delta, x_init_value=[image, boxes]) self.assertLess(err, 2e-3)