1# Copyright 2016 The TensorFlow Authors. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# ============================================================================== 15"""Tests for image preprocessing utils.""" 16 17from __future__ import absolute_import 18from __future__ import division 19from __future__ import print_function 20 21import os 22import shutil 23 24import numpy as np 25 26from tensorflow.python.keras._impl import keras 27from tensorflow.python.platform import test 28 29try: 30 import PIL # pylint:disable=g-import-not-at-top 31except ImportError: 32 PIL = None 33 34 35def _generate_test_images(): 36 img_w = img_h = 20 37 rgb_images = [] 38 gray_images = [] 39 for _ in range(8): 40 bias = np.random.rand(img_w, img_h, 1) * 64 41 variance = np.random.rand(img_w, img_h, 1) * (255 - 64) 42 imarray = np.random.rand(img_w, img_h, 3) * variance + bias 43 im = keras.preprocessing.image.array_to_img(imarray, scale=False) 44 rgb_images.append(im) 45 46 imarray = np.random.rand(img_w, img_h, 1) * variance + bias 47 im = keras.preprocessing.image.array_to_img(imarray, scale=False) 48 gray_images.append(im) 49 50 return [rgb_images, gray_images] 51 52 53class TestImage(test.TestCase): 54 55 def test_image_data_generator(self): 56 if PIL is None: 57 return # Skip test if PIL is not available. 58 59 for test_images in _generate_test_images(): 60 img_list = [] 61 for im in test_images: 62 img_list.append(keras.preprocessing.image.img_to_array(im)[None, ...]) 63 64 images = np.vstack(img_list) 65 generator = keras.preprocessing.image.ImageDataGenerator( 66 featurewise_center=True, 67 samplewise_center=True, 68 featurewise_std_normalization=True, 69 samplewise_std_normalization=True, 70 zca_whitening=True, 71 rotation_range=90., 72 width_shift_range=0.1, 73 height_shift_range=0.1, 74 shear_range=0.5, 75 zoom_range=0.2, 76 channel_shift_range=0., 77 fill_mode='nearest', 78 cval=0.5, 79 horizontal_flip=True, 80 vertical_flip=True) 81 # Basic test before fit 82 x = np.random.random((32, 10, 10, 3)) 83 generator.flow(x) 84 85 # Fit 86 generator.fit(images, augment=True) 87 88 for x, _ in generator.flow( 89 images, 90 np.arange(images.shape[0]), 91 shuffle=True): 92 self.assertEqual(x.shape[1:], images.shape[1:]) 93 break 94 95 def test_image_data_generator_invalid_data(self): 96 generator = keras.preprocessing.image.ImageDataGenerator( 97 featurewise_center=True, 98 samplewise_center=True, 99 featurewise_std_normalization=True, 100 samplewise_std_normalization=True, 101 zca_whitening=True, 102 data_format='channels_last') 103 104 # Test fit with invalid data 105 with self.assertRaises(ValueError): 106 x = np.random.random((3, 10, 10)) 107 generator.fit(x) 108 # Test flow with invalid data 109 with self.assertRaises(ValueError): 110 generator.flow(np.arange(5)) 111 # Invalid number of channels: will work but raise a warning 112 x = np.random.random((32, 10, 10, 5)) 113 generator.flow(x) 114 115 with self.assertRaises(ValueError): 116 generator = keras.preprocessing.image.ImageDataGenerator( 117 data_format='unknown') 118 119 generator = keras.preprocessing.image.ImageDataGenerator( 120 zoom_range=(2, 2)) 121 with self.assertRaises(ValueError): 122 generator = keras.preprocessing.image.ImageDataGenerator( 123 zoom_range=(2, 2, 2)) 124 125 def test_image_data_generator_fit(self): 126 generator = keras.preprocessing.image.ImageDataGenerator( 127 featurewise_center=True, 128 samplewise_center=True, 129 featurewise_std_normalization=True, 130 samplewise_std_normalization=True, 131 zca_whitening=True, 132 data_format='channels_last') 133 # Test grayscale 134 x = np.random.random((32, 10, 10, 1)) 135 generator.fit(x) 136 # Test RBG 137 x = np.random.random((32, 10, 10, 3)) 138 generator.fit(x) 139 generator = keras.preprocessing.image.ImageDataGenerator( 140 featurewise_center=True, 141 samplewise_center=True, 142 featurewise_std_normalization=True, 143 samplewise_std_normalization=True, 144 zca_whitening=True, 145 data_format='channels_first') 146 # Test grayscale 147 x = np.random.random((32, 1, 10, 10)) 148 generator.fit(x) 149 # Test RBG 150 x = np.random.random((32, 3, 10, 10)) 151 generator.fit(x) 152 153 def test_directory_iterator(self): 154 if PIL is None: 155 return # Skip test if PIL is not available. 156 157 num_classes = 2 158 159 temp_dir = self.get_temp_dir() 160 self.addCleanup(shutil.rmtree, temp_dir) 161 162 # create folders and subfolders 163 paths = [] 164 for cl in range(num_classes): 165 class_directory = 'class-{}'.format(cl) 166 classpaths = [ 167 class_directory, os.path.join(class_directory, 'subfolder-1'), 168 os.path.join(class_directory, 'subfolder-2'), os.path.join( 169 class_directory, 'subfolder-1', 'sub-subfolder') 170 ] 171 for path in classpaths: 172 os.mkdir(os.path.join(temp_dir, path)) 173 paths.append(classpaths) 174 175 # save the images in the paths 176 count = 0 177 filenames = [] 178 for test_images in _generate_test_images(): 179 for im in test_images: 180 # rotate image class 181 im_class = count % num_classes 182 # rotate subfolders 183 classpaths = paths[im_class] 184 filename = os.path.join(classpaths[count % len(classpaths)], 185 'image-{}.jpg'.format(count)) 186 filenames.append(filename) 187 im.save(os.path.join(temp_dir, filename)) 188 count += 1 189 190 # Test image loading util 191 fname = os.path.join(temp_dir, filenames[0]) 192 _ = keras.preprocessing.image.load_img(fname) 193 _ = keras.preprocessing.image.load_img(fname, grayscale=True) 194 _ = keras.preprocessing.image.load_img(fname, target_size=(10, 10)) 195 _ = keras.preprocessing.image.load_img(fname, target_size=(10, 10), 196 interpolation='bilinear') 197 198 # create iterator 199 generator = keras.preprocessing.image.ImageDataGenerator() 200 dir_iterator = generator.flow_from_directory(temp_dir) 201 202 # check number of classes and images 203 self.assertEqual(len(dir_iterator.class_indices), num_classes) 204 self.assertEqual(len(dir_iterator.classes), count) 205 self.assertEqual(sorted(dir_iterator.filenames), sorted(filenames)) 206 _ = dir_iterator.next() 207 208 def test_img_utils(self): 209 if PIL is None: 210 return # Skip test if PIL is not available. 211 212 height, width = 10, 8 213 214 # Test channels_first data format 215 x = np.random.random((3, height, width)) 216 img = keras.preprocessing.image.array_to_img( 217 x, data_format='channels_first') 218 self.assertEqual(img.size, (width, height)) 219 x = keras.preprocessing.image.img_to_array( 220 img, data_format='channels_first') 221 self.assertEqual(x.shape, (3, height, width)) 222 # Test 2D 223 x = np.random.random((1, height, width)) 224 img = keras.preprocessing.image.array_to_img( 225 x, data_format='channels_first') 226 self.assertEqual(img.size, (width, height)) 227 x = keras.preprocessing.image.img_to_array( 228 img, data_format='channels_first') 229 self.assertEqual(x.shape, (1, height, width)) 230 231 # Test channels_last data format 232 x = np.random.random((height, width, 3)) 233 img = keras.preprocessing.image.array_to_img(x, data_format='channels_last') 234 self.assertEqual(img.size, (width, height)) 235 x = keras.preprocessing.image.img_to_array(img, data_format='channels_last') 236 self.assertEqual(x.shape, (height, width, 3)) 237 # Test 2D 238 x = np.random.random((height, width, 1)) 239 img = keras.preprocessing.image.array_to_img(x, data_format='channels_last') 240 self.assertEqual(img.size, (width, height)) 241 x = keras.preprocessing.image.img_to_array(img, data_format='channels_last') 242 self.assertEqual(x.shape, (height, width, 1)) 243 244 def test_img_transforms(self): 245 x = np.random.random((3, 200, 200)) 246 _ = keras.preprocessing.image.random_rotation(x, 20) 247 _ = keras.preprocessing.image.random_shift(x, 0.2, 0.2) 248 _ = keras.preprocessing.image.random_shear(x, 2.) 249 _ = keras.preprocessing.image.random_zoom(x, (0.5, 0.5)) 250 with self.assertRaises(ValueError): 251 keras.preprocessing.image.random_zoom(x, (0, 0, 0)) 252 _ = keras.preprocessing.image.random_channel_shift(x, 2.) 253 254 255if __name__ == '__main__': 256 test.main() 257