2016-02-04 14 views
5

Sto cercando di leggere alcuni input di immagini per un problema di classificazione delle immagini con TensorFlow.TensorFlow Ridimensiona il tensore dell'immagine in forma dinamica

Naturalmente, lo sto facendo con tf.image.decode_jpeg(...). Le mie immagini hanno dimensioni variabili e quindi non sono in grado di specificare una forma fissa per il tensore dell'immagine.

Ma ho bisogno di ridimensionare le immagini in base alla loro dimensione effettiva. Nello specifico, voglio ridimensionare il lato più corto a un valore fisso e il lato più lungo in modo da preservare le proporzioni.

È possibile ottenere la forma effettiva di una determinata immagine tramite shape = tf.shape(image). Sono anche in grado di fare il calcolo per il nuovo bordo più come

shape = tf.shape(image) 
height = shape[0] 
width = shape[1] 
new_shorter_edge = 400 
if height <= width: 
    new_height = new_shorter_edge 
    new_width = ((width/height) * new_shorter_edge) 
else: 
    new_width = new_shorter_edge 
    new_height = ((height/width) * new_shorter_edge) 

mio problema ora è che non riesco a passare new_height e new_width a tf.image.resize_images(...) perché uno di loro è un tensore e resize_images aspetta interi come altezza e gli ingressi di larghezza .

C'è un modo per "estrarre" il numero intero del tensore o esiste un altro modo per eseguire il mio compito con TensorFlow?

Grazie in anticipo.


Modifica

Da quando ho avuto anche some other issues con tf.image.resize_images, ecco il codice che ha funzionato per me:

shape = tf.shape(image) 
height = shape[0] 
width = shape[1] 
new_shorter_edge = tf.constant(400, dtype=tf.int32) 

height_smaller_than_width = tf.less_equal(height, width) 
new_height_and_width = tf.cond(
    height_smaller_than_width, 
    lambda: (new_shorter_edge, _compute_longer_edge(height, width, new_shorter_edge)), 
    lambda: (_compute_longer_edge(width, height, new_shorter_edge), new_shorter_edge) 
) 

image = tf.expand_dims(image, 0) 
image = tf.image.resize_bilinear(image, tf.pack(new_height_and_width)) 
image = tf.squeeze(image, [0]) 

risposta

4

Il modo per farlo è quello di utilizzare il (attualmente sperimentale, ma disponibile nella prossima versione) tf.cond() * operator. Questo operatore è in grado di testare un valore calcolato in fase di esecuzione ed eseguire uno dei due rami in base a tale valore.

shape = tf.shape(image) 
height = shape[0] 
width = shape[1] 
new_shorter_edge = 400 
height_smaller_than_width = tf.less_equal(height, width) 

new_shorter_edge = tf.constant(400) 
new_height, new_width = tf.cond(
    height_smaller_than_width, 
    lambda: new_shorter_edge, (width/height) * new_shorter_edge, 
    lambda: new_shorter_edge, (height/width) * new_shorter_edge) 

Ora avete Tensor valori per new_height e new_width che prenderanno il valore appropriato in fase di esecuzione.


*   Per accedere l'operatore nella versione attuale rilasciata, è necessario importare i seguenti:

from tensorflow.python.ops import control_flow_ops 

... e quindi utilizzare control_flow_ops.cond() invece di tf.cond().

+0

Questa è una funzionalità molto bella e interessante. Ma il mio problema esiste ancora. 'tf.image.resize_images (...)' prende un 'int32' come secondo e terzo argomento. Ecco dove dovrebbero andare i valori di 'new_height' e' new_width'. Nella mia comprensione di TensorFlow, una chiamata a 'eval()' non funzionava perché questo è valutato solo in fase di esecuzione. C'è qualche comando che dice a TensorFlow di "estrarre il primo (e unico) intero del Tensore" al momento della costruzione del grafico? – mackcmillion

+0

Chiamando 'tf.image.resize_images (image, new_height, new_width)' getta sempre 'TypeError: Exp32 intic, ha ottenuto la lista contenente Tensors di tipo '_Message' invece. – mackcmillion

+0

Ah, questo mi sembra un bug. Ho archiviato [un problema] (https://github.com/tensorflow/tensorflow/issues/1001) e proverò a ottenere una soluzione a breve. – mrry