Commit f872672f authored by Kai Chen's avatar Kai Chen
Browse files

renaming and reorganizing for subpackage

parent eadd1e0f
from .io import *
from .processing import *
from .transforms import *
......@@ -19,8 +19,10 @@ imread_flags = {
'unchanged': IMREAD_UNCHANGED
}
__all__ = ['imread', 'imwrite', 'imfrombytes']
def read_img(img_or_path, flag='color'):
def imread(img_or_path, flag='color'):
"""Read an image.
Args:
......@@ -44,12 +46,12 @@ def read_img(img_or_path, flag='color'):
raise TypeError('"img" must be a numpy array or a filename')
def img_from_bytes(content, flag='color'):
def imfrombytes(content, flag='color'):
"""Read an image from bytes.
Args:
content (bytes): Image bytes got from files or other streams.
flag (str): Same as :func:`read_img`.
flag (str): Same as :func:`imread`.
Returns:
ndarray: Loaded image array.
......@@ -60,11 +62,11 @@ def img_from_bytes(content, flag='color'):
return img
def write_img(img, file_path, params=None, auto_mkdir=True):
def imwrite(img, file_path, params=None, auto_mkdir=True):
"""Write image to file
Args:
img (ndarray): Image to be written to file.
img (ndarray): Image array to be written.
file_path (str): Image file path.
params (None or list): Same as opencv's :func:`imwrite` interface.
auto_mkdir (bool): If the parrent folder of `file_path` does not exist,
......
from .colorspace import *
from .geometry import *
from .resize import *
import cv2
__all__ = ['bgr2gray', 'gray2bgr', 'bgr2rgb', 'rgb2bgr', 'bgr2hsv', 'hsv2bgr']
def bgr2gray(img, keepdim=False):
"""Convert a BGR image to grayscale image.
Args:
img (ndarray): The input image.
keepdim (bool): If False (by default), then return the grayscale image
with 2 dims, otherwise 3 dims.
Returns:
ndarray: The converted grayscale image.
"""
out_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
if keepdim:
out_img = out_img[..., None]
return out_img
def gray2bgr(img):
"""Convert a grayscale image to BGR image.
Args:
img (ndarray or str): The input image.
Returns:
ndarray: The converted BGR image.
"""
img = img[..., None] if img.ndim == 2 else img
out_img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
return out_img
def convert_color_factory(src, dst):
code = getattr(cv2, 'COLOR_{}2{}'.format(src.upper(), dst.upper()))
def convert_color(img):
out_img = cv2.cvtColor(img, code)
return out_img
convert_color.__doc__ = """Convert a {0} image to {1} image.
Args:
img (ndarray or str): The input image.
Returns:
ndarray: The converted {1} image.
""".format(src.upper(), dst.upper())
return convert_color
bgr2rgb = convert_color_factory('bgr', 'rgb')
rgb2bgr = convert_color_factory('rgb', 'bgr')
bgr2hsv = convert_color_factory('bgr', 'hsv')
hsv2bgr = convert_color_factory('hsv', 'bgr')
from __future__ import division
import cv2
import numpy as np
from .io import read_img
def bgr2gray(img, keepdim=False):
"""Convert a BGR image to grayscale image.
Args:
img (ndarray or str): The input image or image path.
keepdim (bool): If False (by default), then return the grayscale image
with 2 dims, otherwise 3 dims.
Returns:
ndarray: The converted grayscale image.
"""
in_img = read_img(img)
out_img = cv2.cvtColor(in_img, cv2.COLOR_BGR2GRAY)
if keepdim:
out_img = out_img[..., None]
return out_img
def gray2bgr(img):
"""Convert a grayscale image to BGR image.
Args:
img (ndarray or str): The input image or image path.
Returns:
ndarray: The converted BGR image.
"""
in_img = read_img(img)
in_img = in_img[..., None] if in_img.ndim == 2 else in_img
out_img = cv2.cvtColor(in_img, cv2.COLOR_GRAY2BGR)
return out_img
def convert_color_factory(src, dst):
code = getattr(cv2, 'COLOR_{}2{}'.format(src.upper(), dst.upper()))
__all__ = ['imrotate', 'imcrop', 'impad']
def convert_color(img):
in_img = read_img(img)
out_img = cv2.cvtColor(in_img, code)
return out_img
convert_color.__doc__ = """Convert a {0} image to {1} image
Args:
img (ndarray or str): The input image or image path.
Returns:
ndarray: The converted {1} image
""".format(src.upper(), dst.upper())
return convert_color
bgr2rgb = convert_color_factory('bgr', 'rgb')
rgb2bgr = convert_color_factory('rgb', 'bgr')
bgr2hsv = convert_color_factory('bgr', 'hsv')
hsv2bgr = convert_color_factory('hsv', 'bgr')
def scale_size(size, scale):
"""Rescale a size by a ratio.
Args:
size (tuple): w, h.
scale (float): Scaling factor.
Returns:
tuple[int]: scaled size.
"""
w, h = size
return int(w * float(scale) + 0.5), int(h * float(scale) + 0.5)
interp_codes = {
'nearest': cv2.INTER_NEAREST,
'bilinear': cv2.INTER_LINEAR,
'bicubic': cv2.INTER_CUBIC,
'area': cv2.INTER_AREA,
'lanczos': cv2.INTER_LANCZOS4
}
def resize(img, size, return_scale=False, interpolation='bilinear'):
"""Resize image to a given size.
Args:
img (ndarray): The input image or image path.
size (tuple): Target (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".
Returns:
tuple or ndarray: (`resized_img`, `w_scale`, `h_scale`) or
`resized_img`.
"""
img = read_img(img)
h, w = img.shape[:2]
resized_img = cv2.resize(
img, size, interpolation=interp_codes[interpolation])
if not return_scale:
return resized_img
else:
w_scale = size[0] / float(w)
h_scale = size[1] / float(h)
return resized_img, w_scale, h_scale
def resize_like(img, dst_img, return_scale=False, interpolation='bilinear'):
"""Resize image to the same size of a given image.
Args:
img (ndarray): The input image or image path.
dst_img (ndarray): The target image.
return_scale (bool): Whether to return `w_scale` and `h_scale`.
interpolation (str): Same as :func:`resize`.
Returns:
tuple or ndarray: (`resized_img`, `w_scale`, `h_scale`) or
`resized_img`.
"""
h, w = dst_img.shape[:2]
return resize(img, (w, h), return_scale, interpolation)
def resize_by_ratio(img, ratio, interpolation='bilinear'):
"""Resize image by a ratio.
Args:
img (ndarray): The input image or image path.
ratio (float): Scaling factor.
interpolation (str): Same as :func:`resize`.
Returns:
ndarray: The resized image
"""
assert isinstance(ratio, (float, int)) and ratio > 0
img = read_img(img)
h, w = img.shape[:2]
new_size = scale_size((w, h), ratio)
return resize(img, new_size, interpolation=interpolation)
def resize_keep_ar(img,
max_long_edge,
max_short_edge,
return_scale=False,
interpolation='bilinear'):
"""Resize image with aspect ratio unchanged.
The long edge of resized image will be no greater than `max_long_edge`,
and the short edge of resized image is no greater than `max_short_edge`.
def imrotate(img,
angle,
center=None,
scale=1.0,
border_value=0,
auto_bound=False):
"""Rotate an image.
Args:
img (ndarray): The input image or image path.
max_long_edge (int): Max value of the long edge of resized image.
max_short_edge (int): Max value of the short edge of resized image.
return_scale (bool): Whether to return scale besides the resized image.
interpolation (str): Same as :func:`resize`.
img (ndarray or str): Image to be rotated.
angle (float): Rotation angle in degrees, positive values mean
clockwise rotation.
center (tuple): Center of the rotation in the source image, by default
it is the center of the image.
scale (float): Isotropic scale factor.
border_value (int): Border value.
auto_bound (bool): Whether to adjust the image size to cover the whole
rotated image.
Returns:
tuple or ndarray: (resized_img, scale_factor) or resized_img.
ndarray: The rotated image.
"""
if max_long_edge < max_short_edge:
raise ValueError(
'"max_long_edge" should not be less than "max_short_edge"')
img = read_img(img)
if center is not None and auto_bound:
raise ValueError('`auto_bound` conflicts with `center`')
h, w = img.shape[:2]
ratio = min(
float(max_long_edge) / max(h, w),
float(max_short_edge) / min(h, w))
new_size = scale_size((w, h), ratio)
resized_img = resize(img, new_size, interpolation=interpolation)
if return_scale:
return resized_img, ratio
else:
return resized_img
def limit_size(img, max_edge, return_scale=False, interpolation='bilinear'):
"""Limit the size of an image.
If the long edge of the image is greater than max_edge, resize the image.
Args:
img (ndarray): The input image or image path.
max_edge (int): Maximum value of the long edge.
return_scale (bool): Whether to return scale besides the resized image.
interpolation (str): Same as :func:`resize`.
if center is None:
center = ((w - 1) * 0.5, (h - 1) * 0.5)
assert isinstance(center, tuple)
Returns:
tuple or ndarray: (resized_img, scale_factor) or resized_img.
"""
img = read_img(img)
h, w = img.shape[:2]
if max(h, w) > max_edge:
scale = float(max_edge) / max(h, w)
new_size = scale_size((w, h), scale)
resized_img = resize(img, new_size, interpolation=interpolation)
else:
scale = 1.0
resized_img = img
if return_scale:
return resized_img, scale
else:
return resized_img
matrix = cv2.getRotationMatrix2D(center, -angle, scale)
if auto_bound:
cos = np.abs(matrix[0, 0])
sin = np.abs(matrix[0, 1])
new_w = h * sin + w * cos
new_h = h * cos + w * sin
matrix[0, 2] += (new_w - w) * 0.5
matrix[1, 2] += (new_h - h) * 0.5
w = int(np.round(new_w))
h = int(np.round(new_h))
rotated = cv2.warpAffine(img, matrix, (w, h), borderValue=border_value)
return rotated
def bbox_clip(bboxes, img_shape):
......@@ -229,16 +58,12 @@ def bbox_clip(bboxes, img_shape):
ndarray: Clipped bboxes.
"""
assert bboxes.shape[-1] % 4 == 0
cliped_bboxes = np.empty_like(bboxes, dtype=bboxes.dtype)
cliped_bboxes[..., 0::4] = np.maximum(
np.minimum(bboxes[..., 0::4], img_shape[1] - 1), 0)
cliped_bboxes[..., 1::4] = np.maximum(
np.minimum(bboxes[..., 1::4], img_shape[0] - 1), 0)
cliped_bboxes[..., 2::4] = np.maximum(
np.minimum(bboxes[..., 2::4], img_shape[1] - 1), 0)
cliped_bboxes[..., 3::4] = np.maximum(
np.minimum(bboxes[..., 3::4], img_shape[0] - 1), 0)
return cliped_bboxes
clipped_bboxes = np.empty_like(bboxes, dtype=bboxes.dtype)
clipped_bboxes[..., 0::2] = np.maximum(
np.minimum(bboxes[..., 0::2], img_shape[1] - 1), 0)
clipped_bboxes[..., 1::2] = np.maximum(
np.minimum(bboxes[..., 1::2], img_shape[0] - 1), 0)
return clipped_bboxes
def bbox_scaling(bboxes, scale, clip_shape=None):
......@@ -267,7 +92,7 @@ def bbox_scaling(bboxes, scale, clip_shape=None):
return scaled_bboxes
def crop_img(img, bboxes, scale_ratio=1.0, pad_fill=None):
def imcrop(img, bboxes, scale_ratio=1.0, pad_fill=None):
"""Crop image patches.
3 steps: scale the bboxes -> clip bboxes -> crop and pad.
......@@ -288,17 +113,18 @@ def crop_img(img, bboxes, scale_ratio=1.0, pad_fill=None):
if isinstance(pad_fill, (int, float)):
pad_fill = [pad_fill for _ in range(chn)]
assert len(pad_fill) == chn
img = read_img(img)
_bboxes = bboxes[None, ...] if bboxes.ndim == 1 else bboxes
scaled_bboxes = bbox_scaling(_bboxes, scale_ratio).astype(np.int32)
clipped_bbox = bbox_clip(scaled_bboxes, img.shape)
patches = []
for i in range(clipped_bbox.shape[0]):
x1, y1, x2, y2 = tuple(clipped_bbox[i, :].tolist())
x1, y1, x2, y2 = tuple(clipped_bbox[i, :])
if pad_fill is None:
patch = img[y1:y2 + 1, x1:x2 + 1, ...]
else:
_x1, _y1, _x2, _y2 = tuple(scaled_bboxes[i, :].tolist())
_x1, _y1, _x2, _y2 = tuple(scaled_bboxes[i, :])
if chn == 2:
patch_shape = (_y2 - _y1 + 1, _x2 - _x1 + 1)
else:
......@@ -313,13 +139,14 @@ def crop_img(img, bboxes, scale_ratio=1.0, pad_fill=None):
patch[y_start:y_start + h, x_start:x_start +
w, ...] = img[y1:y1 + h, x1:x1 + w, ...]
patches.append(patch)
if bboxes.ndim == 1:
return patches[0]
else:
return patches
def pad_img(img, shape, pad_val):
def impad(img, shape, pad_val):
"""Pad an image to a certain shape.
Args:
......@@ -341,46 +168,3 @@ def pad_img(img, shape, pad_val):
pad[...] = pad_val
pad[:img.shape[0], :img.shape[1], ...] = img
return pad
def rotate_img(img,
angle,
center=None,
scale=1.0,
border_value=0,
auto_bound=False):
"""Rotate an image.
Args:
img (ndarray or str): Image to be rotated.
angle (float): Rotation angle in degrees, positive values mean
clockwise rotation.
center (tuple): Center of the rotation in the source image, by default
it is the center of the image.
scale (float): Isotropic scale factor.
border_value (int): Border value.
auto_bound (bool): Whether to adjust the image size to cover the whole
rotated image.
Returns:
ndarray: The rotated image.
"""
if center is not None and auto_bound:
raise ValueError('`auto_bound` conflicts with `center`')
img = read_img(img)
h, w = img.shape[:2]
if center is None:
center = ((w - 1) / 2, (h - 1) / 2)
assert isinstance(center, tuple)
matrix = cv2.getRotationMatrix2D(center, -angle, scale)
if auto_bound:
cos = np.abs(matrix[0, 0])
sin = np.abs(matrix[0, 1])
new_w = h * sin + w * cos
new_h = h * cos + w * sin
matrix[0, 2] += (new_w - w) / 2
matrix[1, 2] += (new_h - h) / 2
w = int(np.round(new_w))
h = int(np.round(new_h))
rotated = cv2.warpAffine(img, matrix, (w, h), borderValue=border_value)
return rotated
from __future__ import division
import cv2
def scale_size(size, scale):
"""Rescale a size by a ratio.
Args:
size (tuple): w, h.
scale (float): Scaling factor.
Returns:
tuple[int]: scaled size.
"""
w, h = size
return int(w * float(scale) + 0.5), int(h * float(scale) + 0.5)
interp_codes = {
'nearest': cv2.INTER_NEAREST,
'bilinear': cv2.INTER_LINEAR,
'bicubic': cv2.INTER_CUBIC,
'area': cv2.INTER_AREA,
'lanczos': cv2.INTER_LANCZOS4
}
def imresize(img, size, return_scale=False, interpolation='bilinear'):
"""Resize image to a given size.
Args:
img (ndarray): The input image.
size (tuple): Target (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".
Returns:
tuple or ndarray: (`resized_img`, `w_scale`, `h_scale`) or
`resized_img`.
"""
h, w = img.shape[:2]
resized_img = cv2.resize(
img, size, interpolation=interp_codes[interpolation])
if not return_scale:
return resized_img
else:
w_scale = size[0] / w
h_scale = size[1] / h
return resized_img, w_scale, h_scale
def imresize_like(img, dst_img, return_scale=False, interpolation='bilinear'):
"""Resize image to the same size of a given image.
Args:
img (ndarray): The input image.
dst_img (ndarray): The target image.
return_scale (bool): Whether to return `w_scale` and `h_scale`.
interpolation (str): 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)
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]
if isinstance(scale, (float, int)):
if scale <= 0:
raise ValueError(
'Invalid scale {}, must be positive.'.format(scale))
scale_factor = scale
elif isinstance(scale, tuple):
max_long_edge = max(scale)
max_short_edge = min(scale)
scale_factor = min(max_long_edge / max(h, w),
max_short_edge / min(h, w))
else:
raise TypeError(
'Scale must be a number or tuple of int, but got {}'.format(
type(scale)))
new_size = scale_size((w, h), scale_factor)
rescaled_img = imresize(img, new_size, interpolation=interpolation)
if return_scale:
return rescaled_img, scale_factor
else:
return rescaled_img
def limit_size(img, max_edge, return_scale=False, interpolation='bilinear'):
"""Limit the size of an image.
If the long edge of the image is greater than max_edge, resize the image.
Args:
img (ndarray): The input image.
max_edge (int): Maximum value of the long edge.
return_scale (bool): Whether to return scale besides the resized image.
interpolation (str): Same as :func:`resize`.
Returns:
tuple or ndarray: (resized_img, scale_factor) or resized_img.
"""
h, w = img.shape[:2]
if max(h, w) > max_edge:
scale = float(max_edge) / max(h, w)
new_size = scale_size((w, h), scale)
resized_img = imresize(img, new_size, interpolation=interpolation)
else:
scale = 1.0
resized_img = img
if return_scale:
return resized_img, scale
else:
return resized_img
import numpy as np
from mmcv.image import read_img, write_img
from mmcv.image import imread, imwrite
from mmcv.utils import is_str
......@@ -52,8 +52,8 @@ def read_flow(flow_or_path, quantize=False, *args, **kwargs):
flow = np.fromfile(f, np.float32, w * h * 2).reshape((h, w, 2))
else:
dx_filename, dy_filename = _pair_name(flow_or_path)
dx = read_img(dx_filename, flag='unchanged')
dy = read_img(dy_filename, flag='unchanged')
dx = imread(dx_filename, flag='unchanged')
dy = imread(dy_filename, flag='unchanged')
flow = dequantize_flow(dx, dy, *args, **kwargs)
return flow.astype(np.float32)
......@@ -79,8 +79,8 @@ def write_flow(flow, filename, quantize=False, *args, **kwargs):
else:
dx, dy = quantize_flow(flow, *args, **kwargs)
dx_filename, dy_filename = _pair_name(filename)
write_img(dx, dx_filename)
write_img(dy, dy_filename)
imwrite(dx, dx_filename)
imwrite(dy, dy_filename)
def quantize_flow(flow, max_val=0.02, norm=True):
......
import cv2
import numpy as np
from mmcv.image import read_img, write_img
from mmcv.image import imread, imwrite
from .color import color_val
......@@ -13,7 +13,7 @@ def show_img(img, win_name='', wait_time=0):
win_name (str): The window name.
wait_time (int): Value of waitKey param.
"""
cv2.imshow(win_name, read_img(img))
cv2.imshow(win_name, imread(img))
cv2.waitKey(wait_time)
......@@ -39,7 +39,7 @@ def draw_bboxes(img,
wait_time (int): Value of waitKey param.
out_file (str, optional): The filename to write the image.
"""
img = read_img(img)
img = imread(img)
if isinstance(bboxes, np.ndarray):
bboxes = [bboxes]
......@@ -63,4 +63,4 @@ def draw_bboxes(img,
if show:
show_img(img, win_name, wait_time)
if out_file is not None:
write_img(img, out_file)
imwrite(img, out_file)
......@@ -2,6 +2,7 @@ import os
import os.path as osp
import tempfile
import cv2
import mmcv
import numpy as np
import pytest
......@@ -16,6 +17,7 @@ class TestImage(object):
cls.img_path = osp.join(osp.dirname(__file__), 'data/color.jpg')
cls.gray_img_path = osp.join(
osp.dirname(__file__), 'data/grayscale.jpg')
cls.img = cv2.imread(cls.img_path)
def assert_img_equal(self, img, ref_img, ratio_thr=0.999):
assert img.shape == ref_img.shape
......@@ -24,31 +26,31 @@ class TestImage(object):
diff = np.abs(img.astype('int32') - ref_img.astype('int32'))
assert np.sum(diff <= 1) / float(area) > ratio_thr
def test_read_img(self):
img = mmcv.read_img(self.img_path)
def test_imread(self):
img = mmcv.imread(self.img_path)
assert img.shape == (300, 400, 3)
img = mmcv.read_img(self.img_path, 'grayscale')
img = mmcv.imread(self.img_path, 'grayscale')
assert img.shape == (300, 400)
img = mmcv.read_img(self.gray_img_path)
img = mmcv.imread(self.gray_img_path)
assert img.shape == (300, 400, 3)
img = mmcv.read_img(self.gray_img_path, 'unchanged')
img = mmcv.imread(self.gray_img_path, 'unchanged')
assert img.shape == (300, 400)
img = mmcv.read_img(img)
assert_array_equal(img, mmcv.read_img(img))
img = mmcv.imread(img)
assert_array_equal(img, mmcv.imread(img))
with pytest.raises(TypeError):
mmcv.read_img(1)
mmcv.imread(1)
def test_img_from_bytes(self):
def test_imfrombytes(self):
with open(self.img_path, 'rb') as f:
img_bytes = f.read()
img = mmcv.img_from_bytes(img_bytes)
img = mmcv.imfrombytes(img_bytes)
assert img.shape == (300, 400, 3)
def test_write_img(self):
img = mmcv.read_img(self.img_path)
def test_imwrite(self):
img = mmcv.imread(self.img_path)
out_file = osp.join(tempfile.gettempdir(), 'mmcv_test.jpg')
mmcv.write_img(img, out_file)
rewrite_img = mmcv.read_img(out_file)
mmcv.imwrite(img, out_file)
rewrite_img = mmcv.imread(out_file)
os.remove(out_file)
self.assert_img_equal(img, rewrite_img)
......@@ -112,66 +114,71 @@ class TestImage(object):
assert mmcv.scale_size((300, 200), 0.5) == (150, 100)
assert mmcv.scale_size((11, 22), 0.7) == (8, 15)
def test_resize(self):
resized_img = mmcv.resize(self.img_path, (1000, 600))
def test_imresize(self):
resized_img = mmcv.imresize(self.img, (1000, 600))
assert resized_img.shape == (600, 1000, 3)
resized_img, w_scale, h_scale = mmcv.resize(self.img_path, (1000, 600),
True)
resized_img, w_scale, h_scale = mmcv.imresize(self.img, (1000, 600),
True)
assert (resized_img.shape == (600, 1000, 3) and w_scale == 2.5
and h_scale == 2.0)
for mode in ['nearest', 'bilinear', 'bicubic', 'area', 'lanczos']:
resized_img = mmcv.resize(
self.img_path, (1000, 600), interpolation=mode)
resized_img = mmcv.imresize(
self.img, (1000, 600), interpolation=mode)
assert resized_img.shape == (600, 1000, 3)
def test_resize_like(self):
def test_imresize_like(self):
a = np.zeros((100, 200, 3))
resized_img = mmcv.resize_like(self.img_path, a)
resized_img = mmcv.imresize_like(self.img, a)
assert resized_img.shape == (100, 200, 3)
def test_resize_by_ratio(self):
resized_img = mmcv.resize_by_ratio(self.img_path, 1.5)
def test_imrescale(self):
# rescale by a certain factor
resized_img = mmcv.imrescale(self.img, 1.5)
assert resized_img.shape == (450, 600, 3)
resized_img = mmcv.resize_by_ratio(self.img_path, 0.934)
resized_img = mmcv.imrescale(self.img, 0.934)
assert resized_img.shape == (280, 374, 3)
def test_resize_keep_ar(self):
# rescale by a certain max_size
# resize (400, 300) to (max_1000, max_600)
resized_img = mmcv.resize_keep_ar(self.img_path, 1000, 600)
resized_img = mmcv.imrescale(self.img, (1000, 600))
assert resized_img.shape == (600, 800, 3)
resized_img, scale = mmcv.resize_keep_ar(self.img_path, 1000, 600,
True)
resized_img, scale = mmcv.imrescale(
self.img, (1000, 600), return_scale=True)
assert resized_img.shape == (600, 800, 3) and scale == 2.0
# resize (400, 300) to (max_200, max_180)
img = mmcv.read_img(self.img_path)
resized_img = mmcv.resize_keep_ar(img, 200, 180)
resized_img = mmcv.imrescale(self.img, (180, 200))
assert resized_img.shape == (150, 200, 3)
resized_img, scale = mmcv.resize_keep_ar(self.img_path, 200, 180, True)
resized_img, scale = mmcv.imrescale(
self.img, (180, 200), return_scale=True)
assert resized_img.shape == (150, 200, 3) and scale == 0.5
# max_long_edge cannot be less than max_short_edge
# test exceptions
with pytest.raises(ValueError):
mmcv.resize_keep_ar(self.img_path, 500, 600)
mmcv.imrescale(self.img, -0.5)
with pytest.raises(TypeError):
mmcv.imrescale(self.img, [100, 100])
def test_limit_size(self):
# limit to 800
resized_img = mmcv.limit_size(self.img_path, 800)
resized_img = mmcv.limit_size(self.img, 800)
assert resized_img.shape == (300, 400, 3)
resized_img, scale = mmcv.limit_size(self.img_path, 800, True)
resized_img, scale = mmcv.limit_size(self.img, 800, True)
assert resized_img.shape == (300, 400, 3) and scale == 1
# limit to 200
resized_img = mmcv.limit_size(self.img_path, 200)
resized_img = mmcv.limit_size(self.img, 200)
assert resized_img.shape == (150, 200, 3)
resized_img, scale = mmcv.limit_size(self.img_path, 200, True)
resized_img, scale = mmcv.limit_size(self.img, 200, True)
assert resized_img.shape == (150, 200, 3) and scale == 0.5
# test with img rather than img path
img = mmcv.read_img(self.img_path)
img = mmcv.imread(self.img)
resized_img = mmcv.limit_size(img, 200)
assert resized_img.shape == (150, 200, 3)
resized_img, scale = mmcv.limit_size(img, 200, True)
assert resized_img.shape == (150, 200, 3) and scale == 0.5
def test_crop_img(self):
img = mmcv.read_img(self.img_path)
def test_imcrop(self):
# yapf: disable
bboxes = np.array([[100, 100, 199, 199], # center
[0, 0, 150, 100], # left-top corner
......@@ -179,46 +186,51 @@ class TestImage(object):
[0, 100, 399, 199], # wide
[150, 0, 299, 299]]) # tall
# yapf: enable
# crop one bbox
patch = mmcv.crop_img(img, bboxes[0, :])
patches = mmcv.crop_img(img, bboxes[[0], :])
patch = mmcv.imcrop(self.img, bboxes[0, :])
patches = mmcv.imcrop(self.img, bboxes[[0], :])
assert patch.shape == (100, 100, 3)
patch_path = osp.join(osp.dirname(__file__), 'data/patches')
ref_patch = np.load(patch_path + '/0.npy')
self.assert_img_equal(patch, ref_patch)
assert isinstance(patches, list) and len(patches) == 1
self.assert_img_equal(patches[0], ref_patch)
# crop with no scaling and padding
patches = mmcv.crop_img(img, bboxes)
patches = mmcv.imcrop(self.img, bboxes)
assert len(patches) == bboxes.shape[0]
for i in range(len(patches)):
ref_patch = np.load(patch_path + '/{}.npy'.format(i))
self.assert_img_equal(patches[i], ref_patch)
# crop with scaling and no padding
patches = mmcv.crop_img(img, bboxes, 1.2)
patches = mmcv.imcrop(self.img, bboxes, 1.2)
for i in range(len(patches)):
ref_patch = np.load(patch_path + '/scale_{}.npy'.format(i))
self.assert_img_equal(patches[i], ref_patch)
# crop with scaling and padding
patches = mmcv.crop_img(img, bboxes, 1.2, pad_fill=[255, 255, 0])
patches = mmcv.imcrop(self.img, bboxes, 1.2, pad_fill=[255, 255, 0])
for i in range(len(patches)):
ref_patch = np.load(patch_path + '/pad_{}.npy'.format(i))
self.assert_img_equal(patches[i], ref_patch)
patches = mmcv.crop_img(img, bboxes, 1.2, pad_fill=0)
patches = mmcv.imcrop(self.img, bboxes, 1.2, pad_fill=0)
for i in range(len(patches)):
ref_patch = np.load(patch_path + '/pad0_{}.npy'.format(i))
self.assert_img_equal(patches[i], ref_patch)
def test_pad_img(self):
def test_impad(self):
img = np.random.rand(10, 10, 3).astype(np.float32)
padded_img = mmcv.pad_img(img, (15, 12), 0)
padded_img = mmcv.impad(img, (15, 12), 0)
assert_array_equal(img, padded_img[:10, :10, :])
assert_array_equal(
np.zeros((5, 12, 3), dtype='float32'), padded_img[10:, :, :])
assert_array_equal(
np.zeros((15, 2, 3), dtype='float32'), padded_img[:, 10:, :])
img = np.random.randint(256, size=(10, 10, 3)).astype('uint8')
padded_img = mmcv.pad_img(img, (15, 12, 3), [100, 110, 120])
padded_img = mmcv.impad(img, (15, 12, 3), [100, 110, 120])
assert_array_equal(img, padded_img[:10, :10, :])
assert_array_equal(
np.array([100, 110, 120], dtype='uint8') * np.ones(
......@@ -226,27 +238,31 @@ class TestImage(object):
assert_array_equal(
np.array([100, 110, 120], dtype='uint8') * np.ones(
(15, 2, 3), dtype='uint8'), padded_img[:, 10:, :])
with pytest.raises(AssertionError):
mmcv.pad_img(img, (15, ), 0)
mmcv.impad(img, (15, ), 0)
with pytest.raises(AssertionError):
mmcv.pad_img(img, (5, 5), 0)
mmcv.impad(img, (5, 5), 0)
with pytest.raises(AssertionError):
mmcv.pad_img(img, (5, 5), [0, 1])
mmcv.impad(img, (5, 5), [0, 1])
def test_rotate_img(self):
def test_imrotate(self):
img = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).astype(np.uint8)
assert_array_equal(mmcv.rotate_img(img, 0), img)
assert_array_equal(mmcv.imrotate(img, 0), img)
img_r = np.array([[7, 4, 1], [8, 5, 2], [9, 6, 3]])
assert_array_equal(mmcv.rotate_img(img, 90), img_r)
assert_array_equal(mmcv.imrotate(img, 90), img_r)
img_r = np.array([[3, 6, 9], [2, 5, 8], [1, 4, 7]])
assert_array_equal(mmcv.rotate_img(img, -90), img_r)
assert_array_equal(mmcv.imrotate(img, -90), img_r)
img = np.array([[1, 2, 3, 4], [5, 6, 7, 8]]).astype(np.uint8)
img_r = np.array([[0, 6, 2, 0], [0, 7, 3, 0]])
assert_array_equal(mmcv.rotate_img(img, 90), img_r)
assert_array_equal(mmcv.imrotate(img, 90), img_r)
img_r = np.array([[1, 0, 0, 0], [2, 0, 0, 0]])
assert_array_equal(mmcv.rotate_img(img, 90, center=(0, 0)), img_r)
assert_array_equal(mmcv.imrotate(img, 90, center=(0, 0)), img_r)
img_r = np.array([[255, 6, 2, 255], [255, 7, 3, 255]])
assert_array_equal(mmcv.rotate_img(img, 90, border_value=255), img_r)
assert_array_equal(mmcv.imrotate(img, 90, border_value=255), img_r)
img_r = np.array([[5, 1], [6, 2], [7, 3], [8, 4]])
assert_array_equal(mmcv.rotate_img(img, 90, auto_bound=True), img_r)
assert_array_equal(mmcv.imrotate(img, 90, auto_bound=True), img_r)
with pytest.raises(ValueError):
mmcv.imrotate(img, 90, center=(0, 0), auto_bound=True)
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