方法一
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
|
import random import numpy as np from PIL import Image, ImageOps, ImageFilter from skimage.filters import gaussian import torch import math import numbers import random class RandomVerticalFlip( object ): def __call__( self , img): if random.random() < 0.5 : return img.transpose(Image.FLIP_TOP_BOTTOM) return img class DeNormalize( object ): def __init__( self , mean, std): self .mean = mean self .std = std def __call__( self , tensor): for t, m, s in zip (tensor, self .mean, self .std): t.mul_(s).add_(m) return tensor class MaskToTensor( object ): def __call__( self , img): return torch.from_numpy(np.array(img, dtype = np.int32)). long () class FreeScale( object ): def __init__( self , size, interpolation = Image.BILINEAR): self .size = tuple ( reversed (size)) # size: (h, w) self .interpolation = interpolation def __call__( self , img): return img.resize( self .size, self .interpolation) class FlipChannels( object ): def __call__( self , img): img = np.array(img)[:, :, :: - 1 ] return Image.fromarray(img.astype(np.uint8)) class RandomGaussianBlur( object ): def __call__( self , img): sigma = 0.15 + random.random() * 1.15 blurred_img = gaussian(np.array(img), sigma = sigma, multichannel = True ) blurred_img * = 255 return Image.fromarray(blurred_img.astype(np.uint8)) # 组合 class Compose( object ): def __init__( self , transforms): self .transforms = transforms def __call__( self , img, mask): assert img.size = = mask.size for t in self .transforms: img, mask = t(img, mask) return img, mask # 随机裁剪 class RandomCrop( object ): def __init__( self , size, padding = 0 ): if isinstance (size, numbers.Number): self .size = ( int (size), int (size)) else : self .size = size self .padding = padding def __call__( self , img, mask): if self .padding > 0 : img = ImageOps.expand(img, border = self .padding, fill = 0 ) mask = ImageOps.expand(mask, border = self .padding, fill = 0 ) assert img.size = = mask.size w, h = img.size th, tw = self .size if w = = tw and h = = th: return img, mask if w < tw or h < th: return img.resize((tw, th), Image.BILINEAR), mask.resize((tw, th), Image.NEAREST) x1 = random.randint( 0 , w - tw) y1 = random.randint( 0 , h - th) return img.crop((x1, y1, x1 + tw, y1 + th)), mask.crop((x1, y1, x1 + tw, y1 + th)) # 中心裁剪 class CenterCrop( object ): def __init__( self , size): if isinstance (size, numbers.Number): self .size = ( int (size), int (size)) else : self .size = size def __call__( self , img, mask): assert img.size = = mask.size w, h = img.size th, tw = self .size x1 = int ( round ((w - tw) / 2. )) y1 = int ( round ((h - th) / 2. )) return img.crop((x1, y1, x1 + tw, y1 + th)), mask.crop((x1, y1, x1 + tw, y1 + th)) class RandomHorizontallyFlip( object ): def __call__( self , img, mask): if random.random() < 0.5 : return img.transpose(Image.FLIP_LEFT_RIGHT), mask.transpose(Image.FLIP_LEFT_RIGHT) return img, mask class Scale( object ): def __init__( self , size): self .size = size def __call__( self , img, mask): assert img.size = = mask.size w, h = img.size if (w > = h and w = = self .size) or (h > = w and h = = self .size): return img, mask if w > h: ow = self .size oh = int ( self .size * h / w) return img.resize((ow, oh), Image.BILINEAR), mask.resize((ow, oh), Image.NEAREST) else : oh = self .size ow = int ( self .size * w / h) return img.resize((ow, oh), Image.BILINEAR), mask.resize((ow, oh), Image.NEAREST) class RandomSizedCrop( object ): def __init__( self , size): self .size = size def __call__( self , img, mask): assert img.size = = mask.size for attempt in range ( 10 ): area = img.size[ 0 ] * img.size[ 1 ] target_area = random.uniform( 0.45 , 1.0 ) * area aspect_ratio = random.uniform( 0.5 , 2 ) w = int ( round (math.sqrt(target_area * aspect_ratio))) h = int ( round (math.sqrt(target_area / aspect_ratio))) if random.random() < 0.5 : w, h = h, w if w < = img.size[ 0 ] and h < = img.size[ 1 ]: x1 = random.randint( 0 , img.size[ 0 ] - w) y1 = random.randint( 0 , img.size[ 1 ] - h) img = img.crop((x1, y1, x1 + w, y1 + h)) mask = mask.crop((x1, y1, x1 + w, y1 + h)) assert (img.size = = (w, h)) return img.resize(( self .size, self .size), Image.BILINEAR), mask.resize(( self .size, self .size), Image.NEAREST) # Fallback scale = Scale( self .size) crop = CenterCrop( self .size) return crop( * scale(img, mask)) class RandomRotate( object ): def __init__( self , degree): self .degree = degree def __call__( self , img, mask): rotate_degree = random.random() * 2 * self .degree - self .degree return img.rotate(rotate_degree, Image.BILINEAR), mask.rotate(rotate_degree, Image.NEAREST) class RandomSized( object ): def __init__( self , size): self .size = size self .scale = Scale( self .size) self .crop = RandomCrop( self .size) def __call__( self , img, mask): assert img.size = = mask.size w = int (random.uniform( 0.5 , 2 ) * img.size[ 0 ]) h = int (random.uniform( 0.5 , 2 ) * img.size[ 1 ]) img, mask = img.resize((w, h), Image.BILINEAR), mask.resize((w, h), Image.NEAREST) return self .crop( * self .scale(img, mask)) class SlidingCropOld( object ): def __init__( self , crop_size, stride_rate, ignore_label): self .crop_size = crop_size self .stride_rate = stride_rate self .ignore_label = ignore_label def _pad( self , img, mask): h, w = img.shape[: 2 ] pad_h = max ( self .crop_size - h, 0 ) pad_w = max ( self .crop_size - w, 0 ) img = np.pad(img, (( 0 , pad_h), ( 0 , pad_w), ( 0 , 0 )), 'constant' ) mask = np.pad(mask, (( 0 , pad_h), ( 0 , pad_w)), 'constant' , constant_values = self .ignore_label) return img, mask def __call__( self , img, mask): assert img.size = = mask.size w, h = img.size long_size = max (h, w) img = np.array(img) mask = np.array(mask) if long_size > self .crop_size: stride = int (math.ceil( self .crop_size * self .stride_rate)) h_step_num = int (math.ceil((h - self .crop_size) / float (stride))) + 1 w_step_num = int (math.ceil((w - self .crop_size) / float (stride))) + 1 img_sublist, mask_sublist = [], [] for yy in range (h_step_num): for xx in range (w_step_num): sy, sx = yy * stride, xx * stride ey, ex = sy + self .crop_size, sx + self .crop_size img_sub = img[sy: ey, sx: ex, :] mask_sub = mask[sy: ey, sx: ex] img_sub, mask_sub = self ._pad(img_sub, mask_sub) img_sublist.append(Image.fromarray(img_sub.astype(np.uint8)).convert( 'RGB' )) mask_sublist.append(Image.fromarray(mask_sub.astype(np.uint8)).convert( 'P' )) return img_sublist, mask_sublist else : img, mask = self ._pad(img, mask) img = Image.fromarray(img.astype(np.uint8)).convert( 'RGB' ) mask = Image.fromarray(mask.astype(np.uint8)).convert( 'P' ) return img, mask class SlidingCrop( object ): def __init__( self , crop_size, stride_rate, ignore_label): self .crop_size = crop_size self .stride_rate = stride_rate self .ignore_label = ignore_label def _pad( self , img, mask): h, w = img.shape[: 2 ] pad_h = max ( self .crop_size - h, 0 ) pad_w = max ( self .crop_size - w, 0 ) img = np.pad(img, (( 0 , pad_h), ( 0 , pad_w), ( 0 , 0 )), 'constant' ) mask = np.pad(mask, (( 0 , pad_h), ( 0 , pad_w)), 'constant' , constant_values = self .ignore_label) return img, mask, h, w def __call__( self , img, mask): assert img.size = = mask.size w, h = img.size long_size = max (h, w) img = np.array(img) mask = np.array(mask) if long_size > self .crop_size: stride = int (math.ceil( self .crop_size * self .stride_rate)) h_step_num = int (math.ceil((h - self .crop_size) / float (stride))) + 1 w_step_num = int (math.ceil((w - self .crop_size) / float (stride))) + 1 img_slices, mask_slices, slices_info = [], [], [] for yy in range (h_step_num): for xx in range (w_step_num): sy, sx = yy * stride, xx * stride ey, ex = sy + self .crop_size, sx + self .crop_size img_sub = img[sy: ey, sx: ex, :] mask_sub = mask[sy: ey, sx: ex] img_sub, mask_sub, sub_h, sub_w = self ._pad(img_sub, mask_sub) img_slices.append(Image.fromarray(img_sub.astype(np.uint8)).convert( 'RGB' )) mask_slices.append(Image.fromarray(mask_sub.astype(np.uint8)).convert( 'P' )) slices_info.append([sy, ey, sx, ex, sub_h, sub_w]) return img_slices, mask_slices, slices_info else : img, mask, sub_h, sub_w = self ._pad(img, mask) img = Image.fromarray(img.astype(np.uint8)).convert( 'RGB' ) mask = Image.fromarray(mask.astype(np.uint8)).convert( 'P' ) return [img], [mask], [[ 0 , sub_h, 0 , sub_w, sub_h, sub_w]] |
方法二
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
import numpy as np import random import torch from torchvision import transforms as T from torchvision.transforms import functional as F def pad_if_smaller(img, size, fill = 0 ): # 如果图像最小边长小于给定size,则用数值fill进行padding min_size = min (img.size) if min_size < size: ow, oh = img.size padh = size - oh if oh < size else 0 padw = size - ow if ow < size else 0 img = F.pad(img, ( 0 , 0 , padw, padh), fill = fill) return img class Compose( object ): def __init__( self , transforms): self .transforms = transforms def __call__( self , image, target): for t in self .transforms: image, target = t(image, target) return image, target class RandomResize( object ): def __init__( self , min_size, max_size = None ): self .min_size = min_size if max_size is None : max_size = min_size self .max_size = max_size def __call__( self , image, target): size = random.randint( self .min_size, self .max_size) # 这里size传入的是int类型,所以是将图像的最小边长缩放到size大小 image = F.resize(image, size) # 这里的interpolation注意下,在torchvision(0.9.0)以后才有InterpolationMode.NEAREST # 如果是之前的版本需要使用PIL.Image.NEAREST target = F.resize(target, size, interpolation = T.InterpolationMode.NEAREST) return image, target class RandomHorizontalFlip( object ): def __init__( self , flip_prob): self .flip_prob = flip_prob def __call__( self , image, target): if random.random() < self .flip_prob: image = F.hflip(image) target = F.hflip(target) return image, target class RandomCrop( object ): def __init__( self , size): self .size = size def __call__( self , image, target): image = pad_if_smaller(image, self .size) target = pad_if_smaller(target, self .size, fill = 255 ) crop_params = T.RandomCrop.get_params(image, ( self .size, self .size)) image = F.crop(image, * crop_params) target = F.crop(target, * crop_params) return image, target class CenterCrop( object ): def __init__( self , size): self .size = size def __call__( self , image, target): image = F.center_crop(image, self .size) target = F.center_crop(target, self .size) return image, target class ToTensor( object ): def __call__( self , image, target): image = F.to_tensor(image) target = torch.as_tensor(np.array(target), dtype = torch.int64) return image, target class Normalize( object ): def __init__( self , mean, std): self .mean = mean self .std = std def __call__( self , image, target): image = F.normalize(image, mean = self .mean, std = self .std) return image, target |
到此这篇关于详解Python实现图像分割增强的两种方法的文章就介绍到这了,更多相关Python图像分割增强内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://blog.csdn.net/hhhhhhhhhhwwwwwwwwww/article/details/123233333