Source code for mindspore.ops.function.image_func

# Copyright 2022 Huawei Technologies Co., Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ============================================================================

"""Defines image operators with functional form."""

from mindspore.ops import operations as P
from mindspore.ops.operations import image_ops as IMG
import mindspore.common.dtype as mstype
from mindspore.common.tensor import Tensor
from mindspore._c_expression import Tensor as Tensor_
from .._primitive_cache import _get_cache_prim


[docs]def bounding_box_decode(anchor_box, deltas, max_shape, means=(0.0, 0.0, 0.0, 0.0), stds=(1.0, 1.0, 1.0, 1.0), wh_ratio_clip=0.016): r""" Decode the bounding box locations, calculate the offset, and convert the offset into a Bbox, which is used to mark the target in the subsequent images, etc. Args: anchor_box (Tensor): Anchor boxes. The shape of `anchor_box` must be :math:`(n, 4)`. deltas (Tensor): Delta of boxes. Which has the same shape with `anchor_box`. max_shape (tuple): The max size limit for decoding box calculation. means (tuple, optional): The means of `deltas` calculation. Default: (0.0, 0.0, 0.0, 0.0). stds (tuple, optional): The standard deviations of `deltas` calculation. Default: (1.0, 1.0, 1.0, 1.0). wh_ratio_clip (float, optional): The limit of width and height ratio for decoding box calculation. Default: 0.016. Returns: Tensor, decoded boxes. It has the same data type and shape as `anchor_box`. Raises: TypeError: If `means`, `stds` or `max_shape` is not a tuple. TypeError: If `wh_ratio_clip` is not a float. TypeError: If `anchor_box` or `deltas` is not a Tensor. Supported Platforms: ``Ascend`` ``GPU`` ``CPU`` Examples: >>> anchor_box = Tensor([[4, 1, 2, 1], [2, 2, 2, 3]], mindspore.float32) >>> deltas = Tensor([[3, 1, 2, 2], [1, 2, 1, 4]], mindspore.float32) >>> output = ops.bounding_box_decode(anchor_box, deltas, max_shape=(768, 1280), means=(0.0, 0.0, 0.0, 0.0), ... stds=(1.0, 1.0, 1.0, 1.0), wh_ratio_clip=0.016) >>> print(output) [[ 4.1953125 0. 0. 5.1953125] [ 2.140625 0. 3.859375 60.59375 ]] """ bounding_box_decode_op = _get_cache_prim(P.BoundingBoxDecode)(max_shape, means, stds, wh_ratio_clip) return bounding_box_decode_op(anchor_box, deltas)
[docs]def bounding_box_encode(anchor_box, groundtruth_box, means=(0.0, 0.0, 0.0, 0.0), stds=(1.0, 1.0, 1.0, 1.0)): r""" Encode the bounding box locations, calculate the offset between the predicted bounding boxes and the real bounding boxes, and the offset will be used as a variable for the loss. Args: anchor_box (Tensor): Anchor boxes. The shape of `anchor_box` must be :math:`(n, 4)`. groundtruth_box (Tensor): Ground truth boxes. Which has the same shape with `anchor_box`. means (tuple, optional): Means for encoding bounding boxes calculation. Default: (0.0, 0.0, 0.0, 0.0). stds (tuple, optional): The standard deviations of deltas calculation. Default: (1.0, 1.0, 1.0, 1.0). Returns: Tensor, encoded bounding boxes. It has the same data type and shape as input `anchor_box`. Raises: TypeError: If `means` or `stds` is not a tuple. TypeError: If `anchor_box` or `groundtruth_box` is not a Tensor. Supported Platforms: ``Ascend`` ``GPU`` ``CPU`` Examples: >>> anchor_box = Tensor([[2, 2, 2, 3], [2, 2, 2, 3]], mindspore.float32) >>> groundtruth_box = Tensor([[1, 2, 1, 4], [1, 2, 1, 4]], mindspore.float32) >>> output = ops.bounding_box_encode(anchor_box, groundtruth_box, means=(0.0, 0.0, 0.0, 0.0), ... stds=(1.0, 1.0, 1.0, 1.0)) >>> print(output) [[ -1. 0.25 0. 0.40551758] [ -1. 0.25 0. 0.40551758]] """ bounding_box_encode_op = _get_cache_prim(P.BoundingBoxEncode)(means, stds) return bounding_box_encode_op(anchor_box, groundtruth_box)
[docs]def check_valid(bboxes, img_metas): r""" Checks whether the bounding box is in the image. `bboxes` contain several sets of bounding boxes, each represented by two abscissa points :math:`(x0, x1)` and two ordinate points :math:`(y0, y1)` . `img_metas` provides information about the original image, including three parameters :math:`(height, width, ratio)` , which specify the valid boundary of the image. when the following conditions are met: :math:`x0 >= 0` :math:`y0 >= 0` :math:`x1 <= width * ratio - 1` :math:`y1 <= height * ratio - 1` the bounding box is considered to be within the image. .. warning:: The bounding box specified by `bboxes` and the image information specified by `img_metas` need to be valid, i.e.: :math:`x0 <= x1` , :math:`y0 <= y1` , and :math:`(height, width, ratio)` are all positive. Args: bboxes (Tensor): Bounding boxes tensor with shape :math:`(N, 4)` . :math:`N` indicates the number of bounding boxes, the value `4` indicates four coordinate points :math:`(x0, y0, x1, y1)` . Data type must be float16 or float32. img_metas (Tensor): Raw image size information with the format of :math:`(height, width, ratio)` , specifying the valid boundary :math:`(height * ratio - 1, width * ratio - 1)` . Data type must be float16 or float32. Returns: Tensor, with shape of :math:`(N,)` and dtype of bool, specifying whether the bounding boxes is in the image. `True` indicates valid, while `False` indicates invalid. Raises: TypeError: If `bboxes` or `img_metas` is not a Tensor. TypeError: If dtype of `bboxes` or `img_metas` is neither float16 nor float32. Supported Platforms: ``Ascend`` ``GPU`` ``CPU`` Examples: >>> bboxes = Tensor(np.linspace(0, 6, 12).reshape(3, 4), mindspore.float32) >>> img_metas = Tensor(np.array([2, 1, 3]), mindspore.float32) >>> output = ops.check_valid(bboxes, img_metas) >>> print(output) [ True False False] """ check_valid_op = _get_cache_prim(P.CheckValid)() return check_valid_op(bboxes, img_metas)
[docs]def crop_and_resize(image, boxes, box_indices, crop_size, method="bilinear", extrapolation_value=0.0): r""" Extracts crops from the input image Tensor and resizes them. Note: In case that the output shape depends on crop_size, the crop_size must be constant. For now, the backward of the operator only support bilinear method, for other methods, will return 0. Args: image (Tensor): A 4-D Tensor representing a batch of images. It has shape :math:`(batch, image\_height, image\_width, depth)`. boxes (Tensor): A 2-D Tensor with shape :math:`(num\_boxes, 4)` representing the normalized coordinates of the boxes to be cropped. The coordinates are specified in the form :math:`[y1, x1, y2, x2]`, where :math:`(y1, x1)` is the first corner and :math:`(y2, x2)` is the second corner of the box. If :math:`y1 > y2`, the sampled crop is inverted upside down, the width dimensionis treated similarly when :math:`x1 > x2`. If normalized coordinates are not in range :math:`[0, 1]`, extrapolated input image values are used instead. Supported data type: float32. box_indices (Tensor): A 1-D Tensor of shape :math:`(num\_boxes)` representing the batch index for each box. Supported type: int32. crop_size (Tuple[int]): A tuple of two elements: (crop_height, crop_width), representing the output size of the cropped and resized images. Only positive values are supported. Supported type: int32. method (str, optional): An optional string that specifies the sampling method for resizing. It can be "bilinear", "nearest" or "bilinear_v2". The option "bilinear" stands for standard bilinear interpolation algorithm, while "bilinear_v2" may result in better result in some cases. "nearest" is the nearest neighbor interpolation algorithm. Default: "bilinear". extrapolation_value (float, optional): An optional float value used extrapolation, if applicable. Default: 0.0. Returns: A 4-D tensor of shape :math:`(num_boxes, crop_height, crop_width, depth)` with type(float32). Raises: TypeError: If `image` or `boxes` or `box_indices` is not a Tensor. TypeError: If `crop_size` is not a Tuple with two int32 elements. TypeError: If dtype of `boxes` is not float or that of `box_indices` is not int. TypeError: If `method` is not a str. TypeError: If `extrapolation_value` is not a float. ValueError: If the shape rank of `image` is not 4. ValueError: If the shape rank of `boxes` is not 2. ValueError: If the second dim of `boxes` is not 4. ValueError: If the shape rank of `box_indices` is not 1. ValueError: If the first dim of `box_indices` is not equal to that of `boxes`. ValueError: If existing element in `box_indices` is out of range `[0, batch)`. ValueError: If the data of `crop_size` is not positive. ValueError: If `method` is not one of 'bilinear', 'nearest', 'bilinear_v2'. Supported Platforms: ``Ascend`` ``GPU`` ``CPU`` Examples: >>> BATCH_SIZE = 1 >>> NUM_BOXES = 5 >>> IMAGE_HEIGHT = 256 >>> IMAGE_WIDTH = 256 >>> CHANNELS = 3 >>> image = np.random.normal(size=[BATCH_SIZE, IMAGE_HEIGHT, IMAGE_WIDTH, CHANNELS]).astype(np.float32) >>> boxes = np.random.uniform(size=[NUM_BOXES, 4]).astype(np.float32) >>> box_indices = np.random.uniform(size=[NUM_BOXES], low=0, high=BATCH_SIZE).astype(np.int32) >>> crop_size = (24, 24) >>> output = ops.crop_and_resize(Tensor(image), Tensor(boxes), Tensor(box_indices), crop_size) >>> print(output.shape) (5, 24, 24, 3) """ if not isinstance(image, (Tensor, Tensor_)): raise TypeError("For crop_and_resize, the input image must be a tensor") if not isinstance(boxes, (Tensor, Tensor_)): raise TypeError("For crop_and_resize, the input boxes must be a tensor") if not isinstance(box_indices, (Tensor, Tensor_)): raise TypeError("For crop_and_resize, the input box_indices must be a tensor") if not isinstance(crop_size, tuple): raise TypeError("For crop_and_resize, the input crop_size must be a tuple, but got {}".format(type(crop_size))) if len(crop_size) != 2: raise ValueError("For crop_and_resize, the crop_size's length must be 2, bot got {}".format(len(crop_size))) if not isinstance(crop_size[0], int) or not isinstance(crop_size[1], int): raise TypeError("For crop_and_resize, the crop_size's value must be int.") if crop_size[0] <= 0 or crop_size[1] <= 0: raise ValueError("For crop_and_resize, the crop_size's value must be positive.") image_shape = image.shape if len(image_shape) != 4: raise ValueError( "For crop_and_resize, the input image must be 4D Tensor, but got is {}D".format(len(image_shape))) boxes_dtype = _get_cache_prim(P.DType)()(boxes) if boxes_dtype not in [mstype.float32]: raise TypeError( "For crop_and_resize, the input boxes must be {}, but got {}".format(mstype.float32, boxes_dtype)) boxes_shape = boxes.shape if len(boxes_shape) != 2 or boxes_shape[-1] != 4: raise ValueError("For crop_and_resize, the input boxes must be 2D and the second-dim must be 4, " "but got {}".format(boxes_shape)) box_indices_dtype = _get_cache_prim(P.DType)()(box_indices) if box_indices_dtype not in [mstype.int32]: raise TypeError( "For crop_and_resize, the input box_indices must be {}, but got {}".format(mstype.int32, box_indices_dtype)) box_indices_shape = box_indices.shape if len(box_indices_shape) != 1: raise ValueError("For crop_and_resize, the input box_indices must be 1D, but got {}".format(box_indices_shape)) if boxes_shape[0] != box_indices_shape[0]: raise ValueError("For crop_and_resize, the first dim of input box_indices must be equal to that of input boxes" ", but got {} vs {}".format(box_indices_shape[0], boxes_shape[0])) _crop_and_resize = _get_cache_prim(IMG.CropAndResize)(method, extrapolation_value) return _crop_and_resize(image, boxes, box_indices, crop_size)
__all__ = [ 'bounding_box_decode', 'bounding_box_encode', 'check_valid', 'crop_and_resize' ] __all__.sort()