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

add some methods

parent 507e67e4
from .colorspace import * from .colorspace import *
from .geometry import * from .geometry import *
from .normalize import *
from .resize import * from .resize import *
from __future__ import division
import cv2 import cv2
import numpy as np 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, def imrotate(img,
...@@ -13,7 +32,7 @@ def imrotate(img, ...@@ -13,7 +32,7 @@ def imrotate(img,
"""Rotate an image. """Rotate an image.
Args: Args:
img (ndarray or str): Image to be rotated. img (ndarray): Image to be rotated.
angle (float): Rotation angle in degrees, positive values mean angle (float): Rotation angle in degrees, positive values mean
clockwise rotation. clockwise rotation.
center (tuple): Center of the rotation in the source image, by default 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): ...@@ -146,13 +165,13 @@ def imcrop(img, bboxes, scale_ratio=1.0, pad_fill=None):
return patches return patches
def impad(img, shape, pad_val): def impad(img, shape, pad_val=0):
"""Pad an image to a certain shape. """Pad an image to a certain shape.
Args: Args:
img (ndarray): Image to be padded. img (ndarray): Image to be padded.
shape (tuple): Expected padding shape. 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: Returns:
ndarray: The padded image. ndarray: The padded image.
...@@ -168,3 +187,19 @@ def impad(img, shape, pad_val): ...@@ -168,3 +187,19 @@ def impad(img, shape, pad_val):
pad[...] = pad_val pad[...] = pad_val
pad[:img.shape[0], :img.shape[1], ...] = img pad[:img.shape[0], :img.shape[1], ...] = img
return pad 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): ...@@ -145,3 +145,17 @@ class PaviLoggerHook(LoggerHook):
log_outs.pop('time', None) log_outs.pop('time', None)
log_outs.pop('data_time', None) log_outs.pop('data_time', None)
self.pavi.log(runner.mode, runner.iter, log_outs) 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 functools
import logging import logging
import sys
import time import time
from getpass import getuser from getpass import getuser
from socket import gethostname from socket import gethostname
...@@ -45,7 +46,7 @@ def add_file_handler(logger, filename=None, mode='w', level=logging.INFO): ...@@ -45,7 +46,7 @@ def add_file_handler(logger, filename=None, mode='w', level=logging.INFO):
return logger 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. """Initialize an object from dict.
The dict must contain the key "type", which indicates the object type, it 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): ...@@ -60,14 +61,17 @@ def obj_from_dict(info, module, default_args=None):
object. object.
Returns: Returns:
any type: Object built from the dict.
""" """
assert isinstance(info, dict) and 'type' in info assert isinstance(info, dict) and 'type' in info
assert isinstance(default_args, dict) or default_args is None assert isinstance(default_args, dict) or default_args is None
args = info.copy() args = info.copy()
obj_type = args.pop('type') obj_type = args.pop('type')
if mmcv.is_str(obj_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): elif not isinstance(obj_type, type):
raise TypeError('type must be a str or valid type, but got {}'.format( raise TypeError('type must be a str or valid type, but got {}'.format(
type(obj_type))) type(obj_type)))
......
...@@ -178,6 +178,36 @@ class TestImage(object): ...@@ -178,6 +178,36 @@ class TestImage(object):
resized_img, scale = mmcv.limit_size(img, 200, True) resized_img, scale = mmcv.limit_size(img, 200, True)
assert resized_img.shape == (150, 200, 3) and scale == 0.5 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): def test_imcrop(self):
# yapf: disable # yapf: disable
bboxes = np.array([[100, 100, 199, 199], # center bboxes = np.array([[100, 100, 199, 199], # center
...@@ -246,6 +276,17 @@ class TestImage(object): ...@@ -246,6 +276,17 @@ class TestImage(object):
with pytest.raises(AssertionError): with pytest.raises(AssertionError):
mmcv.impad(img, (5, 5), [0, 1]) 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): def test_imrotate(self):
img = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).astype(np.uint8) img = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).astype(np.uint8)
assert_array_equal(mmcv.imrotate(img, 0), img) 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