mirror of https://github.com/open-mmlab/mmcv.git
parent
34ee69e0f6
commit
9e3ff5f94c
|
@ -4,6 +4,13 @@ import numbers
|
|||
import cv2
|
||||
import numpy as np
|
||||
|
||||
from .io import imread_backend
|
||||
|
||||
try:
|
||||
from PIL import Image
|
||||
except ImportError:
|
||||
Image = None
|
||||
|
||||
|
||||
def _scale_size(size, scale):
|
||||
"""Rescale a size by a ratio.
|
||||
|
@ -19,7 +26,7 @@ def _scale_size(size, scale):
|
|||
return int(w * float(scale) + 0.5), int(h * float(scale) + 0.5)
|
||||
|
||||
|
||||
interp_codes = {
|
||||
cv2_interp_codes = {
|
||||
'nearest': cv2.INTER_NEAREST,
|
||||
'bilinear': cv2.INTER_LINEAR,
|
||||
'bicubic': cv2.INTER_CUBIC,
|
||||
|
@ -27,12 +34,23 @@ interp_codes = {
|
|||
'lanczos': cv2.INTER_LANCZOS4
|
||||
}
|
||||
|
||||
if Image is not None:
|
||||
pillow_interp_codes = {
|
||||
'nearest': Image.NEAREST,
|
||||
'bilinear': Image.BILINEAR,
|
||||
'bicubic': Image.BICUBIC,
|
||||
'box': Image.BOX,
|
||||
'lanczos': Image.LANCZOS,
|
||||
'hamming': Image.HAMMING
|
||||
}
|
||||
|
||||
|
||||
def imresize(img,
|
||||
size,
|
||||
return_scale=False,
|
||||
interpolation='bilinear',
|
||||
out=None):
|
||||
out=None,
|
||||
backend=None):
|
||||
"""Resize image to a given size.
|
||||
|
||||
Args:
|
||||
|
@ -40,16 +58,32 @@ def imresize(img,
|
|||
size (tuple[int]): Target size (w, h).
|
||||
return_scale (bool): Whether to return `w_scale` and `h_scale`.
|
||||
interpolation (str): Interpolation method, accepted values are
|
||||
"nearest", "bilinear", "bicubic", "area", "lanczos".
|
||||
"nearest", "bilinear", "bicubic", "area", "lanczos" for 'cv2'
|
||||
backend, "nearest", "bilinear" for 'pillow' backend.
|
||||
out (ndarray): The output destination.
|
||||
backend (str | None): The image resize backend type. Options are `cv2`,
|
||||
`pillow`, `None`. If backend is None, the global imread_backend
|
||||
specified by ``mmcv.use_backend()`` will be used. Default: None.
|
||||
|
||||
Returns:
|
||||
tuple | ndarray: (`resized_img`, `w_scale`, `h_scale`) or
|
||||
`resized_img`.
|
||||
"""
|
||||
h, w = img.shape[:2]
|
||||
resized_img = cv2.resize(
|
||||
img, size, dst=out, interpolation=interp_codes[interpolation])
|
||||
if backend is None:
|
||||
backend = imread_backend
|
||||
if backend not in ['cv2', 'pillow']:
|
||||
raise ValueError(f'backend: {backend} is not supported for resize.'
|
||||
f"Supported backends are 'cv2', 'pillow'")
|
||||
|
||||
if backend == 'pillow':
|
||||
assert img.dtype == np.uint8, 'Pillow backend only support uint8 type'
|
||||
pil_image = Image.fromarray(img)
|
||||
pil_image = pil_image.resize(size, pillow_interp_codes[interpolation])
|
||||
resized_img = np.array(pil_image)
|
||||
else:
|
||||
resized_img = cv2.resize(
|
||||
img, size, dst=out, interpolation=cv2_interp_codes[interpolation])
|
||||
if not return_scale:
|
||||
return resized_img
|
||||
else:
|
||||
|
@ -58,7 +92,11 @@ def imresize(img,
|
|||
return resized_img, w_scale, h_scale
|
||||
|
||||
|
||||
def imresize_like(img, dst_img, return_scale=False, interpolation='bilinear'):
|
||||
def imresize_like(img,
|
||||
dst_img,
|
||||
return_scale=False,
|
||||
interpolation='bilinear',
|
||||
backend=None):
|
||||
"""Resize image to the same size of a given image.
|
||||
|
||||
Args:
|
||||
|
@ -66,13 +104,14 @@ def imresize_like(img, dst_img, return_scale=False, interpolation='bilinear'):
|
|||
dst_img (ndarray): The target image.
|
||||
return_scale (bool): Whether to return `w_scale` and `h_scale`.
|
||||
interpolation (str): Same as :func:`resize`.
|
||||
backend (str | None): Same as :func:`resize`.
|
||||
|
||||
Returns:
|
||||
tuple or ndarray: (`resized_img`, `w_scale`, `h_scale`) or
|
||||
`resized_img`.
|
||||
"""
|
||||
h, w = dst_img.shape[:2]
|
||||
return imresize(img, (w, h), return_scale, interpolation)
|
||||
return imresize(img, (w, h), return_scale, interpolation, backend=backend)
|
||||
|
||||
|
||||
def rescale_size(old_size, scale, return_scale=False):
|
||||
|
@ -112,7 +151,11 @@ def rescale_size(old_size, scale, return_scale=False):
|
|||
return new_size
|
||||
|
||||
|
||||
def imrescale(img, scale, return_scale=False, interpolation='bilinear'):
|
||||
def imrescale(img,
|
||||
scale,
|
||||
return_scale=False,
|
||||
interpolation='bilinear',
|
||||
backend=None):
|
||||
"""Resize image while keeping the aspect ratio.
|
||||
|
||||
Args:
|
||||
|
@ -124,13 +167,15 @@ def imrescale(img, scale, return_scale=False, interpolation='bilinear'):
|
|||
return_scale (bool): Whether to return the scaling factor besides the
|
||||
rescaled image.
|
||||
interpolation (str): Same as :func:`resize`.
|
||||
backend (str | None): Same as :func:`resize`.
|
||||
|
||||
Returns:
|
||||
ndarray: The rescaled image.
|
||||
"""
|
||||
h, w = img.shape[:2]
|
||||
new_size, scale_factor = rescale_size((w, h), scale, return_scale=True)
|
||||
rescaled_img = imresize(img, new_size, interpolation=interpolation)
|
||||
rescaled_img = imresize(
|
||||
img, new_size, interpolation=interpolation, backend=backend)
|
||||
if return_scale:
|
||||
return rescaled_img, scale_factor
|
||||
else:
|
||||
|
|
|
@ -131,10 +131,10 @@ def imread(img_or_path, flag='color', channel_order='bgr', backend=None):
|
|||
candidates are `color`, `grayscale` and `unchanged`.
|
||||
Note that the `turbojpeg` backened does not support `unchanged`.
|
||||
channel_order (str): Order of channel, candidates are `bgr` and `rgb`.
|
||||
backend (str|None): The image decoding backend type. Options are `cv2`,
|
||||
`pillow`, `turbojpeg`, `None`. If backend is None, the global
|
||||
imread_backend specified by ``mmcv.use_backend()`` will be used.
|
||||
Default: None.
|
||||
backend (str | None): The image decoding backend type. Options are
|
||||
`cv2`, `pillow`, `turbojpeg`, `None`. If backend is None, the
|
||||
global imread_backend specified by ``mmcv.use_backend()`` will be
|
||||
used. Default: None.
|
||||
|
||||
Returns:
|
||||
ndarray: Loaded image array.
|
||||
|
@ -181,10 +181,10 @@ def imfrombytes(content, flag='color', channel_order='bgr', backend=None):
|
|||
Args:
|
||||
content (bytes): Image bytes got from files or other streams.
|
||||
flag (str): Same as :func:`imread`.
|
||||
backend (str|None): The image decoding backend type. Options are `cv2`,
|
||||
`pillow`, `turbojpeg`, `None`. If backend is None, the global
|
||||
imread_backend specified by ``mmcv.use_backend()`` will be used.
|
||||
Default: None.
|
||||
backend (str | None): The image decoding backend type. Options are
|
||||
`cv2`, `pillow`, `turbojpeg`, `None`. If backend is None, the
|
||||
global imread_backend specified by ``mmcv.use_backend()`` will be
|
||||
used. Default: None.
|
||||
|
||||
Returns:
|
||||
ndarray: Loaded image array.
|
||||
|
|
|
@ -35,6 +35,18 @@ class TestGeometric:
|
|||
self.img, (1000, 600), interpolation=mode)
|
||||
assert resized_img.shape == (600, 1000, 3)
|
||||
|
||||
# test pillow resize
|
||||
for mode in [
|
||||
'nearest', 'bilinear', 'bicubic', 'box', 'lanczos', 'hamming'
|
||||
]:
|
||||
resized_img = mmcv.imresize(
|
||||
self.img, (1000, 600), interpolation=mode, backend='pillow')
|
||||
assert resized_img.shape == (600, 1000, 3)
|
||||
|
||||
# resize backend must be 'cv2' or 'pillow'
|
||||
with pytest.raises(ValueError):
|
||||
mmcv.imresize(self.img, (1000, 600), backend='not support')
|
||||
|
||||
def test_imresize_like(self):
|
||||
a = np.zeros((100, 200, 3))
|
||||
resized_img = mmcv.imresize_like(self.img, a)
|
||||
|
|
Loading…
Reference in New Issue