Commit 1f767847 authored by Kai Chen's avatar Kai Chen
Browse files

add some methods

parent 507e67e4
from .colorspace import *
from .geometry import *
from .normalize import *
from .resize import *
from __future__ import division
import cv2
import numpy as np
__all__ = ['imrotate', 'imcrop', 'impad']
__all__ = ['imflip', 'imrotate', 'imcrop', 'impad', 'impad_to_multiple']
def imflip(img, direction='horizontal'):
"""Flip an image horizontally or vertically.
Args:
img (ndarray): Image to be flipped.
direction (str): The flip direction, either "horizontal" or "vertical".
Returns:
ndarray: The flipped image.
"""
assert direction in ['horizontal', 'vertical']
if direction == 'horizontal':
return np.flip(img, axis=1)
else:
return np.flip(img, axis=0)
def imrotate(img,
......@@ -13,7 +32,7 @@ def imrotate(img,
"""Rotate an image.
Args:
img (ndarray or str): Image to be rotated.
img (ndarray): 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
......@@ -146,13 +165,13 @@ def imcrop(img, bboxes, scale_ratio=1.0, pad_fill=None):
return patches
def impad(img, shape, pad_val):
def impad(img, shape, pad_val=0):
"""Pad an image to a certain shape.
Args:
img (ndarray): Image to be padded.
shape (tuple): Expected padding shape.
pad_val (number or list): Values to be filled in padding areas.
pad_val (number or sequence): Values to be filled in padding areas.
Returns:
ndarray: The padded image.
......@@ -168,3 +187,19 @@ def impad(img, shape, pad_val):
pad[...] = pad_val
pad[:img.shape[0], :img.shape[1], ...] = img
return pad
def impad_to_multiple(img, divisor, pad_val=0):
"""Pad an image to ensure each edge to be multiple to some number.
Args:
img (ndarray): Image to be padded.
divisor (int): Padded image edges will be multiple to divisor.
pad_val (number or sequence): Same as :func:`impad`.
Returns:
ndarray: The padded image.
"""
pad_h = int(np.ceil(img.shape[0] / divisor)) * divisor
pad_w = int(np.ceil(img.shape[1] / divisor)) * divisor
return impad(img, (pad_h, pad_w), pad_val)
import numpy as np
from .colorspace import bgr2rgb, rgb2bgr
__all__ = ['imnorm', 'imdenorm']
def imnorm(img, mean, std, to_rgb=True):
img = img.astype(np.float32)
if to_rgb:
img = bgr2rgb(img)
return (img - mean) / std
def imdenorm(img, mean, std, to_bgr=True):
img = (img * std) + mean
if to_bgr:
img = rgb2bgr(img)
return img
......@@ -145,3 +145,17 @@ class PaviLoggerHook(LoggerHook):
log_outs.pop('time', None)
log_outs.pop('data_time', None)
self.pavi.log(runner.mode, runner.iter, log_outs)
def pavi_hook_connect(runner, cfg_filename, cfg_text):
for hook in runner.hooks:
if isinstance(hook, PaviLoggerHook):
hook.connect(
runner.model_name,
runner.work_dir,
info={
'session_file': cfg_filename,
'session_text': cfg_text
},
logger=runner.logger)
break
import functools
import logging
import sys
import time
from getpass import getuser
from socket import gethostname
......@@ -45,7 +46,7 @@ def add_file_handler(logger, filename=None, mode='w', level=logging.INFO):
return logger
def obj_from_dict(info, module, default_args=None):
def obj_from_dict(info, parrent=None, default_args=None):
"""Initialize an object from dict.
The dict must contain the key "type", which indicates the object type, it
......@@ -60,14 +61,17 @@ def obj_from_dict(info, module, default_args=None):
object.
Returns:
any type: Object built from the dict.
"""
assert isinstance(info, dict) and 'type' in info
assert isinstance(default_args, dict) or default_args is None
args = info.copy()
obj_type = args.pop('type')
if mmcv.is_str(obj_type):
obj_type = getattr(module, obj_type)
if parrent is not None:
obj_type = getattr(parrent, obj_type)
else:
obj_type = sys.modules[obj_type]
elif not isinstance(obj_type, type):
raise TypeError('type must be a str or valid type, but got {}'.format(
type(obj_type)))
......
......@@ -178,6 +178,36 @@ class TestImage(object):
resized_img, scale = mmcv.limit_size(img, 200, True)
assert resized_img.shape == (150, 200, 3) and scale == 0.5
def test_imflip(self):
# test color image
img = np.random.rand(80, 60, 3)
h, w, c = img.shape
hf_img = mmcv.imflip(img)
assert hf_img.shape == (h, w, c)
for i in range(h):
for j in range(w):
for k in range(c):
assert hf_img[i, j, k] == img[i, w - 1 - j, k]
hf_img = mmcv.imflip(img, direction='vertical')
assert hf_img.shape == (h, w, c)
for i in range(h):
for j in range(w):
for k in range(c):
assert hf_img[i, j, k] == self.img[h - 1 - i, j, k]
# test grayscale image
img = np.random.rand(80, 60)
h, w, c = img.shape
hf_img = mmcv.imflip(img)
assert hf_img.shape == (h, w, c)
for i in range(h):
for j in range(w):
assert hf_img[i, j, k] == img[i, w - 1 - j]
hf_img = mmcv.imflip(img, direction='vertical')
assert hf_img.shape == (h, w, c)
for i in range(h):
for j in range(w):
assert hf_img[i, j, k] == self.img[h - 1 - i, j]
def test_imcrop(self):
# yapf: disable
bboxes = np.array([[100, 100, 199, 199], # center
......@@ -246,6 +276,17 @@ class TestImage(object):
with pytest.raises(AssertionError):
mmcv.impad(img, (5, 5), [0, 1])
def test_impad_to_multiple(self):
img = np.random.rand(11, 14, 3).astype(np.float32)
padded_img = mmcv.impad_to_multiple(img, 4)
assert padded_img.shape == (12, 16, 3)
img = np.random.rand(20, 12).astype(np.float32)
padded_img = mmcv.impad_to_multiple(img, 5)
assert padded_img.shape == (20, 15)
img = np.random.rand(20, 12).astype(np.float32)
padded_img = mmcv.impad_to_multiple(img, 2)
assert padded_img.shape == (20, 12)
def test_imrotate(self):
img = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).astype(np.uint8)
assert_array_equal(mmcv.imrotate(img, 0), img)
......
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