glob的使用

import glob

1
2
3
4
5
6
7
8
9
10
all_image_path = glob.glob('./*/*jpg')		#将遍历该文件夹下的所有文件夹中的以.jpg结尾的文件

all_image_path
['.\\airplane\\airplane_632.jpg',
'.\\lake\\lake_056.jpg',
'.\\lake\\lake_584.jpg',
'.\\lake\\lake_334.jpg',
'.\\airplane\\airplane_684.jpg',
'.\\airplane\\airplane_079.jpg',
'.\\airplane\\airplane_294.jpg']

图片位置的乱序

1
2
3
#做乱序,shuffle
import random
random.shuffle(all_image_path)

图片 Label与Index直接转换

1
2
label_to_index = {'airplane':0,'lake':1}    #label -> index
index_to_label = dict((v,k) for k,v in label_to_index.items()) #index -> label

将所有图片label转index

1
all_labels = [label_to_index.get(img.split('\\')[1]) for img in all_image_path]

读取图片

1
2
3
4
5
6
7
8
9
10
img = all_image_path[100]
img_raw = tf.io.read_file(img)#以二进制读入
img_tensor = tf.image.decode_jpeg(img_raw)#解码
plt.imshow(img_tensor) #输出图片
## tensorflow 中转换数据类型用tf.cast
#### uint类型对于模型预测是不适用的,要转化成float类型
img_tensor.shape,img_tensor.dtype#uint8 表示无符号整型,0~255
img_tensor = tf.cast(img_tensor,tf.float32)
img_tensor.dtype #查看类型
img_tensor = img_tensor / 255 #归一化

==整合==

1
2
3
4
5
6
7
def load_img(path):
img_raw = tf.io.read_file(path)#读取
img_tensor = tf.image.decode_jpeg(img_raw,channels=3)#解码
img_tensor = tf.image.resize(img_tensor,[256,256])#图片resize
img_tensor = tf.cast(img_tensor,tf.float32)
img_tensor = img_tensor / 255
return img_tensor

图片Dataset

1
2
img_ds = tf.data.Dataset.from_tensor_slices(all_image_path)
img_ds = img_ds.map(load_img)#map接收一个函数,Dataset中的每个元素都会被当作这个函数的输入,并将函数返回值作为新的Dataset

标签Dataset

1
label_ds = tf.data.Dataset.from_tensor_slices(all_labels)

图片和标签对应Dataset

1
img_label_ds = tf.data.Dataset.zip((img_ds,label_ds))#二合一

分配训练和测试

1
2
3
4
5
6
7
8
# 分配训练和测试
test_count = int(image_count*0.2)
train_count = image_count - test_count
train_ds = img_label_ds.skip(test_count)#跳过test_count张图
test_ds = img_label_ds.take(test_count)#从前取test_count张
BATCH_SIZE = 16
train_ds = train_ds.repeat().shuffle(100).batch(BATCH_SIZE)
test_ds = test_ds.batch(BATCH_SIZE)

模型的创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
model = tf.keras.Sequential()
model.add(tf.keras.layers.Conv2D(64,(3,3),input_shape=(256,256,3),
activation='relu'))
model.add(tf.keras.layers.Conv2D(64,(3,3),activation='relu'))
model.add(tf.keras.layers.MaxPool2D())
model.add(tf.keras.layers.Conv2D(128,(3,3),activation='relu'))
model.add(tf.keras.layers.Conv2D(128,(3,3),activation='relu'))
model.add(tf.keras.layers.MaxPool2D())
model.add(tf.keras.layers.Conv2D(256,(3,3),activation='relu'))
model.add(tf.keras.layers.Conv2D(256,(3,3),activation='relu'))
model.add(tf.keras.layers.MaxPool2D())
model.add(tf.keras.layers.Conv2D(512,(3,3),activation='relu'))
model.add(tf.keras.layers.Conv2D(512,(3,3),activation='relu'))
model.add(tf.keras.layers.MaxPool2D())
model.add(tf.keras.layers.Conv2D(512,(3,3),activation='relu'))
model.add(tf.keras.layers.Conv2D(512,(3,3),activation='relu'))
model.add(tf.keras.layers.Conv2D(512,(3,3),activation='relu'))
model.add(tf.keras.layers.GlobalAveragePooling2D())#平均池化
model.add(tf.keras.layers.Dense(1024,activation='relu'))#连接到1024个单元数
model.add(tf.keras.layers.Dense(512,activation='relu'))#做输出单元数减小
model.add(tf.keras.layers.Dense(1,activation='sigmoid'))#二分类问题输出单个

模型优化函数等设置

==多分类 CategoricalCrossentropy==
==二分类 BinaryCrossentropy==

1
2
3
4
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.00001),
loss=tf.keras.losses.BinaryCrossentropy(),
metrics=['acc']
)

开始训练

1
2
3
4
5
6
7
8
9
step_per_epoch = train_count//BATCH_SIZE #每一个epoch,全部数据训练一遍
val_step = test_count//BATCH_SIZE

history = model.fit(train_ds, epochs=50,
steps_per_epoch=step_per_epoch,
validation_data=test_ds,
validation_steps=val_step

)#train_ds = train_ds.repeat().shuffle(100).batch(BATCH_SIZE) 的repeat没设置需要设置epochs

使用模型进行预测

1
2
imgpth = './test01.jpg'  #预测图片
img = load_img(imgpth)

调用自定义load_img函数 图片->读取(tf.io.read_file()) -> 解码(tf.image.decode_jpeg(img_raw,channels=3)) ->图片resize(tf.image.resize(img_tensor,[256,256])) ->图片数据类型更改为float32(tf.cast(img_tensor,tf.float32)) -> 图片归一化(img_tensor / 255)

1
2
3
4
5
#扩展维度
img = tf.expand_dims(img,axis=0)#扩展数据,扩展维度第几个,在第0个位置扩展
img.shape
pred = model.predict(img)
index_to_label.get((pred > 0.5).astype('int')[0][0])#astype修改数据类型

==整合==

1
2
3
4
5
6
def pre_img(img_path):
img = load_img(img_path)
img = tf.expand_dims(img,axis=0)
pred = model.predict(img)
print(pred)
print(index_to_label.get((pred > 0.5).astype('int')[0][0]))#astype修改数据类型
1
pre_img('hu.jfif')