Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
MMCV
Commits
f872672f
Commit
f872672f
authored
Aug 27, 2018
by
Kai Chen
Browse files
renaming and reorganizing for subpackage
parent
eadd1e0f
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
465 additions
and
76 deletions
+465
-76
mmcv/image/__init__.py
mmcv/image/__init__.py
+1
-1
mmcv/image/io.py
mmcv/image/io.py
+7
-5
mmcv/image/transforms/__init__.py
mmcv/image/transforms/__init__.py
+3
-0
mmcv/image/transforms/colorspace.py
mmcv/image/transforms/colorspace.py
+63
-0
mmcv/image/transforms/geometry.py
mmcv/image/transforms/geometry.py
+170
-0
mmcv/image/transforms/resize.py
mmcv/image/transforms/resize.py
+135
-0
mmcv/video/optflow.py
mmcv/video/optflow.py
+5
-5
mmcv/visualization/image.py
mmcv/visualization/image.py
+4
-4
tests/test_image.py
tests/test_image.py
+77
-61
No files found.
mmcv/image/__init__.py
View file @
f872672f
from
.io
import
*
from
.
processing
import
*
from
.
transforms
import
*
mmcv/image/io.py
View file @
f872672f
...
...
@@ -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
im
g_
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:`
im
read`.
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
im
write
(
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,
...
...
mmcv/image/transforms/__init__.py
0 → 100644
View file @
f872672f
from
.colorspace
import
*
from
.geometry
import
*
from
.resize
import
*
mmcv/image/transforms/colorspace.py
0 → 100644
View file @
f872672f
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'
)
mmcv/image/
processing
.py
→
mmcv/image/
transforms/geometry
.py
View file @
f872672f
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 resiz
ed
_
im
g
.
ndarray: The rotat
ed
im
age
.
"""
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
im
crop
(
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
im
pad
(
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
mmcv/image/transforms/resize.py
0 → 100644
View file @
f872672f
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
mmcv/video/optflow.py
View file @
f872672f
import
numpy
as
np
from
mmcv.image
import
read
_img
,
write
_img
from
mmcv.image
import
im
read
,
im
write
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
=
im
read
(
dx_filename
,
flag
=
'unchanged'
)
dy
=
im
read
(
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
)
im
write
(
dx
,
dx_filename
)
im
write
(
dy
,
dy_filename
)
def
quantize_flow
(
flow
,
max_val
=
0.02
,
norm
=
True
):
...
...
mmcv/visualization/image.py
View file @
f872672f
import
cv2
import
numpy
as
np
from
mmcv.image
import
read
_img
,
write
_img
from
mmcv.image
import
im
read
,
im
write
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
,
im
read
(
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
=
im
read
(
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
)
im
write
(
img
,
out_file
)
tests/test_image.py
View file @
f872672f
...
...
@@ -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_
im
read
(
self
):
img
=
mmcv
.
im
read
(
self
.
img_path
)
assert
img
.
shape
==
(
300
,
400
,
3
)
img
=
mmcv
.
read
_img
(
self
.
img_path
,
'grayscale'
)
img
=
mmcv
.
im
read
(
self
.
img_path
,
'grayscale'
)
assert
img
.
shape
==
(
300
,
400
)
img
=
mmcv
.
read
_img
(
self
.
gray_img_path
)
img
=
mmcv
.
im
read
(
self
.
gray_img_path
)
assert
img
.
shape
==
(
300
,
400
,
3
)
img
=
mmcv
.
read
_img
(
self
.
gray_img_path
,
'unchanged'
)
img
=
mmcv
.
im
read
(
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
.
im
read
(
img
)
assert_array_equal
(
img
,
mmcv
.
im
read
(
img
))
with
pytest
.
raises
(
TypeError
):
mmcv
.
read
_img
(
1
)
mmcv
.
im
read
(
1
)
def
test_im
g_
from
_
bytes
(
self
):
def
test_imfrombytes
(
self
):
with
open
(
self
.
img_path
,
'rb'
)
as
f
:
img_bytes
=
f
.
read
()
img
=
mmcv
.
im
g_
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_
im
write
(
self
):
img
=
mmcv
.
im
read
(
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
.
im
write
(
img
,
out_file
)
rewrite_img
=
mmcv
.
im
read
(
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_
im
resize
(
self
):
resized_img
=
mmcv
.
im
resize
(
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
.
im
resize
(
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
.
im
resize
(
self
.
img
,
(
1000
,
600
),
interpolation
=
mode
)
assert
resized_img
.
shape
==
(
600
,
1000
,
3
)
def
test_resize_like
(
self
):
def
test_
im
resize_like
(
self
):
a
=
np
.
zeros
((
100
,
200
,
3
))
resized_img
=
mmcv
.
resize_like
(
self
.
img
_path
,
a
)
resized_img
=
mmcv
.
im
resize_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
.
res
ize_by_ratio
(
self
.
img
_path
,
0.934
)
resized_img
=
mmcv
.
im
res
cale
(
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
.
res
ize_keep_ar
(
self
.
img
_path
,
1000
,
600
)
resized_img
=
mmcv
.
im
res
cale
(
self
.
img
,
(
1000
,
600
)
)
assert
resized_img
.
shape
==
(
600
,
800
,
3
)
resized_img
,
scale
=
mmcv
.
res
ize_keep_ar
(
self
.
img_path
,
1000
,
600
,
True
)
resized_img
,
scale
=
mmcv
.
im
res
cale
(
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
.
im
read
(
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
.
im
crop
(
self
.
img
,
bboxes
[
0
,
:])
patches
=
mmcv
.
im
crop
(
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
.
im
crop
(
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
.
im
crop
(
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
.
im
crop
(
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
.
im
crop
(
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_
im
pad
(
self
):
img
=
np
.
random
.
rand
(
10
,
10
,
3
).
astype
(
np
.
float32
)
padded_img
=
mmcv
.
pad
_img
(
img
,
(
15
,
12
),
0
)
padded_img
=
mmcv
.
im
pad
(
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
.
im
pad
(
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
.
im
pad
(
img
,
(
15
,
),
0
)
with
pytest
.
raises
(
AssertionError
):
mmcv
.
pad
_img
(
img
,
(
5
,
5
),
0
)
mmcv
.
im
pad
(
img
,
(
5
,
5
),
0
)
with
pytest
.
raises
(
AssertionError
):
mmcv
.
pad
_img
(
img
,
(
5
,
5
),
[
0
,
1
])
mmcv
.
im
pad
(
img
,
(
5
,
5
),
[
0
,
1
])
def
test_rotate
_img
(
self
):
def
test_
im
rotate
(
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
.
im
rotate
(
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
.
im
rotate
(
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
.
im
rotate
(
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
.
im
rotate
(
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
.
im
rotate
(
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
.
im
rotate
(
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
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment