分類問題:
對於分類問題,raw為影象,label為數字,在這個例子中我的資料格式為:
共有12類,每個類有他自己的資料夾,也就是共12個資料夾,這十二個資料夾又都在image_set資料夾下,如圖:
大致思路為:獲取每個圖片的路徑及其label——>在for迴圈中開啟每個圖片並存儲進tfrecord中——>decode
第一部分
:獲取每個圖片的路徑及其對應的label:
def
get_file
(
file_dir
):
images
=
[]
temp
=
[]
labels
=
[]
i
=
0
for
root
,
dirs
,
files
in
os
。
walk
(
file_dir
):
for
name
in
files
:
images
。
append
(
os
。
path
。
join
(
root
,
name
))
#將路徑新增到images中 第一個E:\Lucas_up\Alexnet\image_set\ant
for
name
in
dirs
:
temp
。
append
(
os
。
path
。
join
(
root
,
name
))
#比image更下一層 第一個E:\Lucas_up\Alexnet\image_set\ant\image_0001。jpg
for
one_floder
in
temp
:
n_img
=
len
(
os
。
listdir
(
one_floder
))
#每一個類的圖片有多少張
labels
=
np
。
append
(
labels
,
n_img
*
[
i
])
#建立標籤矩陣:每一種圖片的數量n_img乘以矩陣[i]append到後面
i
=
i
+
1
temp
=
np
。
array
([
images
,
labels
])
#temp。shape = (2,711)
temp
=
temp
。
transpose
()
#轉置
np
。
random
。
shuffle
(
temp
)
#隨機,是真的可以隨機。。。
image_list
=
list
(
temp
[:,
0
])
#路徑
label_list
=
list
(
temp
[:,
1
])
#現在是一個list而不是矩陣#2。0 numpy。str
label_list
=
[
int
(
float
(
n
))
for
n
in
label_list
]
return
image_list
,
label_list
輸入為image_set的資料夾路徑,輸出為每張照片的路徑及其對應label:
data_dir = ‘E:\\Lucas_up\\Alexnet\\image_set’
image_dir,label = get_file(data_dir)
print(image_dir)
print(label)
如圖:
iamge_dir
label
第二部分
:生成tfrecord檔案
程式碼如下
def convert_to_tfrecord(images,labels,save_dir,name):
filename = os。path。join(save_dir,name + ‘。tfrecord’)
n_samples = len(labels)
if np。shape(images)[0] != n_samples:
raise ValueError(‘Image size %d does not match label size %d。’%(images。shape,n_samples。shape))
writer = tf。python_io。TFRecordWriter(filename)
print(‘\nTransform start。。。。’)
for i in np。arange(n_samples):
try:
image = Image。open(images[i])
image = image。resize((227,227))
image = np。array(image)
if image。shape != (227,227,3):
print(images[i])
print(labels[i])
#os。remove(images[i]) # 去除掉所有的非rgb圖
image_raw = image。tostring()
label = int(labels[i])
example = tf。train。Example(features = tf。train。Features(
feature = {“label”:tf。train。Feature(int64_list = tf。train。Int64List(value = [label])),
“img_raw”:tf。train。Feature(bytes_list = tf。train。BytesList(value = [image_raw]))}
))
writer。write(example。SerializeToString())
except IOError as e:
print(‘Could not read:’,images[i])
print(‘error : %s’ %e)
print(‘Skip it! \n’)
writer。close()
print(“Transform done!”)
這裡用Image。open讀取影象,需要 將其轉化成numpy陣列再轉為string最後寫入tfrecord,這個過程很麻煩而且生成的tfrecord檔案會很大,在下面分割問題中tfrecord的使用時會介紹一種新的方法。
第三部分
:讀取tfrecord檔案
程式碼如下:
def read_and_decode(tfrecords_file,batch_size):
filename_queue = tf。train。string_input_producer([tfrecords_file])
reader = tf。TFRecordReader()
_,serialized_example = reader。read(filename_queue)
img_features = tf。parse_single_example(serialized_example,
features={
‘label’:tf。FixedLenFeature([],tf。int64),
‘img_raw’:tf。FixedLenFeature([],tf。string),
})
image = tf。decode_raw(img_features[‘img_raw’],tf。uint8)
image = tf。reshape(image,[227,227,3])
image = tf。cast(image, tf。float32) * (1。 / 255) #在流中丟擲img張量
label = tf。cast(img_features[‘label’],tf。int32)
image_batch,label_batch = tf。train。batch([image,label],
batch_size=batch_size,
num_threads = 2,
capacity=32)
label_batch = tf。reshape(label_batch,[batch_size])
print(“Read tfrecord doc done!”)
return image_batch,label_batch
得到的image_batch,label_batch可以直接拿去用
測試:
這裡提供展示的程式碼:
BATCH_SIZE = 20
def plot_images(images,labels):
for i in np。arange(0,BATCH_SIZE):
plt。subplot(4,5,i + 1)
plt。axis(‘off’)
plt。title(labels[i],fontsize = 14)
plt。subplots_adjust(top = 1。5)
plt。imshow(images[i])
plt。show()
log_dir = ‘E:\\Lucas_up\\Alexnet\\tfrecord\\test。tfrecord’
image_batch,label_batch = read_and_decode(log_dir,BATCH_SIZE)
x = image_batch
in_channels = x。get_shape()[-1]
with tf。Session() as sess:
i = 0
coord = tf。train。Coordinator()
threads = tf。train。start_queue_runners(coord = coord)
try:
while not coord。should_stop() and i<1:
#just plot one batch size
image,label = sess。run([image_batch,label_batch])
#print(label。shape)
plot_images(image,label)
i = i+1
except tf。errors。OutOfRangeError:
print(‘done!’)
finally:
coord。request_stop()
coord。join(threads)
結果 如圖:
show
分割問題:
我做的是對於肝臟的分割,資料集是這樣的:
在bmp肝圖檔案中存放的是raw,在白色mask中存放的是label,與分類問題不同,分割問題的label是影象並非數字,同樣也分三個部分。
第一部分
:獲取每張影象的路徑,程式碼如下
def gen_road(raw_dir,target_dir):
raw = []
for root,dirs,files in os。walk(raw_dir):
for name in files:
raw。append(os。path。join(root,name))#將路徑新增到images中 第一個E:\Lucas_up\Alexnet\image_set\ant
target = []
for root,dirs,files in os。walk(target_dir):
for name in files:
target。append(os。path。join(root,name))
return raw,target
raw,target = gen_road(raw_dir,target_dir)
第二部分
:讀取每張圖片並寫入tfrecord,程式碼如下(未封裝):
def _bytes_feature(value,TFRECORD_PATH):
return tf。train。Feature(bytes_list=tf。train。BytesList(value=[value]))
writer = tf。python_io。TFRecordWriter(TFRECORD_PATH)
n_samples = len(raw)
print(n_samples)
for i in np。arange(n_samples):
img = tf。gfile。FastGFile(raw[i], ‘rb’)。read()
label = tf。gfile。FastGFile(target[i], ‘rb’)。read()
example = tf。train。Example(features=tf。train。Features(feature={
‘raw_image’: _bytes_feature(img,TFRECORD_PATH),
‘label’: _bytes_feature(label,TFRECORD_PATH)
}))
# 最後將example寫入TFRecord檔案
writer。write(example。SerializeToString())
writer。close()
在這裡,直接用tf。gfile。FastGFile讀取圖片,生成的record檔案相較於上一種方法要小。
第三部分
:讀取tfrecord檔案
def decode_and_gen_batch(BATCH_SIZE,TFRECORD_PATH):
# 1。 把所有的TFRecord檔名列表寫入佇列中(只有一個就寫一個檔名在列表中,多個就寫多個)
queue = tf。train。string_input_producer([TFRECORD_PATH], shuffle=True)
# 2。 建立一個讀取器
reader = tf。TFRecordReader()
# 3。 將佇列中的tfrecord檔案讀取為example格式
_, serialized_example = reader。read(queue)
# 4。 根據定義資料的方式對應說明讀取的方式
features = tf。parse_single_example(serialized_example,
features={
‘raw_image’: tf。FixedLenFeature([], tf。string),
‘label’: tf。FixedLenFeature([], tf。string)
})
img = features[‘raw_image’]
label = features[‘label’]
# 5。 對圖片進行解碼
img = tf。image。decode_bmp(img, channels=3)
label = tf。image。decode_bmp(label, channels=3)
img = tf。reshape(img,[512,512,3])
label = tf。reshape(label,[512,512,3])
# 然後就可以用tf。train。batch方法來生成一個batch的image和label啦
image_batch,label_batch = tf。train。batch([img,label],
batch_size=50,
num_threads = 2,
capacity=32)
return image_batch,label_batch
因為我的所有影象都是bmp格式的,所以用tf。image。decode_bmp解碼,解碼之後千萬要reshape[512,512,3],不然會報錯:
All shapes must be fully defined: [TensorShape([Dimension(None), Dimension(None), Dimension(3)]), TensorShape([Dimension(None), Dimension(None), Dimension(3)])]
測試
:
image_batch,label_batch = decode_and_gen_batch(BATCH_SIZE,TFRECORD_PATH)
with tf。Session() as sess:
i = 0
coord = tf。train。Coordinator()
threads = tf。train。start_queue_runners(coord = coord)
image,label = sess。run([image_batch,label_batch])
plt。figure(1)
plt。imshow(image[25])
plt。figure(2)
plt。imshow(label[25])
結果如圖:
以上就是tfrecord在分類與分割問題中的使用方法。
參考: