The image preprocessor loads an image from disk and prepares it as needed for batching. This includes padding, resizing, normalization, data type casting, and transposing. This Image Batcher implements one algorithm for now: * Resizes and pads the image to fit the in
(self, image_path)
| 124 | |
| 125 | |
| 126 | def preprocess_image(self, image_path): |
| 127 | """ |
| 128 | The image preprocessor loads an image from disk and prepares it as needed for batching. This includes padding, |
| 129 | resizing, normalization, data type casting, and transposing. |
| 130 | This Image Batcher implements one algorithm for now: |
| 131 | * Resizes and pads the image to fit the input size. |
| 132 | :param image_path: The path to the image on disk to load. |
| 133 | :return: Two values: A numpy array holding the image sample, ready to be contacatenated into the rest of the |
| 134 | batch, and the resize scale used, if any. |
| 135 | """ |
| 136 | |
| 137 | def resize_pad(image, pad_color=(0, 0, 0)): |
| 138 | """ |
| 139 | A subroutine to implement padding and resizing. This will resize the image to fit fully within the input |
| 140 | size, and pads the remaining bottom-right portions with the value provided. |
| 141 | :param image: The PIL image object |
| 142 | :pad_color: The RGB values to use for the padded area. Default: Black/Zeros. |
| 143 | :return: Two values: The PIL image object already padded and cropped, and the resize scale used. |
| 144 | """ |
| 145 | |
| 146 | # Get characteristics. |
| 147 | width, height = image.size |
| 148 | |
| 149 | # Replicates behavior of ResizeShortestEdge augmentation. |
| 150 | size = self.min_size_test * 1.0 |
| 151 | pre_scale = size / min(height, width) |
| 152 | if height < width: |
| 153 | newh, neww = size, pre_scale * width |
| 154 | else: |
| 155 | newh, neww = pre_scale * height, size |
| 156 | |
| 157 | # If delta between min and max dimensions is so that max sized dimension reaches self.max_size_test |
| 158 | # before min dimension reaches self.min_size_test, keeping the same aspect ratio. We still need to |
| 159 | # maintain the same aspect ratio and keep max dimension at self.max_size_test. |
| 160 | if max(newh, neww) > self.max_size_test: |
| 161 | pre_scale = self.max_size_test * 1.0 / max(newh, neww) |
| 162 | newh = newh * pre_scale |
| 163 | neww = neww * pre_scale |
| 164 | neww = int(neww + 0.5) |
| 165 | newh = int(newh + 0.5) |
| 166 | |
| 167 | # Scaling factor for normalized box coordinates scaling in post-processing. |
| 168 | scaling = max(newh/height, neww/width) |
| 169 | |
| 170 | # Padding. |
| 171 | image = image.resize((neww, newh), resample=Image.BILINEAR) |
| 172 | pad = Image.new("RGB", (self.width, self.height)) |
| 173 | pad.paste(pad_color, [0, 0, self.width, self.height]) |
| 174 | pad.paste(image) |
| 175 | return pad, scaling |
| 176 | |
| 177 | scale = None |
| 178 | image = Image.open(image_path) |
| 179 | image = image.convert(mode='RGB') |
| 180 | # Pad with mean values of COCO dataset, since padding is applied before actual model's |
| 181 | # preprocessor steps (Sub, Div ops), we need to pad with mean values in order to reverse |
| 182 | # the effects of Sub and Div, so that padding after model's preprocessor will be with actual 0s. |
| 183 | image, scale = resize_pad(image, (124, 116, 104)) |