本篇博客与验证码识别的操作大同小异,只不过在网络结构以及优化器的处理上有所不同。 注:本博客所实现的车牌识别不足以作为一个课设或者毕设,仅使用了CNN,若想做到精确的识别,还需要用到别的模型
1.导入库
import tensorflow as tf
import matplotlib.pyplot as plt
import os,PIL,random,pathlib
import numpy as np
from tensorflow.keras import datasets,layers,models
2.导入数据
data_dir = "E:\\tmp\\.keras\\datasets\\ch_photos"
data_dir = pathlib.Path(data_dir)
pic_paths = list(data_dir.glob('*'))
pic_paths = [str(path) for path in pic_paths]
pic_paths后三张图片的路径
['E:\\tmp\\.keras\\datasets\\ch_photos\\000000000_川W9BR26.jpg', 'E:\\tmp\\.keras\\datasets\\ch_photos\\000000000_藏WP66B0.jpg', 'E:\\tmp\\.keras\\datasets\\ch_photos\\000000001_沪E264UD.jpg']
图片总数:13675
all_label_names = [path.split("_")[2].split(".")[0] for path in pic_paths]
plt.figure(figsize=(10, 5))
plt.suptitle("数据示例", fontsize=15)
for i in range(20):
plt.subplot(5, 4, i + 1)
plt.xticks([])
plt.yticks([])
plt.grid(False)
images = plt.imread(pic_paths[i])
plt.imshow(images)
plt.xlabel(all_label_names[i], fontsize=13)
plt.show()
图片如下所示:
3.标签数字化
char_enum = ["京","沪","津","渝","冀","晋","蒙","辽","吉","黑","苏","浙","皖","闽","赣","鲁","豫","鄂","湘","粤","桂","琼","川","贵","云","藏","陕","甘","青","宁","新","军","使"]
number = [str(i) for i in range(0,10)]
alt = [chr(i) for i in range(65,91)]
char_set = char_enum+number+alt
char_set_len = len(char_set)
label_name_len = len(all_label_names[0])
def text2vec(text):
print(text)
vector = np.zeros([label_name_len,char_set_len])
for i ,c in enumerate(text):
idx = char_set.index(c)
vector[i][idx] = 1.0
return vector
all_labels = [text2vec(i) for i in all_label_names]
4.构建一个tf.data.Dataset
path_ds = tf.data.Dataset.from_tensor_slices(pic_paths)
image_ds = path_ds.map(load_and_preprocess_image,num_parallel_calls=tf.data.experimental.AUTOTUNE)
label_ds = tf.data.Dataset.from_tensor_slices(all_labels)
image_label_ds = tf.data.Dataset.zip((image_ds,label_ds))
train_ds = image_label_ds.take(5000).shuffle(5000)
test_ds = image_label_ds.skip(5000).shuffle(1000)
batch_size = 32
train_ds = train_ds.batch(batch_size)
train_ds = train_ds.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)
test_ds = test_ds.batch(batch_size)
test_ds = test_ds.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)
5.搭建CNN网络
网络结构为:三层卷积池化+Flatten+两层Dense
model = models.Sequential([
tf.keras.layers.Conv2D(32,(3,3),activation='relu',input_shape=(50,200,1)),
tf.keras.layers.MaxPooling2D((2,2)),
tf.keras.layers.Conv2D(64,(3,3),activation='relu'),
tf.keras.layers.MaxPooling2D((2,2)),
tf.keras.layers.Conv2D(128,(3,3),activation='relu'),
tf.keras.layers.MaxPooling2D((2,2)),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(1000,activation='relu'),
tf.keras.layers.Dense(label_name_len*char_set_len),
tf.keras.layers.Reshape([label_name_len,char_set_len]),
tf.keras.layers.Softmax()
])
优化器的构建(参考K同学啊的博客):
learning_rate是影响模型准确率的一个重要因素。 ①学习率大 优点:学习速率加快、有助于跳出局部最优值 缺点:模型训练不收敛、模型不精确 ②学习率小 优点:有助于模型收敛,模型细化、提高模型精度 缺点:收敛缓慢,很难跳出局部最优值 动态学习率:指数衰减型(ExponentialDecay)。在每一个epoch开始前,学习率(learning_rate)都将会重置为初始学习率(initial_learning_rate),然后再重新开始衰减。 计算公式如下:
learning_rate =initial_learning_rate * decay_rate ^ (step / decay_steps)
init_learning_rate = 1e-3
lr_sch = tf.keras.optimizers.schedules.ExponentialDecay(
initial_learning_rate=init_learning_rate,
decay_steps=50,
decay_rate=0.96,
staircase=True
)
模型编译&&训练
epochs = 10
model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=lr_sch),
loss='categorical_crossentropy',
metrics=['accuracy']
)
history = model.fit(
train_ds,
validation_data=test_ds,
epochs=epochs
)
结果如下所示: 训练集的模型准确率达到了100%,但是测试集的准确率就有些低了,在70%左右。
6.模型加载&&预测
模型保存:
model.save('E:/tmp/.keras/datasets/ch_photos/ch_model.h5')
模型加载:
new_model = tf.keras.models.load_model('E:/tmp/.keras/datasets/ch_model.h5')
选取6张图片进行预测:
plt.figure(figsize=(10, 8))
for images, labels in test_ds.take(1):
images = tf.squeeze(images, axis=3)
for i in range(6):
ax = plt.subplot(5, 2, i + 1)
plt.imshow(images[i])
img_array = tf.expand_dims(images[i], 0)
img_array = tf.expand_dims(img_array, -1)
predictions = new_model.predict(img_array)
plt.title(vec2text(np.argmax(predictions, axis=2)[0]), fontsize=15)
plt.axis("off")
plt.show()
结果如下: 总结: 模型的准确率不高有一下几点: 1.图片模糊,根据上图来看,有的图片本身就存在不清楚、歪斜、缺失等特点,导致训练效果不好。 2.某些字形近,例如0和Q、2和Z、1和I、V和Y等,单纯的利用卷积去识别它们的特征很困难,这里和手写数字识别是不一样的。 进一步提高准确率的方式: 1.对图片做锐化处理,使其特征更加明显,在模型训练时可以更轻松的提取特征。 2.采用分割的方式将车牌分割为7个字符,然后分别对这7个字符进行处理,而不是统一处理。这一操作就需要引入别的字符分割的模型了。 3.修改网络,包括超参数的修改和网络结构的修改,但是这一步所能提高的准确率很有限。 努力加油a啊
|