2016-02-04 16 views
5

Ich versuche einige Bildeingaben für ein Bildklassifikationsproblem mit TensorFlow zu lesen.TensorFlow Größe des Bildtensors auf dynamische Form

Natürlich mache ich das mit tf.image.decode_jpeg(...). Meine Bilder haben eine variable Größe und daher kann ich keine feste Form für den Bildtensor angeben.

Aber ich muss die Bilder abhängig von ihrer tatsächlichen Größe skalieren. Insbesondere möchte ich die kürzere Seite auf einen festen Wert und die längere Seite so skalieren, dass das Seitenverhältnis beibehalten wird.

Ich kann die tatsächliche Form eines bestimmten Bildes von shape = tf.shape(image) erhalten. Ich bin auch in der Lage, die Berechnung für die neue längere Kante zu tun wie

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) 

Mein Problem ist jetzt, dass ich nicht new_height und new_width zu tf.image.resize_images(...) passieren kann, weil einer von ihnen ein Tensor ist und resize_images erwartet ganzen Zahlen als Höhe und Breite Eingänge .

Gibt es eine Möglichkeit, die Ganzzahl des Tensors "herauszuziehen" oder gibt es eine andere Möglichkeit, meine Aufgabe mit TensorFlow zu erledigen?

Vielen Dank im Voraus.


bearbeiten

Da musste ich auch some other issues mit tf.image.resize_images, hier ist der Code, der für mich gearbeitet:

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]) 

Antwort

4

Die Art und Weise, dies zu tun, ist die (zur Zeit experimentell zu verwenden, aber verfügbar in der nächsten Version) tf.cond() * Betreiber. Dieser Operator ist in der Lage, einen zur Laufzeit berechneten Wert zu testen und basierend auf diesem Wert einen von zwei Zweigen auszuführen.

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) 

Jetzt haben Sie Tensor Werte für new_height und new_width, die den entsprechenden Wert zur Laufzeit stattfinden wird.

from tensorflow.python.ops import control_flow_ops 

... und dann control_flow_ops.cond() anstelle von tf.cond():


*   Um den Bediener in der aktuellen freigegebenen Version zugreifen, werden Sie die folgenden importieren müssen.

+0

Das ist sehr schön, coole Funktion. Aber mein Problem existiert immer noch. 'tf.image.resize_images (...)' nimmt ein 'int32' als zweites und drittes Argument. Hier sollten die Werte 'new_height' und' new_width' liegen. In meinem Verständnis von TensorFlow würde ein Aufruf von 'eval()' nicht funktionieren, da dies nur zur Laufzeit ausgewertet wird. Gibt es einen Befehl, der TensorFlow anweist, "die erste (und einzige) Ganzzahl des Tensors" zur Graphenaufbauzeit herauszuziehen? – mackcmillion

+0

Aufruf von 'tf.image.resize_images (image, new_height, new_width)' wirft immer 'TypeError: Expected int32, hat eine Liste mit Tensors vom Typ '_Message' statt. ' – mackcmillion

+0

Ah, das scheint mir ein Fehler zu sein. Ich habe [eine Ausgabe] eingereicht (https://github.com/tensorflow/tensorflow/issues/1001) und werde versuchen, bald eine Lösung zu finden. – mrry

Verwandte Themen