Shortcuts

Source code for mmagic.utils.img_utils

# Copyright (c) OpenMMLab. All rights reserved.
import math
from typing import List, Tuple

import numpy as np
import torch
from mmcv.transforms import to_tensor
from torchvision.utils import make_grid


[docs]def can_convert_to_image(value): """Judge whether the input value can be converted to image tensor via :func:`images_to_tensor` function. Args: value (any): The input value. Returns: bool: If true, the input value can convert to image with :func:`images_to_tensor`, and vice versa. """ if isinstance(value, (List, Tuple)): return all([can_convert_to_image(v) for v in value]) elif isinstance(value, np.ndarray) and len(value.shape) > 1: return True elif isinstance(value, torch.Tensor): return True else: return False
[docs]def image_to_tensor(img): """Trans image to tensor. Args: img (np.ndarray): The original image. Returns: Tensor: The output tensor. """ if len(img.shape) < 3: img = np.expand_dims(img, -1) img = np.ascontiguousarray(img) tensor = to_tensor(img).permute(2, 0, 1).contiguous() return tensor
[docs]def all_to_tensor(value): """Trans image and sequence of frames to tensor. Args: value (np.ndarray | list[np.ndarray] | Tuple[np.ndarray]): The original image or list of frames. Returns: Tensor: The output tensor. """ if not can_convert_to_image(value): return value if isinstance(value, (List, Tuple)): # sequence of frames if len(value) == 1: tensor = image_to_tensor(value[0]) else: frames = [image_to_tensor(v) for v in value] tensor = torch.stack(frames, dim=0) elif isinstance(value, np.ndarray): tensor = image_to_tensor(value) else: # Maybe the data has been converted to Tensor. tensor = to_tensor(value) return tensor
[docs]def tensor2img(tensor, out_type=np.uint8, min_max=(0, 1)): """Convert torch Tensors into image numpy arrays. After clamping to (min, max), image values will be normalized to [0, 1]. For different tensor shapes, this function will have different behaviors: 1. 4D mini-batch Tensor of shape (N x 3/1 x H x W): Use `make_grid` to stitch images in the batch dimension, and then convert it to numpy array. 2. 3D Tensor of shape (3/1 x H x W) and 2D Tensor of shape (H x W): Directly change to numpy array. Note that the image channel in input tensors should be RGB order. This function will convert it to cv2 convention, i.e., (H x W x C) with BGR order. Args: tensor (Tensor | list[Tensor]): Input tensors. out_type (numpy type): Output types. If ``np.uint8``, transform outputs to uint8 type with range [0, 255]; otherwise, float type with range [0, 1]. Default: ``np.uint8``. min_max (tuple): min and max values for clamp. Returns: (Tensor | list[Tensor]): 3D ndarray of shape (H x W x C) or 2D ndarray of shape (H x W). """ if not (torch.is_tensor(tensor) or (isinstance(tensor, list) and all(torch.is_tensor(t) for t in tensor))): raise TypeError( f'tensor or list of tensors expected, got {type(tensor)}') if torch.is_tensor(tensor): tensor = [tensor] result = [] for _tensor in tensor: # Squeeze two times so that: # 1. (1, 1, h, w) -> (h, w) or # 3. (1, 3, h, w) -> (3, h, w) or # 2. (n>1, 3/1, h, w) -> (n>1, 3/1, h, w) _tensor = _tensor.squeeze(0).squeeze(0) _tensor = _tensor.float().detach().cpu().clamp_(*min_max) _tensor = (_tensor - min_max[0]) / (min_max[1] - min_max[0]) n_dim = _tensor.dim() if n_dim == 4: img_np = make_grid( _tensor, nrow=int(math.sqrt(_tensor.size(0))), normalize=False).numpy() img_np = np.transpose(img_np[[2, 1, 0], :, :], (1, 2, 0)) elif n_dim == 3: img_np = _tensor.numpy() img_np = np.transpose(img_np[[2, 1, 0], :, :], (1, 2, 0)) elif n_dim == 2: img_np = _tensor.numpy() else: raise ValueError('Only support 4D, 3D or 2D tensor. ' f'But received with dimension: {n_dim}') if out_type == np.uint8: # Unlike MATLAB, numpy.unit8() WILL NOT round by default. img_np = (img_np * 255.0).round() img_np = img_np.astype(out_type) result.append(img_np) result = result[0] if len(result) == 1 else result return result
[docs]def reorder_image(img, input_order='HWC'): """Reorder images to 'HWC' order. If the input_order is (h, w), return (h, w, 1); If the input_order is (c, h, w), return (h, w, c); If the input_order is (h, w, c), return as it is. Args: img (np.ndarray): Input image. input_order (str): Whether the input order is 'HWC' or 'CHW'. If the input image shape is (h, w), input_order will not have effects. Default: 'HWC'. Returns: np.ndarray: Reordered image. """ if input_order not in ['HWC', 'CHW']: raise ValueError( f'Wrong input_order {input_order}. Supported input_orders are ' '"HWC" and "CHW"') if len(img.shape) == 2: img = img[..., None] return img if input_order == 'CHW': if isinstance(img, np.ndarray): img = img.transpose(1, 2, 0) elif isinstance(img, torch.Tensor): img = img.permute(1, 2, 0) return img
[docs]def to_numpy(img, dtype=np.float64): """Convert data into numpy arrays of dtype. Args: img (Tensor | np.ndarray): Input data. dtype (np.dtype): Set the data type of the output. Default: np.float64 Returns: img (np.ndarray): Converted numpy arrays data. """ if isinstance(img, torch.Tensor): img = img.cpu().numpy() elif not isinstance(img, np.ndarray): raise TypeError('Only support torch.tensor and np.ndarray, ' f'but got type {type(img)}') img = img.astype(dtype) return img
[docs]def get_box_info(pred_bbox, original_shape, final_size): """ Args: pred_bbox: The bounding box for the instance original_shape: Original image shape final_size: Size of the final output Returns: List: [L_pad, R_pad, T_pad, B_pad, rh, rw] """ assert len(pred_bbox) == 4 resize_startx = int(pred_bbox[0] / original_shape[0] * final_size) resize_starty = int(pred_bbox[1] / original_shape[1] * final_size) resize_endx = int(pred_bbox[2] / original_shape[0] * final_size) resize_endy = int(pred_bbox[3] / original_shape[1] * final_size) rh = resize_endx - resize_startx rw = resize_endy - resize_starty if rh < 1: if final_size - resize_endx > 1: resize_endx += 1 else: resize_startx -= 1 rh = 1 if rw < 1: if final_size - resize_endy > 1: resize_endy += 1 else: resize_starty -= 1 rw = 1 L_pad = resize_startx R_pad = final_size - resize_endx T_pad = resize_starty B_pad = final_size - resize_endy return [L_pad, R_pad, T_pad, B_pad, rh, rw]
Read the Docs v: latest
Versions
latest
stable
0.x
Downloads
pdf
epub
On Read the Docs
Project Home
Builds

Free document hosting provided by Read the Docs.