2016-12-18 2 views
0

Ich möchte die Datenargumentation durch Drehen von Bildern in Tensorflow implementieren. Nach dem Durchsuchen des relativen Materials im Stack-Overflow findet sich eine bessere Antwort nach zimmermc.Tensorflow trifft beim Drehen von Bildern auf einen Fehler

def rotate_image_tensor(image, angle, mode='black'): 
""" 
Rotates a 3D tensor (HWD), which represents an image by given radian angle. 
New image has the same size as the input image. 
mode controls what happens to border pixels. 
mode = 'black' results in black bars (value 0 in unknown areas) 
mode = 'white' results in value 255 in unknown areas 
mode = 'ones' results in value 1 in unknown areas 
mode = 'repeat' keeps repeating the closest pixel known 
""" 

s = image.get_shape().as_list() 
assert len(s) == 3, "Input needs to be 3D." 
assert (mode == 'repeat') or (mode == 'black') or (mode == 'white') or (mode == 'ones'), "Unknown boundary mode." 
image_center = [np.floor(x/2) for x in s] 

# Coordinates of new image 
coord1 = tf.range(s[0]) 
coord2 = tf.range(s[1]) 

# Create vectors of those coordinates in order to vectorize the image 
coord1_vec = tf.tile(coord1, [s[1]]) 

coord2_vec_unordered = tf.tile(coord2, [s[0]]) 
coord2_vec_unordered = tf.reshape(coord2_vec_unordered, [s[0], s[1]]) 
coord2_vec = tf.reshape(tf.transpose(coord2_vec_unordered, [1, 0]), [-1]) 

# center coordinates since rotation center is supposed to be in the image center 
coord1_vec_centered = coord1_vec - image_center[0] 
coord2_vec_centered = coord2_vec - image_center[1] 

coord_new_centered = tf.cast(tf.pack([coord1_vec_centered, coord2_vec_centered]), tf.float32) 

# Perform backward transformation of the image coordinates 
rot_mat_inv = tf.dynamic_stitch([[0], [1], [2], [3]], [tf.cos(angle), tf.sin(angle), -tf.sin(angle), tf.cos(angle)]) 
rot_mat_inv = tf.reshape(rot_mat_inv, shape=[2, 2]) 
coord_old_centered = tf.matmul(rot_mat_inv, coord_new_centered) 

# Find nearest neighbor in old image 
coord1_old_nn = tf.cast(tf.round(coord_old_centered[0, :] + image_center[0]), tf.int32) 
coord2_old_nn = tf.cast(tf.round(coord_old_centered[1, :] + image_center[1]), tf.int32) 

# Clip values to stay inside image coordinates 
if mode == 'repeat': 
    coord_old1_clipped = tf.minimum(tf.maximum(coord1_old_nn, 0), s[0]-1) 
    coord_old2_clipped = tf.minimum(tf.maximum(coord2_old_nn, 0), s[1]-1) 
else: 
    outside_ind1 = tf.logical_or(tf.greater(coord1_old_nn, s[0]-1), tf.less(coord1_old_nn, 0)) 
    outside_ind2 = tf.logical_or(tf.greater(coord2_old_nn, s[1]-1), tf.less(coord2_old_nn, 0)) 
    outside_ind = tf.logical_or(outside_ind1, outside_ind2) 

    coord_old1_clipped = tf.boolean_mask(coord1_old_nn, tf.logical_not(outside_ind)) 
    coord_old2_clipped = tf.boolean_mask(coord2_old_nn, tf.logical_not(outside_ind)) 

    coord1_vec = tf.boolean_mask(coord1_vec, tf.logical_not(outside_ind)) 
    coord2_vec = tf.boolean_mask(coord2_vec, tf.logical_not(outside_ind)) 

coord_old_clipped = tf.cast(tf.transpose(tf.pack([coord_old1_clipped, coord_old2_clipped]), [1, 0]), tf.int32) 

# Coordinates of the new image 
coord_new = tf.transpose(tf.cast(tf.pack([coord1_vec, coord2_vec]), tf.int32), [1, 0]) 

image_channel_list = tf.split(2, s[2], image) 

image_rotated_channel_list = list() 
for image_channel in image_channel_list: 
    image_chan_new_values = tf.gather_nd(tf.squeeze(image_channel), coord_old_clipped) 

    if (mode == 'black') or (mode == 'repeat'): 
     background_color = 0 
    elif mode == 'ones': 
     background_color = 1 
    elif mode == 'white': 
     background_color = 255 

    image_rotated_channel_list.append(tf.sparse_to_dense(coord_new, [s[0], s[1]], image_chan_new_values, 
                 background_color, validate_indices=False)) 

image_rotated = tf.transpose(tf.pack(image_rotated_channel_list), [1, 2, 0]) 

return image_rotated 

bei der Umsetzung der oben genannten Codes, trete ich einen Fehler wie folgt. Wie löst man es? Vielen Dank! image_center = [np.floor (x/2) für x in s] TypeError: nicht unterstützte Operandentyp (en) für /: 'NoneType' und 'int'

Ich füttere Daten mit Hilfe der Eingabepipeline in den Graphen Methode. Beim Debuggen der Codes ist s = [None, None, 3]. Die URL des Quellcodes ist tensorflow: how to rotate an image for data augmentation?

Antwort

0

Ihr Eingang image ist höchstwahrscheinlich ein tf.placeholder mit variablen Abmessungen.

Zum Beispiel kann ein Bild mit undefinierter Höhe:

image = tf.placeholder(tf.float32, shape=[None, 365, 3])

Wenn Sie Ihr Diagramm zu bewerten, können Sie die tatsächlichen Abmessungen erhalten:

s = tf.shape(image) # Returns a Tensor, not a list image_center = tf.floor(s/2)

Sie nicht numpy verwenden können , da diese Berechnung als Teil des Graphen erfolgen muss.

Nebenbei sollten Sie tf.contrib.image.rotate jetzt verwenden.

Verwandte Themen