10000 Added pilutils tests taken from scipy · scikit-learn/scikit-learn@05a98cc · GitHub
[go: up one dir, main page]

Skip to content

Commit 05a98cc

Browse files
author
Jonathan Tammo Siebert
committed
Added pilutils tests taken from scipy
1 parent f5475d2 commit 05a98cc

File tree

8 files changed

+206
-0
lines changed

8 files changed

+206
-0
lines changed
Loading
208 Bytes
Loading
Loading
2.07 KB
Loading
449 Bytes
Loading
Loading
Loading
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
"""
2+
Tests for the utility functions wrapping PIL functions
3+
4+
This is a local version of the tests for utility functions from scipy that
5+
are wrapping PIL functionality. These functions are deprecated in scipy 1.0.0
6+
and will be removed in scipy 1.2.0.
7+
8+
Copyright (c) 2001, 2002 Enthought, Inc.
9+
All rights reserved.
10+
11+
Copyright (c) 2003-2017 SciPy Developers.
12+
All rights reserved.
13+
14+
Redistribution and use in source and binary forms, with or without
15+
modification, are permitted provided that the following conditions are met:
16+
17+
a. Redistributions of source code must retain the above copyright notice,
18+
this list of conditions and the following disclaimer.
19+
b. Redistributions in binary form must reproduce the above copyright
20+
notice, this list of conditions and the following disclaimer in the
21+
documentation and/or other materials provided with the distribution.
22+
c. Neither the name of Enthought nor the names of the SciPy Developers
23+
may be used to endorse or promote products derived from this software
24+
without specific prior written permission.
25+
26+
27+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
31+
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
32+
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37+
THE POSSIBILITY OF SUCH DAMAGE.
38+
"""
39+
40+
from __future__ import division, print_function, absolute_import
41+
42+
import tempfile
43+
import glob
44+
import shutil
45+
import os.path
46+
import numpy as np
47+
48+
import pytest
49+
from numpy.testing import (assert_equal, assert_array_equal,
50+
assert_, assert_allclose)
51+
from numpy.ma.testutils import assert_mask_equal
52+
53+
from sklearn.externals.pilutil import (_imread, _imsave, _imresize,
54+
_bytescale, _fromimage)
55+
56+
_have_image = True
57+
try:
58+
try:
59+
from PIL import Image
60+
except ImportError:
61+
import Image
62+
except ImportError:
63+
_have_image = False
64+
65+
# Function / method decorator for skipping PIL tests on import failure
66+
_pilskip = pytest.mark.skipif(
67+
not _have_image, reason='Need to import PIL for this test')
68+
69+
datapath = os.path.dirname(__file__)
70+
71+
72+
class TestPILUtil(object):
73+
@_pilskip
74+
def test_imresize(self):
75+
im = np.random.random((10, 20))
76+
for T in np.sctypes['float'] + [float]:
77+
# 1.1 rounds to below 1.1 for float16, 1.101 works
78+
im1 = _imresize(im, T(1.101))
79+
assert_equal(im1.shape, (11, 22))
80+
81+
def test_bytescale(self):
82+
x = np.array([0, 1, 2], np.uint8)
83+
y = np.array([0, 1, 2])
84+
assert_equal(_bytescale(x), x)
85+
assert_equal(_bytescale(y), [0, 128, 255])
86+
87+
def test_bytescale_mask(self):
88+
a = np.ma.MaskedArray(data=[1, 2, 3], mask=[False, False, True])
89+
actual = _bytescale(a)
90+
expected = [0, 255, 3]
91+
assert_equal(expected, actual)
92+
assert_mask_equal(a.mask, actual.mask)
93+
assert_(isinstance(actual, np.ma.MaskedArray))
94+
95+
@_pilskip
96+
def test_imsave(self):
97+
picdir = os.path.join(datapath, "data")
98+
for png in glob.iglob(picdir + "/*.png"):
99+
img = _imread(png)
100+
tmpdir = tempfile.mkdtemp()
101+
try:
102+
fn = os.path.join(tmpdir, 'test.png')
103+
_imsave(fn, img)
104+
105+
data = _imread(fn)
106+
assert_allclose(data, img)
107+
assert_equal(data.shape, img.shape)
108+
finally:
109+
shutil.rmtree(tmpdir)
110+
111+
112+
@_pilskip
113+
def check_fromimage(filename, irange, shape):
114+
fp = open(filename, "rb")
115+
img = _fromimage(Image.open(fp))
116+
fp.close()
117+
imin, imax = irange
118+
assert_equal(img.min(), imin)
119+
assert_equal(img.max(), imax)
120+
assert_equal(img.shape, shape)
121+
122+
123+
@_pilskip
124+
def test_fromimage():
125+
# Test generator for parametric tests
126+
# Tuples in the list are (filename, (datamin, datamax), shape).
127+
files = [('icon.png', (0, 255), (48, 48, 4)),
128+
('icon_mono.png', (0, 255), (48, 48, 4)),
129+
('icon_mono_flat.png', (0, 255), (48, 48, 3))]
130+
for fn, irange, shape in files:
131+
check_fromimage(os.path.join(datapath, 'data', fn), irange, shape)
132+
133+
134+
@_pilskip
135+
def test_imread_indexed_png():
136+
# The file `foo3x5x4indexed.png` was created with this array
137+
# (3x5 is (height)x(width)):
138+
data = np.array([[[127, 0, 255, 255],
139+
[127, 0, 255, 255],
140+
[127, 0, 255, 255],
141+
[127, 0, 255, 255],
142+
[127, 0, 255, 255]],
143+
[[192, 192, 255, 0],
144+
[192, 192, 255, 0],
145+
[0, 0, 255, 0],
146+
[0, 0, 255, 0],
147+
[0, 0, 255, 0]],
148+
[[0, 31, 255, 255],
149+
[0, 31, 255, 255],
150+
[0, 31, 255, 255],
151+
[0, 31, 255, 255],
152+
[0, 31, 255, 255]]], dtype=np.uint8)
153+
154+
filename = os.path.join(datapath, 'data', 'foo3x5x4indexed.png')
155+
with open(filename, 'rb') as f:
156+
im = _imread(f)
157+
assert_array_equal(im, data)
158+
159+
160+
@_pilskip
161+
def test_imread_1bit():
162+
# box1.png is a 48x48 grayscale image with bit depth 1.
163+
# The border pixels are 1 and the rest are 0.
164+
filename = os.path.join(datapath, 'data', 'box1.png')
165+
with open(filename, 'rb') as f:
166+
im = _imread(f)
167+
assert_equal(im.dtype, np.uint8)
168+
expected = np.zeros((48, 48), dtype=np.uint8)
169+
# When scaled up from 1 bit to 8 bits, 1 becomes 255.
170+
expected[:, 0] = 255
171+
expected[:, -1] = 255
172+
expected[0, :] = 255
173+
expected[-1, :] = 255
174+
assert_equal(im, expected)
175+
176+
177+
@_pilskip
178+
def test_imread_2bit():
179+
# blocks2bit.png is a 12x12 grayscale image with bit depth 2.
180+
# The pattern is 4 square subblocks of size 6x6. Upper left
181+
# is all 0, upper right is all 1, lower left is all 2, lower
182+
# right is all 3.
183+
# When scaled up to 8 bits, the values become [0, 85, 170, 255].
184+
filename = os.path.join(datapath, 'data', 'blocks2bit.png')
185+
with open(filename, 'rb') as f:
186+
im = _imread(f)
187+
assert_equal(im.dtype, np.uint8)
188+
expected = np.zeros((12, 12), dtype=np.uint8)
189+
expected[:6, 6:] = 85
190+
expected[6:, :6] = 170
191+
expected[6:, 6:] = 255
192+
assert_equal(im, expected)
193+
194+
195+
@_pilskip
196+
def test_imread_4bit():
197+
# pattern4bit.png is a 12(h) x 31(w) grayscale image with bit depth 4.
198+
# The value in row j and column i is maximum(j, i) % 16.
199+
# When scaled up to 8 bits, the values become [0, 17, 34, ..., 255].
200+
filename = os.path.join(datapath, 'data', 'pattern4bit.png')
201+
with open(filename, 'rb') as f:
202+
im = _imread(f)
203+
assert_equal(im.dtype, np.uint8)
204+
j, i = np.meshgrid(np.arange(12), np.arange(31), indexing='ij')
205+
expected = 17 * (np.maximum(j, i) % 16).astype(np.uint8)
206+
assert_equal(im, expected)

0 commit comments

Comments
 (0)
0