3
3
import numpy as np
4
4
import tensorflow as tf
5
5
6
- IMG_MEAN = np .array ((104.00698793 ,116.66876762 ,122.67891434 ), dtype = np .float32 )
6
+
7
+
8
+ # IMG_MEAN = np.array((104.00698793,116.66876762,122.67891434), dtype=np.float32)
9
+ # IMG_MEAN = np.array((104.0,116.0,122.0), dtype=np.float32)
10
+
7
11
8
12
def read_labeled_image_list (data_dir , data_list ):
9
13
"""Reads txt file containing paths to images and ground truth masks.
@@ -37,13 +41,87 @@ def read_labeled_image_list(data_dir, data_list):
37
41
38
42
return images , masks , img_type
39
43
40
- def image_distortions (image , distortions ):
41
- distort_left_right_random = distortions [0 ]
44
+ def image_mirroring (image , random_number ):
45
+ distort_left_right_random = random_number [0 ]
42
46
mirror = tf .less (tf .pack ([1.0 , distort_left_right_random , 1.0 ]), 0.5 )
43
47
image = tf .reverse (image , mirror )
44
48
return image
49
+
50
+ def random_crop_and_pad_image_and_labels (image , labels , crop_h , crop_w ):
51
+ """Randomly crops `image` together with `labels`.
52
+ To ensure labels are padded with "ignore_label" this has to be subtracted from the label image, then
53
+ after padding with 0, that value is added again. Make sure dtype allows negative values.
54
+ Args:
55
+ image: A Tensor with shape [D_1, ..., D_K, N]
56
+ labels: A Tensor with shape [D_1, ..., D_K, M]
57
+ size: A Tensor with shape [K] indicating the crop size.
58
+ Returns:
59
+ A tuple of (cropped_image, cropped_label).
60
+ """
61
+ combined = tf .concat (2 , [image , labels ])
62
+ image_shape = tf .shape (image )
63
+ combined_pad = tf .image .pad_to_bounding_box (
64
+ combined , 0 , 0 ,
65
+ tf .maximum (crop_h , image_shape [0 ]),
66
+ tf .maximum (crop_w , image_shape [1 ]))
67
+
68
+ last_image_dim = tf .shape (image )[- 1 ]
69
+ last_label_dim = tf .shape (labels )[- 1 ]
70
+ combined_crop = tf .random_crop (combined_pad ,[crop_h ,crop_w ,4 ]) # TODO: Make cropping size a variable
71
+
72
+ return (combined_crop [:, :, :last_image_dim ],
73
+ combined_crop [:, :, last_image_dim :])
74
+
45
75
46
- def read_images_from_disk (input_queue , input_size , random_scale , img_type ): # optional pre-processing arguments
76
+ def preprocess_input_train (img , label , ignore_label = 255 ,
77
+ input_size = (321 ,321 ),
78
+ scale = True ,
79
+ mirror = True ):
80
+ """Read one image and its corresponding mask with optional pre-processing.
81
+ Args:
82
+ input_queue: tf queue with paths to the image and its mask.
83
+
84
+ Returns:
85
+ Two tensors: the decoded image and its mask.
86
+ """
87
+
88
+ if scale :
89
+ # Scale
90
+ scale = tf .random_uniform ([1 ], minval = 0.5 , maxval = 1.5 , dtype = tf .float32 , seed = None )
91
+ h_new = tf .to_int32 (tf .mul (tf .to_float (tf .shape (img )[0 ]), scale ))
92
+ w_new = tf .to_int32 (tf .mul (tf .to_float (tf .shape (img )[1 ]), scale ))
93
+ new_shape = tf .squeeze (tf .pack ([h_new , w_new ]), squeeze_dims = [1 ])
94
+ img = tf .image .resize_images (img , new_shape )
95
+ label = tf .image .resize_nearest_neighbor (tf .expand_dims (label , 0 ), new_shape )
96
+ label = tf .squeeze (label , squeeze_dims = [0 ])
97
+
98
+ if mirror :
99
+ # Mirror
100
+ random_number = tf .random_uniform ([2 ], 0 , 1.0 , dtype = tf .float32 )
101
+ img = image_mirroring (img , random_number )
102
+ label = image_mirroring (label , random_number )
103
+
104
+ # Crop and pad image
105
+ label = tf .cast (label , dtype = tf .float32 ) # Needs to be subtract and later added due to 0 padding
106
+ label = label - ignore_label
107
+ crop_h , crop_w = input_size
108
+ img , label = random_crop_and_pad_image_and_labels (img , label , crop_h , crop_w )
109
+ label = label + ignore_label
110
+ label = tf .cast (label , dtype = tf .uint8 )
111
+ # Set static shape so that tensorflow knows shape at compile time
112
+ img .set_shape ((crop_h , crop_w , 3 ))
113
+ label .set_shape ((crop_h ,crop_w , 1 ))
114
+
115
+ return img , label
116
+
117
+
118
+ def read_images_from_disk (input_queue ,
119
+ img_type ,
120
+ phase ,
121
+ input_size = (321 ,321 ),
122
+ ignore_label = 255 ,
123
+ scale = True ,
124
+ mirror = True ):
47
125
"""Read one image and its corresponding mask with optional pre-processing.
48
126
49
127
Args:
@@ -52,11 +130,12 @@ def read_images_from_disk(input_queue, input_size, random_scale, img_type): # op
52
130
If not given, return images of original size.
53
131
random_scale: whether to randomly scale the images prior
54
132
to random crop.
133
+ phase: A string specifying either 'train' , 'valid' or 'test'
55
134
56
135
Returns:
57
136
Two tensors: the decoded image and its mask.
58
137
"""
59
- mirror = True # TODO: make this a variable
138
+
60
139
img_contents = tf .read_file (input_queue [0 ])
61
140
label_contents = tf .read_file (input_queue [1 ])
62
141
@@ -66,55 +145,69 @@ def read_images_from_disk(input_queue, input_size, random_scale, img_type): # op
66
145
img = tf .image .decode_png (img_contents , channels = 3 ) # CamVid
67
146
68
147
label = tf .image .decode_png (label_contents , channels = 1 )
69
- if input_size is not None :
70
- h , w = input_size
71
- if random_scale :
72
- scale = tf .random_uniform ([1 ], minval = 0.75 , maxval = 1.25 , dtype = tf .float32 , seed = None )
73
- h_new = tf .to_int32 (tf .mul (tf .to_float (tf .shape (img )[0 ]), scale ))
74
- w_new = tf .to_int32 (tf .mul (tf .to_float (tf .shape (img )[1 ]), scale ))
75
- new_shape = tf .squeeze (tf .pack ([h_new , w_new ]), squeeze_dims = [1 ])
76
-
77
- img = tf .image .resize_images (img , new_shape )
78
- label = tf .image .resize_nearest_neighbor (tf .expand_dims (label , 0 ), new_shape )
79
- label = tf .squeeze (label , squeeze_dims = [0 ])
80
- if mirror :
81
- distortions = tf .random_uniform ([2 ], 0 , 1.0 , dtype = tf .float32 )
82
- img = image_distortions (img , distortions )
83
- label = image_distortions (label , distortions )
84
- img = tf .image .resize_image_with_crop_or_pad (img , h , w )
85
- label = tf .image .resize_image_with_crop_or_pad (label , h , w )
148
+
149
+
150
+ # Change RGB to BGR
86
151
img_r , img_g , img_b = tf .split (split_dim = 2 , num_split = 3 , value = img )
87
- img = tf .cast (tf .concat (2 , [img_b , img_g , img_r ]), dtype = tf .float32 )
88
- # extract mean
89
- img -= IMG_MEAN
90
- return img , label
152
+ img = tf .cast (tf .concat (2 , [img_b , img_g , img_r ]), dtype = tf .float32 )
153
+
154
+ # Mean subtraction
155
+ IMG_MEAN = tf .constant ([104.00698793 ,116.66876762 ,122.67891434 ],shape = [1 ,1 ,3 ], dtype = tf .float32 ) # BGR
156
+ IMG_MEAN = tf .reshape (IMG_MEAN ,[1 ,1 ,3 ])
157
+ img = img - IMG_MEAN
158
+
159
+
160
+ # Optional preprocessing for training phase
161
+ if phase == 'train' :
162
+ img , label = preprocess_input_train (img , label , input_size = (321 ,321 ),
163
+ ignore_label = ignore_label )
164
+ elif phase == 'valid' :
165
+ # TODO: Perform only a central crop -> size should be the same as during training
166
+ pass
167
+ elif phase == 'test' :
168
+ pass
169
+
170
+ return img , label
171
+
172
+
173
+
174
+
175
+ def image_mirroring (image , random_number ):
176
+ distort_left_right_random = random_number [0 ]
177
+ mirror = tf .less (tf .pack ([1.0 , distort_left_right_random , 1.0 ]), 0.5 )
178
+ image = tf .reverse (image , mirror )
179
+ return image
180
+
91
181
92
182
class ImageReader (object ):
93
183
'''Generic ImageReader which reads images and corresponding segmentation
94
184
masks from the disk, and enqueues them into a TensorFlow queue.
95
185
'''
96
186
97
- def __init__ (self , data_dir , data_list , input_size , random_scale , coord ):
187
+ def __init__ (self , data_dir , data_list , input_size , phase , coord ):
98
188
'''Initialise an ImageReader.
99
189
100
190
Args:
101
191
data_dir: path to the directory with images and masks.
102
192
data_list: path to the file with lines of the form '/path/to/image /path/to/mask'.
103
193
input_size: a tuple with (height, width) values, to which all the images will be resized.
104
- random_scale: whether to randomly scale the images prior to random crop.
194
+ phase: 'train', 'valid' or 'test'
105
195
coord: TensorFlow queue coordinator.
106
196
'''
107
197
self .data_dir = data_dir
108
198
self .data_list = data_list
109
199
self .input_size = input_size
110
200
self .coord = coord
201
+ self .phase = phase
111
202
112
203
self .image_list , self .label_list , self .img_type = read_labeled_image_list (self .data_dir , self .data_list )
113
204
self .images = tf .convert_to_tensor (self .image_list , dtype = tf .string )
114
205
self .labels = tf .convert_to_tensor (self .label_list , dtype = tf .string )
115
206
self .queue = tf .train .slice_input_producer ([self .images , self .labels ],
116
207
shuffle = input_size is not None ) # not shuffling if it is val
117
- self .image , self .label = read_images_from_disk (self .queue , self .input_size , random_scale , self .img_type )
208
+ # self.image, self.label = read_images_from_disk(self.queue, self.input_size, phase, self.img_type)
209
+ # self.image, self.label = read_images_from_disk(self.queue, self.img_type, self.phase, input_size = (321,321), ignore_label = 255)
210
+ self .image , self .label = read_images_from_disk (self .queue , self .img_type , self .phase )
118
211
119
212
def dequeue (self , num_elements ):
120
213
'''Pack images and labels into a batch.
0 commit comments