@@ -125,6 +125,97 @@ def adjust_saturation(img, saturation_factor):
125
125
return _blend (img , rgb_to_grayscale (img ), saturation_factor )
126
126
127
127
128
+ def center_crop (img , output_size ):
129
+ """Crop the Image Tensor and resize it to desired size.
130
+
131
+ Args:
132
+ img (Tensor): Image to be cropped. (0,0) denotes the top left corner of the image.
133
+ output_size (sequence or int): (height, width) of the crop box. If int,
134
+ it is used for both directions
135
+
136
+ Returns:
137
+ Tensor: Cropped image.
138
+ """
139
+ if not F ._is_tensor_image (img ):
140
+ raise TypeError ('tensor is not a torch image.' )
141
+
142
+ _ , image_width , image_height = img .size ()
143
+ crop_height , crop_width = output_size
144
+ crop_top = int (round ((image_height - crop_height ) / 2. ))
145
+ crop_left = int (round ((image_width - crop_width ) / 2. ))
146
+
147
+ return crop (img , crop_top , crop_left , crop_height , crop_width )
148
+
149
+
150
+ def five_crop (img , size ):
151
+ """Crop the given Image Tensor into four corners and the central crop.
152
+ .. Note::
153
+ This transform returns a tuple of Tensors and there may be a
154
+ mismatch in the number of inputs and targets your ``Dataset`` returns.
155
+
156
+ Args:
157
+ size (sequence or int): Desired output size of the crop. If size is an
158
+ int instead of sequence like (h, w), a square crop (size, size) is
159
+ made.
160
+
161
+ Returns:
162
+ tuple: tuple (tl, tr, bl, br, center)
163
+ Corresponding top left, top right, bottom left, bottom right and center crop.
164
+ """
165
+ if not F ._is_tensor_image (img ):
166
+ raise TypeError ('tensor is not a torch image.' )
167
+
168
+ assert len (size ) == 2 , "Please provide only two dimensions (h, w) for size."
169
+
170
+ _ , image_width , image_height = img .size ()
171
+ crop_height , crop_width = size
172
+ if crop_width > image_width or crop_height > image_height :
173
+ msg = "Requested crop size {} is bigger than input size {}"
174
+ raise ValueError (msg .format (size , (image_height , image_width )))
175
+
176
+ tl = crop (img , 0 , 0 , crop_width , crop_height )
177
+ tr = crop (img , image_width - crop_width , 0 , image_width , crop_height )
178
+ bl = crop (img , 0 , image_height - crop_height , crop_width , image_height )
179
+ br = crop (img , image_width - crop_width , image_height - crop_height , image_width , image_height )
180
+ center = center_crop (img , (crop_height , crop_width ))
181
+
182
+ return (tl , tr , bl , br , center )
183
+
184
+
185
+ def ten_crop (img , size , vertical_flip = False ):
186
+ """Crop the given Image Tensor into four corners and the central crop plus the
187
+ flipped version of these (horizontal flipping is used by default).
188
+ .. Note::
189
+ This transform returns a tuple of images and there may be a
190
+ mismatch in the number of inputs and targets your ``Dataset`` returns.
191
+
192
+ Args:
193
+ size (sequence or int): Desired output size of the crop. If size is an
194
+ int instead of sequence like (h, w), a square crop (size, size) is
195
+ made.
196
+ vertical_flip (bool): Use vertical flipping instead of horizontal
197
+
198
+ Returns:
199
+ tuple: tuple (tl, tr, bl, br, center, tl_flip, tr_flip, bl_flip, br_flip, center_flip)
200
+ Corresponding top left, top right, bottom left, bottom right and center crop
201
+ and same for the flipped image's tensor.
202
+ """
203
+ if not F ._is_tensor_image (img ):
204
+ raise TypeError ('tensor is not a torch image.' )
205
+
206
+ assert len (size ) == 2 , "Please provide only two dimensions (h, w) for size."
207
+ first_five = five_crop (img , size )
208
+
209
+ if vertical_flip :
210
+ img = vflip (img )
211
+ else :
212
+ img = hflip (img )
213
+
214
+ second_five = five_crop (img , size )
215
+
216
+ return first_five + second_five
217
+
218
+
128
219
def _blend (img1 , img2 , ratio ):
129
220
bound = 1 if img1 .dtype .is_floating_point else 255
130
221
return (ratio * img1 + (1 - ratio ) * img2 ).clamp (0 , bound ).to (img1 .dtype )
0 commit comments