added pillow backend in loading ()

* added pillow backend in loading

* reformat

* remove auto fill for RGBA

* change according to comments

* change according to comments

* reformat
pull/351/head
Wang Xinjiang 2020-06-17 10:25:48 +08:00 committed by GitHub
parent 3f4c9fd0c8
commit 630b747cb1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 161 additions and 38 deletions

View File

@ -1,35 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end
popd
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end
popd

View File

@ -1,4 +1,5 @@
# Copyright (c) Open-MMLab. All rights reserved.
import io
import os.path as osp
from pathlib import Path
@ -13,8 +14,13 @@ try:
except ImportError:
TJCS_RGB = TJPF_GRAY = TJPF_BGR = TurboJPEG = None
try:
from PIL import Image
except ImportError:
Image = None
jpeg = None
supported_backends = ['cv2', 'turbojpeg']
supported_backends = ['cv2', 'turbojpeg', 'pillow']
imread_flags = {
'color': IMREAD_COLOR,
@ -42,6 +48,9 @@ def use_backend(backend):
global jpeg
if jpeg is None:
jpeg = TurboJPEG()
elif imread_backend == 'pillow':
if Image is None:
raise ImportError('`Pillow` is not installed')
def _jpegflag(flag='color', channel_order='bgr'):
@ -60,6 +69,57 @@ def _jpegflag(flag='color', channel_order='bgr'):
raise ValueError('flag must be "color" or "grayscale"')
def _pillow2array(img, flag='color', channel_order='bgr'):
"""Convert a pillow image to numpy array
Args:
img (:obj:`PIL.Image.Image`): The image loaded using PIL
flag (str): Flags specifying the color type of a loaded image,
candidates are 'color', 'grayscale' and 'unchanged'.
Default to 'color'.
channel_order (str): The channel order of the output image array,
candidates are 'bgr' and 'rgb'. Default to 'bgr'.
Returns:
np.ndarray: The converted numpy array
"""
channel_order = channel_order.lower()
if channel_order not in ['rgb', 'bgr']:
raise ValueError('channel order must be either "rgb" or "bgr"')
if flag == 'unchanged':
array = np.array(img)
if array.ndim >= 3 and array.shape[2] >= 3: # color image
array[:, :, :3] = array[:, :, (2, 1, 0)] # RGB to BGR
else:
# If the image mode is not 'RGB', convert it to 'RGB' first.
if img.mode != 'RGB':
if img.mode != 'LA':
# Most formats except 'LA' can be directly converted to RGB
img = img.convert('RGB')
else:
# When the mode is 'LA', the default conversion will fill in
# the canvas with black, which sometimes shadows black objects
# in the foreground.
#
# Therefore, a random color (124, 117, 104) is used for canvas
img_rgba = img.convert('RGBA')
img = Image.new('RGB', img_rgba.size, (124, 117, 104))
img.paste(img_rgba, mask=img_rgba.split()[3]) # 3 is alpha
if flag == 'color':
array = np.array(img)
if channel_order != 'rgb':
array = array[:, :, ::-1] # RGB to BGR
elif flag == 'grayscale':
img = img.convert('L')
array = np.array(img)
else:
raise ValueError(
'flag must be "color", "grayscale" or "unchanged", '
f'but got {flag}')
return array
def imread(img_or_path, flag='color', channel_order='bgr'):
"""Read an image.
@ -90,6 +150,10 @@ def imread(img_or_path, flag='color', channel_order='bgr'):
if img.shape[-1] == 1:
img = img[:, :, 0]
return img
elif imread_backend == 'pillow':
img = Image.open(img_or_path)
img = _pillow2array(img, flag, channel_order)
return img
else:
flag = imread_flags[flag] if is_str(flag) else flag
img = cv2.imread(img_or_path, flag)
@ -116,6 +180,11 @@ def imfrombytes(content, flag='color', channel_order='bgr'):
if img.shape[-1] == 1:
img = img[:, :, 0]
return img
elif imread_backend == 'pillow':
buff = io.BytesIO(content)
img = Image.open(buff)
img = _pillow2array(img, flag, channel_order)
return img
else:
img_np = np.frombuffer(content, np.uint8)
flag = imread_flags[flag] if is_str(flag) else flag

View File

@ -32,4 +32,4 @@
"regnetx_6.4gf": "https://open-mmlab.s3.ap-northeast-2.amazonaws.com/pretrain/third_party/regnetx_6.4gf-006af45d.pth",
"regnetx_8.0gf": "https://open-mmlab.s3.ap-northeast-2.amazonaws.com/pretrain/third_party/regnetx_8.0gf-3c68abe7.pth",
"regnetx_12gf": "https://open-mmlab.s3.ap-northeast-2.amazonaws.com/pretrain/third_party/regnetx_12gf-4c2a3350.pth"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

View File

@ -8,7 +8,7 @@ from unittest.mock import patch
import cv2
import numpy as np
import pytest
from numpy.testing import assert_array_equal
from numpy.testing import assert_allclose, assert_array_equal
import mmcv
@ -65,6 +65,51 @@ class TestIO:
with pytest.raises(TypeError):
mmcv.imread(1)
# backend pillow
mmcv.use_backend('pillow')
self.gray_alpha_img_path = osp.join(self.data_dir, 'gray_alpha.png')
self.palette_img_path = osp.join(self.data_dir, 'palette.gif')
img_pil_grayscale1 = mmcv.imread(self.img_path, 'grayscale')
assert img_pil_grayscale1.shape == (300, 400)
img_pil_gray_alpha = mmcv.imread(self.gray_alpha_img_path, 'grayscale')
assert img_pil_gray_alpha.shape == (400, 500)
mean = img_pil_gray_alpha[300:, 400:].mean()
assert_allclose(img_pil_gray_alpha[300:, 400:] - mean, 0)
img_pil_gray_alpha = mmcv.imread(self.gray_alpha_img_path)
mean = img_pil_gray_alpha[300:, 400:].mean(axis=(0, 1))
assert_allclose(img_pil_gray_alpha[300:, 400:] - mean, 0)
assert img_pil_gray_alpha.shape == (400, 500, 3)
img_pil_gray_alpha = mmcv.imread(self.gray_alpha_img_path, 'unchanged')
assert img_pil_gray_alpha.shape == (400, 500, 2)
img_pil_palette = mmcv.imread(self.palette_img_path, 'grayscale')
assert img_pil_palette.shape == (300, 400)
img_pil_palette = mmcv.imread(self.palette_img_path)
assert img_pil_palette.shape == (300, 400, 3)
img_pil_palette = mmcv.imread(self.palette_img_path, 'unchanged')
assert img_pil_palette.shape == (300, 400)
img_pil_grayscale2 = mmcv.imread(self.gray_img_path)
assert img_pil_grayscale2.shape == (300, 400, 3)
img_pil_unchanged = mmcv.imread(self.gray_img_path, 'unchanged')
assert img_pil_unchanged.shape == (300, 400)
img_pil_unchanged = mmcv.imread(img_pil_unchanged)
assert_array_equal(img_pil_unchanged, mmcv.imread(img_pil_unchanged))
img_pil_color_bgr = mmcv.imread(self.img_path_obj)
assert img_pil_color_bgr.shape == (300, 400, 3)
img_pil_color_rgb = mmcv.imread(self.img_path_obj, channel_order='rgb')
assert img_pil_color_rgb.shape == (300, 400, 3)
assert (img_pil_color_rgb == img_cv2_color_rgb).sum() / float(
img_cv2_color_rgb.size) > 0.5
assert_array_equal(img_pil_color_rgb[:, :, ::-1], img_pil_color_bgr)
img_pil_grayscale1 = mmcv.imread(self.img_path_obj, 'grayscale')
assert img_pil_grayscale1.shape == (300, 400)
img_pil_grayscale2 = mmcv.imread(self.gray_img_path_obj)
assert img_pil_grayscale2.shape == (300, 400, 3)
img_pil_unchanged = mmcv.imread(self.gray_img_path_obj, 'unchanged')
assert img_pil_unchanged.shape == (300, 400)
with pytest.raises(TypeError):
mmcv.imread(1)
# backend turbojpeg
mmcv.use_backend('turbojpeg')
@ -137,6 +182,15 @@ class TestIO:
gray_img_dim3_cv2 = mmcv.imfrombytes(img_bytes, flag='grayscale')
assert gray_img_dim3_cv2.shape == (300, 400)
# backend pillow, channel order: bgr
mmcv.use_backend('pillow')
with open(self.img_path, 'rb') as f:
img_bytes = f.read()
img_pillow = mmcv.imfrombytes(img_bytes)
assert img_pillow.shape == (300, 400, 3)
# Pillow and opencv decoding may not be the same
assert (img_cv2 == img_pillow).sum() / float(img_cv2.size) > 0.5
# backend turbojpeg, channel order: bgr
mmcv.use_backend('turbojpeg')
with open(self.img_path, 'rb') as f: