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 DecodeJpegOp.""" 16 17 from __future__ import absolute_import 18 from __future__ import division 19 from __future__ import print_function 20 21 import os 22 import time 23 24 from six.moves import xrange # pylint: disable=redefined-builtin 25 from tensorflow.python.client import session 26 from tensorflow.python.framework import ops 27 from tensorflow.python.ops import array_ops 28 from tensorflow.python.ops import control_flow_ops 29 from tensorflow.python.ops import image_ops 30 from tensorflow.python.ops import io_ops 31 from tensorflow.python.ops import variable_scope 32 from tensorflow.python.ops import variables 33 from tensorflow.python.platform import test 34 35 prefix_path = 'third_party/tensorflow/core/lib/jpeg/testdata' 36 37 38 class DecodeJpegBenchmark(test.Benchmark): 39 """Evaluate tensorflow DecodeJpegOp performance.""" 40 41 def _evalDecodeJpeg(self, 42 image_name, 43 parallelism, 44 num_iters, 45 crop_during_decode=None, 46 crop_window=None, 47 tile=None): 48 """Evaluate DecodeJpegOp for the given image. 49 50 TODO(tanmingxing): add decoding+cropping as well. 51 52 Args: 53 image_name: a string of image file name (without suffix). 54 parallelism: the number of concurrent decode_jpeg ops to be run. 55 num_iters: number of iterations for evaluation. 56 crop_during_decode: If true, use fused DecodeAndCropJpeg instead of 57 separate decode and crop ops. It is ignored if crop_window is None. 58 crop_window: if not None, crop the decoded image. Depending on 59 crop_during_decode, cropping could happen during or after decoding. 60 tile: if not None, tile the image to composite a larger fake image. 61 62 Returns: 63 The duration of the run in seconds. 64 """ 65 ops.reset_default_graph() 66 67 image_file_path = os.path.join(prefix_path, image_name) 68 69 if tile is None: 70 image_content = variable_scope.get_variable( 71 'image_%s' % image_name, 72 initializer=io_ops.read_file(image_file_path)) 73 else: 74 single_image = image_ops.decode_jpeg( 75 io_ops.read_file(image_file_path), channels=3, name='single_image') 76 # Tile the image to composite a new larger image. 77 tiled_image = array_ops.tile(single_image, tile) 78 image_content = variable_scope.get_variable( 79 'tiled_image_%s' % image_name, 80 initializer=image_ops.encode_jpeg(tiled_image)) 81 82 with session.Session() as sess: 83 sess.run(variables.global_variables_initializer()) 84 images = [] 85 for _ in xrange(parallelism): 86 if crop_window is None: 87 # No crop. 88 image = image_ops.decode_jpeg(image_content, channels=3) 89 elif crop_during_decode: 90 # combined decode and crop. 91 image = image_ops.decode_and_crop_jpeg( 92 image_content, crop_window, channels=3) 93 else: 94 # separate decode and crop. 95 image = image_ops.decode_jpeg(image_content, channels=3) 96 image = image_ops.crop_to_bounding_box( 97 image, 98 offset_height=crop_window[0], 99 offset_width=crop_window[1], 100 target_height=crop_window[2], 101 target_width=crop_window[3]) 102 103 images.append(image) 104 r = control_flow_ops.group(*images) 105 106 for _ in xrange(3): 107 # Skip warm up time. 108 sess.run(r) 109 110 start_time = time.time() 111 for _ in xrange(num_iters): 112 sess.run(r) 113 return time.time() - start_time 114 115 def benchmarkDecodeJpegSmall(self): 116 """Evaluate single DecodeImageOp for small size image.""" 117 num_iters = 10 118 crop_window = [10, 10, 50, 50] 119 for parallelism in [1, 100]: 120 duration_decode = self._evalDecodeJpeg('small.jpg', parallelism, 121 num_iters) 122 duration_decode_crop = self._evalDecodeJpeg('small.jpg', parallelism, 123 num_iters, False, crop_window) 124 duration_decode_after_crop = self._evalDecodeJpeg( 125 'small.jpg', parallelism, num_iters, True, crop_window) 126 self.report_benchmark( 127 name='decode_jpeg_small_p%d' % (parallelism), 128 iters=num_iters, 129 wall_time=duration_decode) 130 self.report_benchmark( 131 name='decode_crop_jpeg_small_p%d' % (parallelism), 132 iters=num_iters, 133 wall_time=duration_decode_crop) 134 self.report_benchmark( 135 name='decode_after_crop_jpeg_small_p%d' % (parallelism), 136 iters=num_iters, 137 wall_time=duration_decode_after_crop) 138 139 def benchmarkDecodeJpegMedium(self): 140 """Evaluate single DecodeImageOp for medium size image.""" 141 num_iters = 10 142 crop_window = [10, 10, 50, 50] 143 for parallelism in [1, 100]: 144 duration_decode = self._evalDecodeJpeg('medium.jpg', parallelism, 145 num_iters) 146 duration_decode_crop = self._evalDecodeJpeg('medium.jpg', parallelism, 147 num_iters, False, crop_window) 148 duration_decode_after_crop = self._evalDecodeJpeg( 149 'medium.jpg', parallelism, num_iters, True, crop_window) 150 self.report_benchmark( 151 name='decode_jpeg_medium_p%d' % (parallelism), 152 iters=num_iters, 153 wall_time=duration_decode) 154 self.report_benchmark( 155 name='decode_crop_jpeg_medium_p%d' % (parallelism), 156 iters=num_iters, 157 wall_time=duration_decode_crop) 158 self.report_benchmark( 159 name='decode_after_crop_jpeg_medium_p%d' % (parallelism), 160 iters=num_iters, 161 wall_time=duration_decode_after_crop) 162 163 def benchmarkDecodeJpegLarge(self): 164 """Evaluate single DecodeImageOp for large size image.""" 165 num_iters = 10 166 crop_window = [10, 10, 50, 50] 167 tile = [4, 4, 1] 168 for parallelism in [1, 100]: 169 # Tile the medium size image to composite a larger fake image. 170 duration_decode = self._evalDecodeJpeg('medium.jpg', parallelism, 171 num_iters, tile) 172 duration_decode_crop = self._evalDecodeJpeg( 173 'medium.jpg', parallelism, num_iters, False, crop_window, tile) 174 duration_decode_after_crop = self._evalDecodeJpeg( 175 'medium.jpg', parallelism, num_iters, True, crop_window, tile) 176 self.report_benchmark( 177 name='decode_jpeg_large_p%d' % (parallelism), 178 iters=num_iters, 179 wall_time=duration_decode) 180 self.report_benchmark( 181 name='decode_crop_jpeg_large_p%d' % (parallelism), 182 iters=num_iters, 183 wall_time=duration_decode_crop) 184 self.report_benchmark( 185 name='decode_after_crop_jpeg_large_p%d' % (parallelism), 186 iters=num_iters, 187 wall_time=duration_decode_after_crop) 188 189 190 if __name__ == '__main__': 191 test.main() 192