Unverified Commit 0bf1e80c authored by Joanna's avatar Joanna Committed by GitHub
Browse files

add fast imresize (#193)



* size hint
Signed-off-by: default avatarlizz <lizz@sensetime.com>

* add fast resize
Signed-off-by: default avatarlixuanyi <lixuanyi@sensetime.com>

* fix
Signed-off-by: default avatarlixuanyi <lixuanyi@sensetime.com>

* add tests
Signed-off-by: default avatarlixuanyi <lixuanyi@sensetime.com>

* fix
Signed-off-by: default avatarlixuanyi <lixuanyi@sensetime.com>

* Update tests/test_image.py

* change format
Signed-off-by: default avatarlixuanyi <lixuanyi@sensetime.com>

* add tests
Signed-off-by: default avatarlixuanyi <lixuanyi@sensetime.com>

* add docstring
Signed-off-by: default avatarlixuanyi <lixuanyi@sensetime.com>
Co-authored-by: default avatarlizz <innerlee@users.noreply.github.com>
parent 9332a1dd
...@@ -4,8 +4,8 @@ from .transforms import (bgr2gray, bgr2hls, bgr2hsv, bgr2rgb, gray2bgr, ...@@ -4,8 +4,8 @@ from .transforms import (bgr2gray, bgr2hls, bgr2hsv, bgr2rgb, gray2bgr,
gray2rgb, hls2bgr, hsv2bgr, imcrop, imdenormalize, gray2rgb, hls2bgr, hsv2bgr, imcrop, imdenormalize,
imflip, imflip_, iminvert, imnormalize, imnormalize_, imflip, imflip_, iminvert, imnormalize, imnormalize_,
impad, impad_to_multiple, imrescale, imresize, impad, impad_to_multiple, imrescale, imresize,
imresize_like, imrotate, posterize, rgb2bgr, rgb2gray, imresize_like, imrotate, posterize, rescale_size,
solarize) rgb2bgr, rgb2gray, solarize)
__all__ = [ __all__ = [
'solarize', 'posterize', 'imread', 'imwrite', 'imfrombytes', 'bgr2gray', 'solarize', 'posterize', 'imread', 'imwrite', 'imfrombytes', 'bgr2gray',
...@@ -13,5 +13,5 @@ __all__ = [ ...@@ -13,5 +13,5 @@ __all__ = [
'hsv2bgr', 'bgr2hls', 'hls2bgr', 'iminvert', 'imflip', 'imflip_', 'hsv2bgr', 'bgr2hls', 'hls2bgr', 'iminvert', 'imflip', 'imflip_',
'imrotate', 'imcrop', 'impad', 'impad_to_multiple', 'imnormalize', 'imrotate', 'imcrop', 'impad', 'impad_to_multiple', 'imnormalize',
'imnormalize_', 'imdenormalize', 'imresize', 'imresize_like', 'imrescale', 'imnormalize_', 'imdenormalize', 'imresize', 'imresize_like', 'imrescale',
'use_backend', 'supported_backends' 'use_backend', 'supported_backends', 'rescale_size'
] ]
...@@ -5,12 +5,12 @@ from .colorspace import (bgr2gray, bgr2hls, bgr2hsv, bgr2rgb, gray2bgr, ...@@ -5,12 +5,12 @@ from .colorspace import (bgr2gray, bgr2hls, bgr2hsv, bgr2rgb, gray2bgr,
from .geometry import (imcrop, imflip, imflip_, impad, impad_to_multiple, from .geometry import (imcrop, imflip, imflip_, impad, impad_to_multiple,
imrotate) imrotate)
from .normalize import imdenormalize, imnormalize, imnormalize_ from .normalize import imdenormalize, imnormalize, imnormalize_
from .resize import imrescale, imresize, imresize_like from .resize import imrescale, imresize, imresize_like, rescale_size
__all__ = [ __all__ = [
'solarize', 'posterize', 'bgr2gray', 'rgb2gray', 'gray2bgr', 'gray2rgb', 'solarize', 'posterize', 'bgr2gray', 'rgb2gray', 'gray2bgr', 'gray2rgb',
'bgr2rgb', 'rgb2bgr', 'bgr2hsv', 'hsv2bgr', 'bgr2hls', 'hls2bgr', 'bgr2rgb', 'rgb2bgr', 'bgr2hsv', 'hsv2bgr', 'bgr2hls', 'hls2bgr',
'iminvert', 'imflip', 'imflip_', 'imrotate', 'imcrop', 'impad', 'iminvert', 'imflip', 'imflip_', 'imrotate', 'imcrop', 'impad',
'impad_to_multiple', 'imnormalize', 'imnormalize_', 'imdenormalize', 'impad_to_multiple', 'imnormalize', 'imnormalize_', 'imdenormalize',
'imresize', 'imresize_like', 'imrescale' 'imresize', 'imresize_like', 'imrescale', 'rescale_size'
] ]
...@@ -27,7 +27,11 @@ interp_codes = { ...@@ -27,7 +27,11 @@ interp_codes = {
} }
def imresize(img, size, return_scale=False, interpolation='bilinear'): def imresize(img,
size,
return_scale=False,
interpolation='bilinear',
out=None):
"""Resize image to a given size. """Resize image to a given size.
Args: Args:
...@@ -36,6 +40,7 @@ def imresize(img, size, return_scale=False, interpolation='bilinear'): ...@@ -36,6 +40,7 @@ def imresize(img, size, return_scale=False, interpolation='bilinear'):
return_scale (bool): Whether to return `w_scale` and `h_scale`. return_scale (bool): Whether to return `w_scale` and `h_scale`.
interpolation (str): Interpolation method, accepted values are interpolation (str): Interpolation method, accepted values are
"nearest", "bilinear", "bicubic", "area", "lanczos". "nearest", "bilinear", "bicubic", "area", "lanczos".
out (ndarray): The output destination.
Returns: Returns:
tuple or ndarray: (`resized_img`, `w_scale`, `h_scale`) or tuple or ndarray: (`resized_img`, `w_scale`, `h_scale`) or
...@@ -43,7 +48,7 @@ def imresize(img, size, return_scale=False, interpolation='bilinear'): ...@@ -43,7 +48,7 @@ def imresize(img, size, return_scale=False, interpolation='bilinear'):
""" """
h, w = img.shape[:2] h, w = img.shape[:2]
resized_img = cv2.resize( resized_img = cv2.resize(
img, size, interpolation=interp_codes[interpolation]) img, size, dst=out, interpolation=interp_codes[interpolation])
if not return_scale: if not return_scale:
return resized_img return resized_img
else: else:
...@@ -69,23 +74,22 @@ def imresize_like(img, dst_img, return_scale=False, interpolation='bilinear'): ...@@ -69,23 +74,22 @@ def imresize_like(img, dst_img, return_scale=False, interpolation='bilinear'):
return imresize(img, (w, h), return_scale, interpolation) return imresize(img, (w, h), return_scale, interpolation)
def imrescale(img, scale, return_scale=False, interpolation='bilinear'): def rescale_size(old_size, scale, return_scale=False):
"""Resize image while keeping the aspect ratio. """Calculate the new size to be rescaled to.
Args: Args:
img (ndarray): The input image. old_size (tuple[int]): The old size of image.
scale (float or tuple[int]): The scaling factor or maximum size. scale (float or tuple[int]): The scaling factor or maximum size.
If it is a float number, then the image will be rescaled by this If it is a float number, then the image will be rescaled by this
factor, else if it is a tuple of 2 integers, then the image will factor, else if it is a tuple of 2 integers, then the image will
be rescaled as large as possible within the scale. be rescaled as large as possible within the scale.
return_scale (bool): Whether to return the scaling factor besides the return_scale (bool): Whether to return the scaling factor besides the
rescaled image. rescaled image size.
interpolation (str): Same as :func:`resize`.
Returns: Returns:
ndarray: The rescaled image. tuple[int]: The new rescaled image size.
""" """
h, w = img.shape[:2] w, h = old_size
if isinstance(scale, (float, int)): if isinstance(scale, (float, int)):
if scale <= 0: if scale <= 0:
raise ValueError( raise ValueError(
...@@ -100,7 +104,33 @@ def imrescale(img, scale, return_scale=False, interpolation='bilinear'): ...@@ -100,7 +104,33 @@ def imrescale(img, scale, return_scale=False, interpolation='bilinear'):
raise TypeError( raise TypeError(
'Scale must be a number or tuple of int, but got {}'.format( 'Scale must be a number or tuple of int, but got {}'.format(
type(scale))) type(scale)))
new_size = _scale_size((w, h), scale_factor) new_size = _scale_size((w, h), scale_factor)
if return_scale:
return new_size, scale_factor
else:
return new_size
def imrescale(img, scale, return_scale=False, interpolation='bilinear'):
"""Resize image while keeping the aspect ratio.
Args:
img (ndarray): The input image.
scale (float or tuple[int]): The scaling factor or maximum size.
If it is a float number, then the image will be rescaled by this
factor, else if it is a tuple of 2 integers, then the image will
be rescaled as large as possible within the scale.
return_scale (bool): Whether to return the scaling factor besides the
rescaled image.
interpolation (str): 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)
if return_scale: if return_scale:
return rescaled_img, scale_factor return rescaled_img, scale_factor
......
...@@ -258,6 +258,11 @@ class TestImage(object): ...@@ -258,6 +258,11 @@ class TestImage(object):
True) True)
assert (resized_img.shape == (600, 1000, 3) and w_scale == 2.5 assert (resized_img.shape == (600, 1000, 3) and w_scale == 2.5
and h_scale == 2.0) and h_scale == 2.0)
resized_img_dst = np.empty((600, 1000, 3), dtype=self.img.dtype)
resized_img = mmcv.imresize(self.img, (1000, 600), out=resized_img_dst)
assert id(resized_img_dst) == id(resized_img)
assert_array_equal(resized_img_dst,
mmcv.imresize(self.img, (1000, 600)))
for mode in ['nearest', 'bilinear', 'bicubic', 'area', 'lanczos']: for mode in ['nearest', 'bilinear', 'bicubic', 'area', 'lanczos']:
resized_img = mmcv.imresize( resized_img = mmcv.imresize(
self.img, (1000, 600), interpolation=mode) self.img, (1000, 600), interpolation=mode)
...@@ -268,6 +273,34 @@ class TestImage(object): ...@@ -268,6 +273,34 @@ class TestImage(object):
resized_img = mmcv.imresize_like(self.img, a) resized_img = mmcv.imresize_like(self.img, a)
assert resized_img.shape == (100, 200, 3) assert resized_img.shape == (100, 200, 3)
def test_rescale_size(self):
new_size, scale_factor = mmcv.rescale_size((400, 300), 1.5, True)
assert new_size == (600, 450) and scale_factor == 1.5
new_size, scale_factor = mmcv.rescale_size((400, 300), 0.934, True)
assert new_size == (374, 280) and scale_factor == 0.934
new_size = mmcv.rescale_size((400, 300), 1.5)
assert new_size == (600, 450)
new_size = mmcv.rescale_size((400, 300), 0.934)
assert new_size == (374, 280)
new_size, scale_factor = mmcv.rescale_size((400, 300), (1000, 600),
True)
assert new_size == (800, 600) and scale_factor == 2.0
new_size, scale_factor = mmcv.rescale_size((400, 300), (180, 200),
True)
assert new_size == (200, 150) and scale_factor == 0.5
new_size = mmcv.rescale_size((400, 300), (1000, 600))
assert new_size == (800, 600)
new_size = mmcv.rescale_size((400, 300), (180, 200))
assert new_size == (200, 150)
with pytest.raises(ValueError):
mmcv.rescale_size((400, 300), -0.5)
with pytest.raises(TypeError):
mmcv.rescale_size()((400, 300), [100, 100])
def test_imrescale(self): def test_imrescale(self):
# rescale by a certain factor # rescale by a certain factor
resized_img = mmcv.imrescale(self.img, 1.5) resized_img = mmcv.imrescale(self.img, 1.5)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment