Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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

 

# coding: utf-8 

 

# In[1]: 

 

from tensorflow.python.ops import image_ops 

from tensorflow.python.ops import math_ops 

from tensorflow.python.ops import array_ops 

 

import tensorflow as tf 

 

# In[2]: 

 

def crop_to_bounding_box(image, offset_height, offset_width, target_height, 

target_width, dynamic_shape=False): 

"""Crops an image to a specified bounding box. 

 

This op cuts a rectangular part out of `image`. The top-left corner of the 

returned image is at `offset_height, offset_width` in `image`, and its 

lower-right corner is at 

`offset_height + target_height, offset_width + target_width`. 

 

Args: 

image: 3-D tensor with shape `[height, width, channels]` 

offset_height: Vertical coordinate of the top-left corner of the result in 

the input. 

offset_width: Horizontal coordinate of the top-left corner of the result in 

the input. 

target_height: Height of the result. 

target_width: Width of the result. 

dynamic_shape: Whether the input image has undertermined shape. If set to 

`True`, shape information will be retrieved at run time. Default to 

`False`. 

 

Returns: 

3-D tensor of image with shape `[target_height, target_width, channels]` 

 

Raises: 

ValueError: If the shape of `image` is incompatible with the `offset_*` or 

`target_*` arguments, and `dynamic_shape` is set to `False`. 

""" 

image = tf.convert_to_tensor(image, name='image') 

_Check3DImage(image, require_static=(not dynamic_shape)) 

height, width, _ = _ImageDimensions(image, dynamic_shape=dynamic_shape) 

 

if not dynamic_shape: 

if offset_width < 0: 

raise ValueError('offset_width must be >= 0.') 

if offset_height < 0: 

raise ValueError('offset_height must be >= 0.') 

 

if width < (target_width + offset_width): 

raise ValueError('width must be >= target + offset.') 

if height < (target_height + offset_height): 

raise ValueError('height must be >= target + offset.') 

 

cropped = array_ops.slice(image, 

array_ops.stack([offset_height, offset_width, 0]), 

array_ops.stack([target_height, target_width, -1])) 

 

return cropped 

 

 

# In[3]: 

 

def pad_to_bounding_box(image, offset_height, offset_width, target_height, 

target_width, dynamic_shape=False): 

"""Pad `image` with zeros to the specified `height` and `width`. 

 

Adds `offset_height` rows of zeros on top, `offset_width` columns of 

zeros on the left, and then pads the image on the bottom and right 

with zeros until it has dimensions `target_height`, `target_width`. 

 

This op does nothing if `offset_*` is zero and the image already has size 

`target_height` by `target_width`. 

 

Args: 

image: 3-D tensor with shape `[height, width, channels]` 

offset_height: Number of rows of zeros to add on top. 

offset_width: Number of columns of zeros to add on the left. 

target_height: Height of output image. 

target_width: Width of output image. 

dynamic_shape: Whether the input image has undertermined shape. If set to 

`True`, shape information will be retrieved at run time. Default to 

`False`. 

 

Returns: 

3-D tensor of shape `[target_height, target_width, channels]` 

Raises: 

ValueError: If the shape of `image` is incompatible with the `offset_*` or 

`target_*` arguments, and `dynamic_shape` is set to `False`. 

""" 

image = tf.convert_to_tensor(image, name='image') 

_Check3DImage(image, require_static=(not dynamic_shape)) 

height, width, depth = _ImageDimensions(image, dynamic_shape=dynamic_shape) 

 

after_padding_width = target_width - offset_width - width 

after_padding_height = target_height - offset_height - height 

 

if not dynamic_shape: 

if target_width < width: 

raise ValueError('target_width must be >= width') 

if target_height < height: 

raise ValueError('target_height must be >= height') 

 

if after_padding_width < 0: 

raise ValueError('target_width not possible given ' 

'offset_width and image width') 

if after_padding_height < 0: 

raise ValueError('target_height not possible given ' 

'offset_height and image height') 

 

# Do not pad on the depth dimensions. 

if (dynamic_shape or offset_width or offset_height or 

after_padding_width or after_padding_height): 

paddings = array_ops.reshape( 

array_ops.stack([offset_height, after_padding_height, 

offset_width, after_padding_width, 

0, 0]), 

[3, 2]) 

padded = array_ops.pad(image, paddings) 

if not dynamic_shape: 

padded.set_shape([target_height, target_width, depth]) 

else: 

padded = image 

 

return padded 

 

 

# In[4]: 

 

def resize_image_with_crop_or_pad(image, target_height, target_width, 

dynamic_shape=False): 

"""Crops and/or pads an image to a target width and height. 

 

Resizes an image to a target width and height by either centrally 

cropping the image or padding it evenly with zeros. 

 

If `width` or `height` is greater than the specified `target_width` or 

`target_height` respectively, this op centrally crops along that dimension. 

If `width` or `height` is smaller than the specified `target_width` or 

`target_height` respectively, this op centrally pads with 0 along that 

dimension. 

 

Args: 

image: 3-D tensor of shape [height, width, channels] 

target_height: Target height. 

target_width: Target width. 

dynamic_shape: Whether the input image has undertermined shape. If set to 

`True`, shape information will be retrieved at run time. Default to 

`False`. 

 

Raises: 

ValueError: if `target_height` or `target_width` are zero or negative. 

 

Returns: 

Cropped and/or padded image of shape 

`[target_height, target_width, channels]` 

""" 

image = tf.convert_to_tensor(image, name='image') 

_Check3DImage(image, require_static=(not dynamic_shape)) 

original_height, original_width, _ = _ImageDimensions(image, dynamic_shape=dynamic_shape) 

 

if target_width <= 0: 

raise ValueError('target_width must be > 0.') 

if target_height <= 0: 

raise ValueError('target_height must be > 0.') 

 

if dynamic_shape: 

max_ = math_ops.maximum 

min_ = math_ops.minimum 

else: 

max_ = max 

min_ = min 

 

width_diff = target_width - original_width 

offset_crop_width = max_(-width_diff // 2, 0) 

offset_pad_width = max_(width_diff // 2, 0) 

 

height_diff = target_height - original_height 

offset_crop_height = max_(-height_diff // 2, 0) 

offset_pad_height = max_(height_diff // 2, 0) 

 

# Maybe crop if needed. 

cropped = crop_to_bounding_box(image, offset_crop_height, offset_crop_width, 

min_(target_height, original_height), 

min_(target_width, original_width), 

dynamic_shape=dynamic_shape) 

 

# Maybe pad if needed. 

resized = pad_to_bounding_box(cropped, offset_pad_height, offset_pad_width, 

target_height, target_width, 

dynamic_shape=dynamic_shape) 

 

if resized.get_shape().ndims is None: 

raise ValueError('resized contains no shape.') 

if not resized.get_shape()[0].is_compatible_with(target_height): 

raise ValueError('resized height is not correct.') 

if not resized.get_shape()[1].is_compatible_with(target_width): 

raise ValueError('resized width is not correct.') 

return resized 

 

 

# In[5]: 

 

def _ImageDimensions(images, dynamic_shape=False): 

"""Returns the dimensions of an image tensor. 

Args: 

images: 4-D Tensor of shape [batch, height, width, channels] 

dynamic_shape: Whether the input image has undertermined shape. If set to 

`True`, shape information will be retrieved at run time. Default to 

`False`. 

 

Returns: 

list of integers [batch, height, width, channels] 

""" 

# A simple abstraction to provide names for each dimension. This abstraction 

# should make it simpler to switch dimensions in the future (e.g. if we ever 

# want to switch height and width.) 

if dynamic_shape: 

return array_ops.unstack(array_ops.shape(images)) 

else: 

return images.get_shape().as_list() 

 

 

# In[6]: 

 

def _Check3DImage(image, require_static=True): 

"""Assert that we are working with properly shaped image. 

Args: 

image: 3-D Tensor of shape [height, width, channels] 

require_static: If `True`, requires that all dimensions of `image` are 

known and non-zero. 

 

Raises: 

ValueError: if image.shape is not a [3] vector. 

""" 

try: 

image_shape = image.get_shape().with_rank(3) 

except ValueError: 

raise ValueError('\'image\' must be three-dimensional.') 

if require_static and not image_shape.is_fully_defined(): 

raise ValueError('\'image\' must be fully defined.') 

if any(x == 0 for x in image_shape): 

raise ValueError('all dims of \'image.shape\' must be > 0: %s' % 

image_shape) 

 

 

# In[7]: 

 

image_ops.resize_image_with_crop_or_pad = resize_image_with_crop_or_pad 

#image_ops.crop_to_bounding_box = crop_to_bounding_box 

#image_ops.pad_to_bounding_box = pad_to_bounding_box 

#image_ops._ImageDimensions = _ImageDimensions 

#image_ops._Check3DImage = _Check3DImage