2016-01-14 41 views
9

我刚开始使用Tensorflow,我有一个新手问题。在Tensorflow中保存图像文件

我知道Tensorflow是所有关于神经网络,但我开始只是它的机制。我试图让它加载,调整大小,翻转并保存两个图像。应该是一个简单的操作,对,并且让我从基础开始。

这里是我到目前为止的代码:

import tensorflow as tf 
import numpy as np 

print("resizing images") 

filenames = ['img1.png', 'img2.png' ] 
filename_queue = tf.train.string_input_producer(filenames, num_epochs=1) 

reader = tf.WholeFileReader() 
key,value = reader.read(filename_queue) 
images = tf.image.decode_png(value) 

resized = tf.image.resize_images(images, 180,180, 1) 
resized.set_shape([180,180,3]) 

flipped_images = tf.image.flip_up_down(resized) 

resized_encoded = tf.image.encode_jpeg(flipped_images,name="save_me") 

init = tf.initialize_all_variables() 
sess = tf.Session() 

with sess.as_default(): 
    tf.train.start_queue_runners() 
    sess.run(init) 

    f = open("/tmp/foo1.jpeg", "wb+") 
    f.write(resized_encoded.eval()) 
    f.close() 

    f = open("/tmp/foo2.jpeg", "wb+") 
    f.write(resized_encoded.eval()) 
    f.close() 

它工作正常,调整两个图像,并将其保存。但它总是以一个错误结束:

W tensorflow/core/common_runtime/executor.cc:1076] 0x7f97240e7a40 
Compute status: Out of range: Reached limit of 1 

我明显做错了事。如果我取消num_epochs = 1,那么它以无错误结束。

我有几个问题:

如何正确地做到这一点?

另外,如果我想通过保留原始文件名从filename_queue一路到底,所以我可以用原来的名称保存它们,我该怎么做呢?我怎么知道我需要保存多少个文件?假设我正在通过读取目录来创建文件名列表。我尝试了很多不同的东西,但是当我到达最后时,我无法知道我的知识。

我觉得奇怪,我说我打电话resized_encoded.eval()的两倍。

谢谢你,我敢肯定,这是一个非常基本的问题,但我不明白这是如何工作。

编辑:我创建了行为的一个更简单的演示:

import tensorflow as tf 
import numpy as np 

filenames = ['file1.png', 'file2.png' ] 

filename_queue = tf.train.string_input_producer(filenames, 
         num_epochs=1, name="my_file_q") 

reader = tf.WholeFileReader() 
key,value = reader.read(filename_queue) 
init = tf.initialize_all_variables() 

sess = tf.Session() 

with sess.as_default(): 
    print("session started") 

    sess.run(init) 

    coord = tf.train.Coordinator() 
    threads = tf.train.start_queue_runners(coord=coord) 

    for i in range (2): 
    print(key.eval()) 

    coord.request_stop() 
    coord.join(threads) 

这给出了同样的警告。我不明白为什么。

回答

5

这个警告是完全正常的。如TensorFlow API中所述

num_epochs: An integer (optional). If specified, string_input_producer produces each string from string_tensor num_epochs times before generating an OutOfRange error. If not specified, string_input_producer can cycle through the strings in string_tensor an unlimited number of times.

为什么这很重要,你可能会问。在我看来,我已经将你的代码重构成了可能更容易理解的东西。让我解释。

import tensorflow as tf 
import numpy as np 
import os 
from PIL import Image 

cur_dir = os.getcwd() 
print("resizing images") 
print("current directory:",cur_dir) 

def modify_image(image): 
    resized = tf.image.resize_images(image, 180, 180, 1) 
    resized.set_shape([180,180,3]) 
    flipped_images = tf.image.flip_up_down(resized) 
    return flipped_images 

def read_image(filename_queue): 
    reader = tf.WholeFileReader() 
    key,value = reader.read(filename_queue) 
    image = tf.image.decode_jpeg(value) 
    return image 

def inputs(): 
    filenames = ['img1.jpg', 'img2.jpg' ] 
    filename_queue = tf.train.string_input_producer(filenames,num_epochs=2) 
    read_input = read_image(filename_queue) 
    reshaped_image = modify_image(read_input) 
    return reshaped_image 

with tf.Graph().as_default(): 
    image = inputs() 
    init = tf.initialize_all_variables() 
    sess = tf.Session() 
    sess.run(init) 
    tf.train.start_queue_runners(sess=sess) 
    for i in xrange(2): 
     img = sess.run(image) 
     img = Image.fromarray(img, "RGB") 
     img.save(os.path.join(cur_dir,"foo"+str(i)+".jpeg")) 

在上面的代码,如果明确提出num_epochs = 2,则作为API表明,通过string_tensor琴弦2倍string_input_producer周期。由于string_tensor只有2个文件名,队列中有4个文件名。如果我将for循环更改为:

for i in xrange(5) 

然后这会出错。但是,如果我把它放在4,那么它会没事的。再举一个例子。如果我不把num_epochs,那么如所建议的那样,它可以循环无限次数。推荐:

for i in xrange(100) 

因此不会出错。我希望这回答了你的问题。

编辑:我意识到你有更多的问题。

Also, if I want to preserve the original file names all the way from the filename_queue through to the end so I can save them with the original names, how do I do that? And how do I know how many files I need to save? Let's say I'm making the list of file names by reading a directory. I tried many different things but I could never find out how I know when I reach the end.

如果您想保留原始文件名,那么您的方法需要返回文件名。以下是代码。

import tensorflow as tf 
import numpy as np 
import os 
from PIL import Image 

cur_dir = os.getcwd() 
print("resizing images") 
print("current directory:",cur_dir) 

def modify_image(image): 
    resized = tf.image.resize_images(image, 180, 180, 1) 
    resized.set_shape([180,180,3]) 
    flipped_images = tf.image.flip_up_down(resized) 
    return flipped_images 

def read_image(filename_queue): 
    reader = tf.WholeFileReader() 
    key,value = reader.read(filename_queue) 
    image = tf.image.decode_jpeg(value) 
    return key,image 

def inputs(): 
    filenames = ['img1.jpg', 'img2.jpg' ] 
    filename_queue = tf.train.string_input_producer(filenames) 
    filename,read_input = read_image(filename_queue) 
    reshaped_image = modify_image(read_input) 
    return filename,reshaped_image 

with tf.Graph().as_default(): 
    image = inputs() 
    init = tf.initialize_all_variables() 
    sess = tf.Session() 
    sess.run(init) 
    tf.train.start_queue_runners(sess=sess) 
    for i in xrange(10): 
     filename,img = sess.run(image) 
     print (filename) 
     img = Image.fromarray(img, "RGB") 
     img.save(os.path.join(cur_dir,"foo"+str(i)+".jpeg")) 

要知道你需要多少文件保存,你可以只调用沿着线的东西:

os.listdir(os.getcwd()) 

此列出目录中的所有文件。检查os.listdir的API以过滤特定的JPG,PNG文件类型。一旦你得到这个,你可以调用一个简单的长度操作,并做:

for i in xrange(len(number_of_elements))