Unverified Commit 49a1d347 authored by Junjun2016's avatar Junjun2016 Committed by GitHub
Browse files

[Enhancement] Support resize or rescale to multiple (#1121)

* add resize or rescale to multiple

* add imresize_to_multiple function in mmcv.image

* fix docstring

* use to_2tuple
parent 303aa7f1
...@@ -4,7 +4,8 @@ from .colorspace import (bgr2gray, bgr2hls, bgr2hsv, bgr2rgb, bgr2ycbcr, ...@@ -4,7 +4,8 @@ from .colorspace import (bgr2gray, bgr2hls, bgr2hsv, bgr2rgb, bgr2ycbcr,
rgb2bgr, rgb2gray, rgb2ycbcr, ycbcr2bgr, ycbcr2rgb) rgb2bgr, rgb2gray, rgb2ycbcr, ycbcr2bgr, ycbcr2rgb)
from .geometric import (cutout, imcrop, imflip, imflip_, impad, from .geometric import (cutout, imcrop, imflip, imflip_, impad,
impad_to_multiple, imrescale, imresize, imresize_like, impad_to_multiple, imrescale, imresize, imresize_like,
imrotate, imshear, imtranslate, rescale_size) imresize_to_multiple, imrotate, imshear, imtranslate,
rescale_size)
from .io import imfrombytes, imread, imwrite, supported_backends, use_backend from .io import imfrombytes, imread, imwrite, supported_backends, use_backend
from .misc import tensor2imgs from .misc import tensor2imgs
from .photometric import (adjust_brightness, adjust_color, adjust_contrast, from .photometric import (adjust_brightness, adjust_color, adjust_contrast,
...@@ -16,12 +17,12 @@ from .photometric import (adjust_brightness, adjust_color, adjust_contrast, ...@@ -16,12 +17,12 @@ from .photometric import (adjust_brightness, adjust_color, adjust_contrast,
__all__ = [ __all__ = [
'bgr2gray', 'bgr2hls', 'bgr2hsv', 'bgr2rgb', 'gray2bgr', 'gray2rgb', 'bgr2gray', 'bgr2hls', 'bgr2hsv', 'bgr2rgb', 'gray2bgr', 'gray2rgb',
'hls2bgr', 'hsv2bgr', 'imconvert', 'rgb2bgr', 'rgb2gray', 'imrescale', 'hls2bgr', 'hsv2bgr', 'imconvert', 'rgb2bgr', 'rgb2gray', 'imrescale',
'imresize', 'imresize_like', 'rescale_size', 'imcrop', 'imflip', 'imflip_', 'imresize', 'imresize_like', 'imresize_to_multiple', 'rescale_size',
'impad', 'impad_to_multiple', 'imrotate', 'imfrombytes', 'imread', 'imcrop', 'imflip', 'imflip_', 'impad', 'impad_to_multiple', 'imrotate',
'imwrite', 'supported_backends', 'use_backend', 'imdenormalize', 'imfrombytes', 'imread', 'imwrite', 'supported_backends', 'use_backend',
'imnormalize', 'imnormalize_', 'iminvert', 'posterize', 'solarize', 'imdenormalize', 'imnormalize', 'imnormalize_', 'iminvert', 'posterize',
'rgb2ycbcr', 'bgr2ycbcr', 'ycbcr2rgb', 'ycbcr2bgr', 'tensor2imgs', 'solarize', 'rgb2ycbcr', 'bgr2ycbcr', 'ycbcr2rgb', 'ycbcr2bgr',
'imshear', 'imtranslate', 'adjust_color', 'imequalize', 'tensor2imgs', 'imshear', 'imtranslate', 'adjust_color', 'imequalize',
'adjust_brightness', 'adjust_contrast', 'lut_transform', 'clahe', 'adjust_brightness', 'adjust_contrast', 'lut_transform', 'clahe',
'adjust_sharpness', 'auto_contrast', 'cutout', 'adjust_lighting' 'adjust_sharpness', 'auto_contrast', 'cutout', 'adjust_lighting'
] ]
...@@ -4,6 +4,7 @@ import numbers ...@@ -4,6 +4,7 @@ import numbers
import cv2 import cv2
import numpy as np import numpy as np
from ..utils import to_2tuple
from .io import imread_backend from .io import imread_backend
try: try:
...@@ -17,13 +18,15 @@ def _scale_size(size, scale): ...@@ -17,13 +18,15 @@ def _scale_size(size, scale):
Args: Args:
size (tuple[int]): (w, h). size (tuple[int]): (w, h).
scale (float): Scaling factor. scale (float | tuple(float)): Scaling factor.
Returns: Returns:
tuple[int]: scaled size. tuple[int]: scaled size.
""" """
if isinstance(scale, (float, int)):
scale = (scale, scale)
w, h = size w, h = size
return int(w * float(scale) + 0.5), int(h * float(scale) + 0.5) return int(w * float(scale[0]) + 0.5), int(h * float(scale[1]) + 0.5)
cv2_interp_codes = { cv2_interp_codes = {
...@@ -92,6 +95,70 @@ def imresize(img, ...@@ -92,6 +95,70 @@ def imresize(img,
return resized_img, w_scale, h_scale return resized_img, w_scale, h_scale
def imresize_to_multiple(img,
divisor,
size=None,
scale_factor=None,
keep_ratio=False,
return_scale=False,
interpolation='bilinear',
out=None,
backend=None):
"""Resize image according to a given size or scale factor and then rounds
up the the resized or rescaled image size to the nearest value that can be
divided by the divisor.
Args:
img (ndarray): The input image.
divisor (int | tuple): Resized image size will be a multiple of
divisor. If divisor is a tuple, divisor should be
(w_divisor, h_divisor).
size (None | int | tuple[int]): Target size (w, h). Default: None.
scale_factor (None | float | tuple[float]): Multiplier for spatial
size. Should match input size if it is a tuple and the 2D style is
(w_scale_factor, h_scale_factor). Default: None.
keep_ratio (bool): Whether to keep the aspect ratio when resizing the
image. Default: False.
return_scale (bool): Whether to return `w_scale` and `h_scale`.
interpolation (str): Interpolation method, accepted values are
"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]
if size is not None and scale_factor is not None:
raise ValueError('only one of size or scale_factor should be defined')
elif size is None and scale_factor is None:
raise ValueError('one of size or scale_factor should be defined')
elif size is not None:
size = to_2tuple(size)
if keep_ratio:
size = rescale_size((w, h), size, return_scale=False)
else:
size = _scale_size((w, h), scale_factor)
divisor = to_2tuple(divisor)
size = tuple([int(np.ceil(s / d)) * d for s, d in zip(size, divisor)])
resized_img, w_scale, h_scale = imresize(
img,
size,
return_scale=True,
interpolation=interpolation,
out=out,
backend=backend)
if return_scale:
return resized_img, w_scale, h_scale
else:
return resized_img
def imresize_like(img, def imresize_like(img,
dst_img, dst_img,
return_scale=False, return_scale=False,
......
...@@ -47,6 +47,55 @@ class TestGeometric: ...@@ -47,6 +47,55 @@ class TestGeometric:
with pytest.raises(ValueError): with pytest.raises(ValueError):
mmcv.imresize(self.img, (1000, 600), backend='not support') mmcv.imresize(self.img, (1000, 600), backend='not support')
def test_imresize_to_multiple(self):
# test size and keep_ratio = False
resized_img = mmcv.imresize_to_multiple(
self.img, divisor=16, size=(511, 513), keep_ratio=False)
assert resized_img.shape == (528, 512, 3)
resized_img = mmcv.imresize_to_multiple(
self.img, divisor=(16, 32), size=(511, 513), keep_ratio=False)
assert resized_img.shape == (544, 512, 3)
# test size, keep_ratio = True, and return_scale
resized_img, w_scale, h_scale = mmcv.imresize_to_multiple(
self.img,
divisor=16,
size=(1000, 600),
keep_ratio=True,
return_scale=True)
assert resized_img.shape == (
608, 800, 3) and h_scale == 608 / 300 and w_scale == 800 / 400
resized_img, w_scale, h_scale = mmcv.imresize_to_multiple(
self.img,
divisor=(18, 16),
size=(1000, 600),
keep_ratio=True,
return_scale=True)
assert resized_img.shape == (
608, 810, 3) and h_scale == 608 / 300 and w_scale == 810 / 400
# test scale_factor and return_scale
resized_img, w_scale, h_scale = mmcv.imresize_to_multiple(
self.img, divisor=16, scale_factor=2, return_scale=True)
assert resized_img.shape == (
608, 800, 3) and h_scale == 608 / 300 and w_scale == 800 / 400
resized_img, w_scale, h_scale = mmcv.imresize_to_multiple(
self.img, divisor=16, scale_factor=(2, 3), return_scale=True)
assert resized_img.shape == (
912, 800, 3) and h_scale == 912 / 300 and w_scale == 800 / 400
resized_img, w_scale, h_scale = mmcv.imresize_to_multiple(
self.img, divisor=(18, 16), scale_factor=(2, 3), return_scale=True)
assert resized_img.shape == (
912, 810, 3) and h_scale == 912 / 300 and w_scale == 810 / 400
# one of size and scale_factor shuld be given
with pytest.raises(ValueError):
mmcv.imresize_to_multiple(
self.img, divisor=16, size=(1000, 600), scale_factor=2)
with pytest.raises(ValueError):
mmcv.imresize_to_multiple(
self.img, divisor=16, size=None, scale_factor=None)
def test_imresize_like(self): def test_imresize_like(self):
a = np.zeros((100, 200, 3)) a = np.zeros((100, 200, 3))
resized_img = mmcv.imresize_like(self.img, a) resized_img = mmcv.imresize_like(self.img, a)
......
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