摘要
随着自动驾驶技术的发展,交通标志的识别与理解在智能交通系统中扮演着越来越重要的角色。本文设计并实现了一个基于深度学习的交通标志图像识别系统,通过对交通标志识别基准数据集的分析与处理,建立了一套完整的图像识别流程。使用Python及其相关库(如Keras、OpenCV、NumPy等)对交通标志图像进行预处理。通过自定义的图像处理函数,对原始图像进行直方图均衡化,以增强图像的对比度,并将图像统一调整为48x48的大小,以便于后续的模型输入。同时,利用标签信息,从文件路径中提取出每个图像对应的类别标签,并进行独热编码处理,以适应深度学习模型的需求。在模型建立方面,我们采用了卷积神经网络(CNN)作为主要架构。该模型包括多个卷积层、池化层和全连接层,旨在提取图像的特征并进行分类。通过搭建Sequential模型,并使用ReLU激活函数,保证了模型的非线性表达能力。为了防止过拟合,模型中引入了Dropout层,并配置了合适的学习率和优化器(SGD),以提高训练的稳定性和收敛速度。在训练过程中,使用了数据增强技术,通过旋转、平移、剪切和缩放等手段,扩展了训练数据集,从而提高模型的泛化能力。模型在训练集上进行了30个epoch的训练,并通过验证集监控训练过程中的性能变化,利用Learning Rate Scheduler动态调整学习率,确保模型在训练后期的细致优化。训练完成后,我们在测试集上评估了模型的性能。经过测试,模型的准确率达到较高水平,表明其在交通标志识别任务上的有效性和可靠性。最终,通过可视化工具展示了训练与验证过程中的损失和准确率变化,清晰呈现了模型的学习曲线和收敛情况。
本项目通过深度学习技术成功实现了对交通标志的自动识别,为未来智能交通系统的构建提供了技术支持。未来的工作可以进一步探索模型的轻量化设计与实时识别能力,以适应实际应用场景的需求。此外,结合更多种类的交通标志数据与其他传感器数据,将为深度学习在自动驾驶领域的应用开辟更广阔的前景。
数据集介绍
数据集里面的图像具有不同大小,光照条件,遮挡情况下的43种不同交通标志符号,图像的成像情况与你实际在真实环境中不同时间路边开车走路时看到的交通标志的情形非常相似。训练集包括大约39,000个图像,而测试集大约有12,000个图像。图像不能保证是固定的尺寸,标志不一定在每个图像中都是居中。每个图像包含实际交通标志周围10%左右的边界。
图像亮度直方图均衡化 (Histogram equalization)处理
从上面的代表性图像可以看出,图像在亮度上(illumination)有很大的差异不同。他们也有不同的大小。所以,我们来编写一个函数,在HSV颜色空间中进行直方图均衡,并将图像调整为成一样的标准大小。
"直方图均衡化"是图像处理领域中利用图像直方图
对对比度
进行调整的方法。
这种方法通常用来增加许多图像的全局对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。
这种方法对于背景和前景都太亮或者太暗的图像非常有用, 而且它是一个相当直观的技术并且是可逆操作,如果已知均衡化函数,那么就可以恢复原始的直方图,并且计算量也不大。 但是这种方法的一个缺点是它可能会增加背景杂质的对比度并且降低有用信息的对比度。
图像大小的修改 (Image Resizing)处理
由于图像具有不同的形状和大小,因此我们必须对图像进行归一化(normalize)处理以便可以决定模型的輸入。
在这个范例我们选择使用48x48的图像大小。你也可以尝试使用比较小的图像比如32x32或24x24看看是不是也可得到类似的准确率。
图像处理并转换成numpy ndarray处理
让我们预处理所有的训练图像并以numpy数组来存储到档案系统中。过程中我们还会从图像的档案路径中获取图片的标签。我们会将标签(label)数据进行one-hot编码:
try:with h5py.File('X.h5') as hf:X, Y = hf['imgs'][:], hf['labels'][:]print("Loaded images from X.h5")except(IOError, OSError, KeyError):print("Error in reading X.h5. Processing all images...")root_dir = 'GTSRB/Final_Training/Images/'imgs = []labels = []all_img_paths = glob.glob(os.path.join(root_dir, '*/*.ppm')) np.random.shuffle(all_img_paths) for img_path in all_img_paths:try:img = preprocess_img(io.imread(img_path))label = get_class(img_path)imgs.append(img) labels.append(label) if len(imgs)%1000 == 0:print("Processed {}/{}".format(len(imgs), len(all_img_paths))) except(IOError, OSError):print('missed', img_path)passX = np.array(imgs, dtype='float32') Y = np.eye(NUM_CLASSES, dtype='uint8')[labels] with h5py.File('X.h5', 'w') as hf:hf.create_dataset('imgs', data=X)hf.create_dataset('labels', data=Y)
模型构建
现在我们来定义我们的模型架构。我们将使用具有6个卷积层的前馈网络,然后是全连接的隐藏层。我们也将在两者之间使用Dropout层来防止网络"过拟合(overfitting)"。
在训练模型之前,我们需要将模型配置为学习算法并进行编译。我们需要指定:
loss
: 我们要优化的损失函数。我们不能使用MSE
,因为它是不连续的数值。因此,我们使用:categorical_crossentropy
optimizer
: 我们使用标准随机梯度下降(Stochastic gradient descent)与涅斯捷罗夫动量(Nesterov momentum)metric
: 由于我们正在处理一个分类问题,评价标准是accuracy
。
训练 (Training)
现在,我们的模型已经准备好了。在训练期间,我们的模型将进行迭代批量训练,每批次的训练资料的大小为batch_size。对于每批次,模型将会计算出梯度(gradient),并自动更新网络的权重。对所有训练集的一次迭代被称为一次的循环(epoch)。训练通常会一直进行到损失收敛于一个常数。
我们将增加一些功能到我们的训练设定:
Learning rate scheduler
: 随着训练循环的次数逐渐增加的过程中对权重调整的学习率进行衰减通常有助于让模型学习更好Model checkpoint
: 我们将比对每个训练循环的验证准确度并只保存模型表现最好的模型。这对深度学度来说是很有用的设定,因为我们的网络可能在一定数量的训练循环后开始过拟合(overfitting),但是我们需要在整个训练过程中将表现最好的模型保存下来。
这些设定不是必须的,但它们的确可以提高模型的准确性。这些功能是通过Keras的callback
功能来实现的。callback
是一组函式,将在训练过程的特定阶段被应用,比如将训练结束。 Keras提供内置的学习速率调度(learning rate scheduling )和模型检查点功能(model checkpointing)。
验证评估 (Evaluation)
加载测试数据并评估模型。训练出一个准确率达到97%的模型。与人类的平均表现相差不远了(98.84%)
y_pred = model.predict_classes(X_test)
acc = np.sum(y_pred==y_test)/np.size(y_pred)
print("Test accuracy = {}".format(acc))
图像增强 (Data Augmentation)
你可能会认为40,000图像是很多的图像。再想一想,我们的模型里有1,358,155个参数。这是训练图像的数量的40多倍。如果我们可以从现有的图像生成新的训练图像,这将是一个很好的方式来增加训练数据集的大小。直接使用keras的内置功能来完成图像增强 (Data Augmentation)。
from sklearn.model_selection import train_test_splitX_train, X_val, Y_train, Y_val = train_test_split(X, Y, test_size=0.2, random_state=42)datagen = ImageDataGenerator(featurewise_center=False, featurewise_std_normalization=False, rotation_range=10.,width_shift_range=0.1,height_shift_range=0.1, shear_range=0.1,zoom_range=0.2,)datagen.fit(X_train)
验证评估 (Evaluation)
通过图像增强 (Data Augmentation)后再训练的这个模型,在测试集上获得了98.7%
的准确度。
以下列出一些可以尝试改进模型的东西:
- 尝试不同的网络架构。尝试更深和更浅的网络。
- 尝试添加
BatchNormalization
层到网络。 - 尝试不同的权重初始化
- 尝试不同的学习速度和时间表
- 制作一个集成模型(ensemble models)
- 尝试输入图像的正则化
- 更好的数据增强(Data Augmentation)
总结
在这篇文章中有一些个人学习到的一些有趣的重点:
- 对于图像的成像亮度通过直方图均衡化(Histogram equalization)可以轻松的调整
- 深度学习的卷积网络真的对图像的识别有很好的效果
- 通过使用Keras的callback可以对模型的训练过程有更多的监控与控制
完整代码可联系我!