圖像基本概念
在圖像數字化表示當中,分為黑白和彩色兩種。在數字化表示圖片的時候,有三個因素。分別是圖片的長、圖片的寬、圖片的顏色通道數。那么黑白圖片的顏色通道數為1,它只需要一個數字就可以表示一個像素位;而彩色照片就不一樣了,它有三個顏色通道,分別為RGB,通過三個數字表示一個像素位。TensorFlow支持JPG、PNG圖像格式,RGB、RGBA顏色空間。圖像用與圖像尺寸相同(height*width*chnanel)張量表示。圖像所有像素存在磁盤文件,需要被加載到內存。
圖像基本操作
目的:
- 增加圖片數據的統一性
- 所有圖片轉換成指定大小
- 縮小圖片數據量,防止增加開銷
操作:
- 縮小圖片大小
圖像基本操作API
tf.image.resize_images(images, size):縮小圖片
- images:4-D形狀[batch, height, width, channels]或3-D形狀的張量[height, width, channels]的圖片數據
- size:1-D int32張量:new_height, new_width,圖像的新尺寸
- 返回4-D格式或者3-D格式圖片
圖像讀取API
圖像讀取器:
tf.WholeFileReader:將文件的全部內容作為值輸出的讀取器
- return:讀取器實例
- read(file_queue):輸出將是一個文件名(key)和該文件的內容(值)
圖像解碼器:
tf.image.decode_jpeg(contents):將JPEG編碼的圖像解碼為uint8張量
- return:uint8張量,3-D形狀[height, width, channels]
tf.image.decode_png(contents):將PNG編碼的圖像解碼為uint8或uint16張量
- return:張量類型,3-D形狀[height, width, channels]
狗圖片讀取
import tensorflow as tf
import os
def readpic(filelist):
"""
狗圖片讀取
"""
# 構建文件隊列
file_queue = tf.train.string_input_producer(filelist)
# 構造閱讀器
reader = tf.WholeFileReader()
key, value = reader.read(file_queue)
print(value)
# 對讀取到的圖片進行解碼
image = tf.image.decode_jpeg(value)
print(image)
# 處理圖片的大小
img_resize = tf.image.resize_images(image, [250, 250])
print(img_resize)
img_resize.set_shape([250, 250, 3])
# 批處理
image_batch = tf.train.batch([img_resize], batch_size=10, num_threads=1, capacity=10)
print(image_batch)
return image_batch
if __name__ == '__main__':
filelist = os.listdir("./data/dogs")
filelist = ["./data/dogs/{}".format(i) for i in filelist]
image_batch = readpic(filelist)
with tf.Session() as sess:
# 線程協調器
coord = tf.train.Coordinator()
# 開啟讀取文件線程
threads = tf.train.start_queue_runners(sess, coord=coord)
# 打印數據
print(sess.run([image_batch]))
coord.request_stop()
coord.join()
案例流程:
- 構造圖片文件隊列
- 構造閱讀器
- 讀取圖片數據
- 處理圖片數據
CIFAR-10二進制數據讀取
網站:https://www.cs.toronto.edu/~kriz/cifar.html
import tensorflow as tf
import os
# 定義cifar命令相關參數
tf.app.flags.DEFINE_string("cifar_dir", "./data/cifar-10-batches-bin", "cifar目錄")
FLAGS = tf.app.flags.FLAGS
class CifarReader(object):
"""
讀取二進制文件,寫入tfrecords,讀取tfrecords
"""
def __init__(self, filelist):
self.filelist = filelist
# 定義讀取的二進制圖片的一些屬性
self.width = 32
self.height = 32
self.channel = 3
self.label_bytes = 1
self.image_bytes = self.width * self.height * self.channel
self.bytes = self.label_bytes + self.image_bytes
def read_and_decode(self):
# 構造文件隊列
file_queue = tf.train.string_input_producer(self.filelist)
# 構造二進制文件閱讀器
reader = tf.FixedLengthRecordReader(self.bytes)
key, value = reader.read(file_queue)
# 解碼
label_image = tf.decode_raw(value, tf.uint8)
print(label_image)
# 分離出圖片和標簽數據
label = tf.cast(tf.slice(label_image, [0], [self.label_bytes]), tf.int32)
image = tf.slice(label_image, [self.label_bytes], [self.image_bytes])
# 改變圖片的形狀 [3072] -> [32, 32, 3]
image_reshape = tf.reshape(image, [self.height, self.width, self.channel])
print(label, image_reshape)
# 批處理數據
label_batch, image_batch = tf.train.batch([label, image_reshape], batch_size=20, num_threads=1, capacity=20)
print(label_batch, image_batch)
return label_batch, image_batch
if __name__ == '__main__':
filelist = os.listdir(FLAGS.cifar_dir)
filelist = [os.path.join(FLAGS.cifar_dir, i) for i in filelist if i.endswith(".bin")]
cf = CifarReader(filelist)
label_batch, image_batch = cf.read_and_decode()
with tf.Session() as sess:
# 線程協調器
coord = tf.train.Coordinator()
# 開啟讀取文件線程
threads = tf.train.start_queue_runners(sess, coord=coord)
# 打印數據
print(sess.run([label_batch, image_batch]))
coord.request_stop()
coord.join()
TFRecords
TFRecords是Tensorflow設計的一種內置文件格式,是一種二進制文件,它能更好的利用內存,更方便復制和移動。為了將二進制數據和標簽(訓練的類別標簽)數據存儲在同一個文件中。
TFRecords存儲
- 建立TFRecord存儲器:tf.python_io.TFRecordWriter(path)
- path: TFRecords文件的路徑
- return:寫文件
- 方法:
- write(record):向文件中寫入一個字符串記錄
- close():關閉文件寫入器
- 注:字符串是一個序列化的Example:Example.SerializeToString()
- 構造每個樣本的Example協議塊
- tf.train.Example(features=None)
- 寫入tfrecords文件
- features:tf.train.Features類型的特征實例
- return:example格式協議塊
- tf.train.Features(feature=None)
- 構建每個樣本的信息鍵值對
- features:字典數據,key為要保存的名字,value為tf.train.Feature實例
- return:Features類型
- tf.train.Feature(**options)
- **options:例如:
bytes_list=tf.train. BytesList(value=[Bytes])
int64_list=tf.train. Int64List(value=[Value])
- **options:例如:
- tf.train.Example(features=None)
對於上例中【CIFAR-10二進制數據讀取】讀取到的數據進行存儲:
import tensorflow as tf
import os
# 定義cifar命令相關參數
tf.app.flags.DEFINE_string("cifar_dir", "./data/cifar-10-batches-bin", "cifar目錄")
tf.app.flags.DEFINE_string("cifar_tfrecords", "./temp/cifar.tfrecords", "保存的tfrecords文件路徑")
FLAGS = tf.app.flags.FLAGS
class CifarReader(object):
"""
讀取二進制文件,寫入tfrecords,讀取tfrecords
"""
def __init__(self, filelist):
self.filelist = filelist
# 定義讀取的二進制圖片的一些屬性
self.width = 32
self.height = 32
self.channel = 3
self.label_bytes = 1
self.image_bytes = self.width * self.height * self.channel
self.bytes = self.label_bytes + self.image_bytes
def read_and_decode(self):
# 構造文件隊列
file_queue = tf.train.string_input_producer(self.filelist)
# 構造二進制文件閱讀器
reader = tf.FixedLengthRecordReader(self.bytes)
key, value = reader.read(file_queue)
# 解碼
label_image = tf.decode_raw(value, tf.uint8)
print(label_image)
# 分離出圖片和標簽數據
label = tf.cast(tf.slice(label_image, [0], [self.label_bytes]), tf.int32)
image = tf.slice(label_image, [self.label_bytes], [self.image_bytes])
# 改變圖片的形狀 [3072] -> [32, 32, 3]
image_reshape = tf.reshape(image, [self.height, self.width, self.channel])
print(label, image_reshape)
# 批處理數據
label_batch, image_batch = tf.train.batch([label, image_reshape], batch_size=20, num_threads=1, capacity=20)
print(label_batch, image_batch)
return label_batch, image_batch
def write_to_tfrecords(self, label_batch, image_batch):
"""
存儲圖片的目標值和特征值
:param label_batch: 圖片的目標值
:param image_batch: 圖片的特征值
:return: None
"""
# 建立tfrecords存儲器
writer = tf.python_io.TFRecordWriter(FLAGS.cifar_tfrecords)
# 將所有樣本寫入文件
for i in range(label_batch.shape[0]):
label = int(label_batch[i].eval()[0])
image = image_batch[i].eval().tostring()
example = tf.train.Example(features=tf.train.Features(feature={
"label": tf.train.Feature(int64_list=tf.train.Int64List(value=[label])),
"image": tf.train.Feature(bytes_list=tf.train.BytesList(value=[image]))
}))
writer.write(example.SerializeToString())
writer.close()
if __name__ == '__main__':
filelist = os.listdir(FLAGS.cifar_dir)
filelist = [os.path.join(FLAGS.cifar_dir, i) for i in filelist if i.endswith(".bin")]
cf = CifarReader(filelist)
label_batch, image_batch = cf.read_and_decode()
with tf.Session() as sess:
# 線程協調器
coord = tf.train.Coordinator()
# 開啟讀取文件線程
threads = tf.train.start_queue_runners(sess, coord=coord)
# 存為tfrecords文件
cf.write_to_tfrecords(label_batch, image_batch)
# 打印數據
print(sess.run([label_batch, image_batch]))
coord.request_stop()
coord.join()
TFRecords讀取方法
同文件閱讀器流程,中間需要解析過程
解析TFRecords的example協議內存塊:
- tf.parse_single_example(serialized,features=None,name=None)
- 解析一個單一的Example原型
- serialized:標量字符串Tensor,一個序列化的Example
- features:dict字典數據,鍵為讀取的名字,值為FixedLenFeature
- return:一個鍵值對組成的字典,鍵為讀取的名字
- tf.FixedLenFeature(shape,dtype)
- shape:輸入數據的形狀,一般不指定,為空列表
- dtype:輸入數據類型,與存儲進文件的類型要一致,類型只能是float32,int64,string
讀取上例保存的tfrecords文件:
# 定義cifar命令相關參數
tf.app.flags.DEFINE_string("cifar_dir", "./data/cifar-10-batches-bin", "cifar目錄")
tf.app.flags.DEFINE_string("cifar_tfrecords", "./temp/cifar.tfrecords", "保存的tfrecords文件路徑")
FLAGS = tf.app.flags.FLAGS
class CifarReader(object):
"""
讀取二進制文件,寫入tfrecords,讀取tfrecords
"""
def __init__(self, filelist):
self.filelist = filelist
# 定義讀取的二進制圖片的一些屬性
self.width = 32
self.height = 32
self.channel = 3
self.label_bytes = 1
self.image_bytes = self.width * self.height * self.channel
self.bytes = self.label_bytes + self.image_bytes
def read_from_cfrecords(self):
"""
讀取cfrecords
:return: None
"""
# 構建文件隊列
file_queue = tf.train.string_input_producer([FLAGS.cifar_tfrecords])
# 構建文件閱讀器
reader = tf.TFRecordReader()
key, value = reader.read(file_queue)
# 解析example
features = tf.parse_single_example(value, features={
"label": tf.FixedLenFeature([], tf.int64),
"image": tf.FixedLenFeature([], tf.string)
})
# 解碼
image = tf.decode_raw(features["image"], tf.uint8)
image_reshape = tf.reshape(image, [self.height, self.width, self.channel])
label = tf.cast(features["label"], tf.int32)
print(label, image_reshape)
# 批處理
label_batch, image_batch = tf.train.batch([label, image_reshape], batch_size=20, num_threads=1, capacity=20)
print(label_batch, image_reshape)
return label_batch, image_reshape
if __name__ == '__main__':
label_batch, image_batch = cf.read_from_cfrecords()
with tf.Session() as sess:
# 線程協調器
coord = tf.train.Coordinator()
# 開啟讀取文件線程
threads = tf.train.start_queue_runners(sess, coord=coord)
# 打印數據
print(sess.run([label_batch, image_batch]))
coord.request_stop()
coord.join()