Harald
Harald

Reputation: 546

Tensorflow: Dynamically Splitting Images into Pieces

Im new to tensorflow and need help in managing my image dataset. Since the image set is huge the reading and training phases should overlap. Each image has also way more pixels in its width than in its height. I need to split the wide image into square parts. Since the width of the image varies, also the amount of parts will change.

It follows my example code, where I need help in getting it to work:

def main(unused_argv):
   filenames = tf.constant(['im_01.png', 'im_02.png', 'im_03.png', 'im_04.png'])
   labels = tf.constant([0, 1, 0, 1])

   def parse_fn(file, label):
      image = tf.image.decode_png(tf.read_file(file), channels=1)

       shape_list = image.get_shape().as_list()
       image_width = shape_list[0]
       image_height = shape_list[1]
       num_pieces = int(image_width/image_height)

       Xy_pairs = []
       for i in range(num_pieces):
          offset_width = i * image_height
          sub_image = tf.image.crop_to_bounding_box(image, 0, offset_width, image_height, image_height)
          sub_image = tf.image.resize_images(sub_image, [128, 128])
          Xy_pairs.append((sub_image, label))

       return Dataset.from_tensor_slices(Xy_pairs)


dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))
dataset = dataset.flat_map(parse_fn)

sess = tf.InteractiveSession()
it = dataset.make_one_shot_iterator()
while True:
    print('OUT: ' + it.get_next().eval())

The error looks like this TypeError: unsupported operand type(s) for /: 'NoneType' and 'NoneType' since tensorflow does not know the size of the images while computing the dataflow graph. Im pretty sure I need something like a placeholder for image.get_shape(). I hope the community can help me with this.

Upvotes: 4

Views: 1261

Answers (1)

benjaminplanche
benjaminplanche

Reputation: 15119

As pointed out in comments, your image shape is left undefined in the graph, so trying to get the values before evaluation (through image.get_shape().as_list()) returns you (None, None, None).

To have everything dynamic in the graph, you could use tf.while_loop() instead of your current for loop to extract the patches, as shown below (this code may need some tweaking):

import tensorflow as tf

filenames = tf.constant(['im_01.png', 'im_02.png', 'im_03.png', 'im_04.png'])
labels = tf.constant([0, 1, 0, 1])
patch_size = [128, 128]

def parse_fn(file, label):
    image = tf.image.decode_png(tf.read_file(file), channels=1)

    shape= tf.shape(image)
    image_width = shape[1]
    image_height = shape[0]
    num_pieces = tf.div(image_width, image_height)

    def tf_while_condition(index, outputs):
        # We loop over the number of pieces:
        return tf.less(index, num_pieces)

    def tf_while_body(index, outputs):
        # We get the image patch for the given index:
        offset_width = index * image_height
        sub_image = tf.image.crop_to_bounding_box(image, 0, offset_width, image_height, image_height)
        sub_image = tf.image.resize_images(sub_image, patch_size)
        sub_image = tf.expand_dims(sub_image, 0)
        # We add it to the output patches (may be a cleaner way to do so):
        outputs = tf.concat([outputs[:index], sub_image, outputs[index + 1:]], axis=0)
        # We increment our index and return the values:
        index = tf.add(index, 1)
        return index, outputs

    # We build our patches tensor which will be filled with the loop:
    patches = tf.zeros((num_pieces, *patch_size, shape[2]), dtype=tf.float32)
    _, patches = tf.while_loop(tf_while_condition, tf_while_body, [0, patches])

    # We tile the label to have one per patch:
    patches_labels = tf.tile(tf.expand_dims(label, 0), [num_pieces])

    return tf.data.Dataset.from_tensor_slices((patches, patches_labels))

dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))
dataset = dataset.flat_map(parse_fn)

sess = tf.InteractiveSession()
it = dataset.make_one_shot_iterator()
op = it.get_next()
while True:
    res = sess.run(op)
    print(res)

Upvotes: 2

Related Questions