2016-01-27 15 views
5

Ho creato un set di dati e l'ho salvato in un file TFRecord. Il fatto è che le immagini hanno dimensioni diverse, quindi voglio salvare anche le dimensioni con le immagini. Così ho usato il TFRecordWriter e definito le caratteristiche come:Come leggere le immagini con dimensioni diverse in un file TFRecord

example = tf.train.Example(features=tf.train.Features(feature={ 
    'rows': _int64_feature(image.shape[0]), 
    'cols': _int64_feature(image.shape[1]), 
    'image_raw': _bytes_feature(image_raw)})) 

mi aspettavo che posso leggere e decodificare l'immagine utilizzando TFRecordReader, ma la cosa è che non posso ottenere il valore di righe e colonne dal file perché sono tensori. Quindi, come dovrei fare per leggere le dimensioni dinamicamente e rimodellare l'immagine di conseguenza. Grazie ragazzi

risposta

2

È possibile chiamare tf.reshape con un parametro dinamico shape.

image_rows = tf.cast(features['rows'], tf.int32) 
image_cols = tf.cast(features['cols'], tf.int32) 
image_data = tf.decode_raw(features['image_raw'], tf.uint8) 
image = tf.reshape(image_data, tf.pack([image_rows, image_cols, 3])) 
+0

ha generato l'errore "Tutte le forme devono essere completamente definite: 1". dal log, sembra che abbia qualcosa a che fare con la funzione "tf.train.shuffle_batch()". Cosa dovrei fare allora? –

+0

batch ha bisogno di conoscere le forme durante la costruzione del grafico (in modo da sapere quanta memoria allocare per la coda), forse usare tf.image.resize_images prima di tf.batch? Se si utilizza uno dei convnets standard, sarà necessario ridimensionare le immagini alla stessa dimensione in ogni caso –

+0

+ Tong Shen, dal momento che si sta costruendo un batch, le immagini devono avere la stessa dimensione. Se conosci questa dimensione in anticipo, potresti chiamare qualcosa come 'image.set_shape ([32,32,3])' per definire completamente la forma. – bgshi

2

suggerisco un flusso di lavoro come:

TARGET_HEIGHT = 500 
TARGET_WIDTH = 500 

image = tf.image.decode_jpeg(image_buffer, channels=3) 
image = tf.image.convert_image_dtype(image, dtype=tf.float32) 

# Choose your bbox here. 
bbox_begin = ... (should be (h_start, w_start, 0)) 
bbox_size = tf.constant((TARGET_HEIGHT, TARGET_WIDTH, 3), dtype=tf.int32) 

cropped_image = tf.slice(image, bbox_begin, bbox_size) 

cropped_image ha una dimensione tensore costante, e possono poi essere gettati in un lotto shuffle.

È possibile accedere in modo dinamico alle dimensioni dell'immagine decodificata utilizzando tf.shape(image). È possibile eseguire calcoli sugli elementi secondari risultanti e quindi ricollegarli utilizzando qualcosa come bbox_begin = tf.pack([bbox_h_start, bbox_y_start, 0]). Basta inserire la propria logica per determinare i punti iniziali del ritaglio e cosa si vuole fare se l'immagine inizia più piccola di quanto si desidera per la propria pipeline.

Se si desidera eseguire l'upsize solo se l'immagine è più piccola vostre dimensioni di destinazione, è necessario utilizzare tf.control_flow_ops.cond o equivalente. Ma tu potresti usare le operazioni min e max per impostare la dimensione della finestra di ritaglio in modo da restituire l'intera immagine se è inferiore alle dimensioni richieste e ridimensionare incondizionatamente fino a 500x500. L'immagine ritagliata sarà già a 500x500, quindi il ridimensionamento dovrebbe diventare un no-op efficace.

+0

questo flusso di lavoro sta funzionando con la coda di file FIFO? Ora la cosa è che voglio ritagliare in modo casuale l'immagine usando 500 * 500, la tua strada sembra ritagliare una regione fissa. Ora ho ridimensionato le immagini in anticipo in modo che la dimensione minima sia uguale o superiore a 500. L'unica cosa che sto affrontando è come decodificare l'immagine dalla stringa raw e ridisegnarla alla sua dimensione originale. Poiché il peso e l'altezza variano nelle immagini, non possiamo usare una dimensione fissa. –

+0

Giusto, devi selezionare in modo casuale l'inizio del bbox 500x500. Impostando bbox_size su [500, 500, 3] (il 3 è per il numero di canali), otterrai un ritaglio 500x500. Devi impostare i punti iniziali per il tuo raccolto casuale, a seconda dell'algoritmo di coltivazione casuale preferito. Dato che hai ridimensionato, potresti semplicemente fare 'imageshape = tf.shape (image)' e quindi impostare l'inizio, i punti finali come: 'h_start = tf.random_uniform ([], minval = 0, maxval = imageshape [0 ] -500, dtype = tf.int32) 'e allo stesso modo per w_start. – dga