Python TensorFlow Keras深度学习模型RetinaNet进行目标检测分析车牌数据
全文链接:https://tecdat.cn/?p=36968
原文出处:拓端数据部落公众号
目标检测作为计算机视觉领域的关键任务之一,在交通管理、智能安防、自动驾驶等众多应用场景中具有重要意义。车牌作为车辆的重要标识,其准确检测对于车辆识别、交通监控等系统的性能提升至关重要。
传统的目标检测方法在面对复杂场景和多样化的车牌样式时,往往存在精度不高、鲁棒性不足等问题。随着深度学习技术的迅速发展,特别是 TensorFlow Keras 框架下的深度学习模型,为解决这些问题提供了强大的工具。
RetinaNet 作为一种先进的深度学习目标检测模型,以其独特的结构和出色的性能,在多个领域取得了显著的成果。本研究将 RetinaNet 模型应用于车牌数据的目标检测,旨在探索其在该特定领域的有效性和潜力。
通过利用大规模的车牌数据集进行训练和优化,期望能够实现对车牌的高精度、快速检测,为相关实际应用提供可靠的技术支持。同时,对模型的性能进行深入分析和评估,为进一步改进和完善车牌检测技术提供有价值的参考。
环境配置与库导入
为了开展本研究,我们首先需要配置Python环境并导入必要的库。这些库涵盖了数据处理、模型构建、可视化以及深度学习框架等多个方面。
我们利用pandas
库来处理和分析数据集,numpy
库用于高效的数值计算。可视化方面,我们引入了matplotlib
和seaborn
库来绘制图表,以便直观地展示数据特征和模型结果。此外,通过%matplotlib inline
和%config InlineBackend.figure_format='retina'
的设置,我们确保了在Jupyter Notebook环境中图表的高质量显示。
为了构建和训练深度学习模型,我们采用了TensorFlow
框架及其高级API Keras
。特别地,针对目标检测任务,我们集成了keras_retinanet
库,该库提供了基于RetinaNet架构的预训练模型和工具。
数据集准备与预处理
首先,我们使用pandas
库从indian_number_plates.json
文件中读取车牌数据。该JSON文件以行格式存储,每行代表一个包含车牌图像URL及其标注信息的记录。通过调用pd.read_json
函数,并设置lines=True
参数,我们成功地将这些数据加载到DataFrame
对象plates_df
中。
接下来,为了确保存储下载图像的目录存在,我们使用os.makedirs
函数创建了一个名为number_plates
的目录。如果该目录已存在,则通过设置exist_ok=True
参数避免抛出错误。
为了构建可用于模型训练的数据集,我们初始化了一个空字典dataset
,其中包含用于存储图像名称、边界框坐标(x_min
, y_min
, x_max
, y_max
)和类别名称(class_name
)的列表。然后,我们遍历plates_df
中的每一行,对每条记录执行以下操作:
- 使用
urllib.request.urlopen
函数根据记录中的content
字段(即图像URL)下载车牌图像。 - 将下载的图像对象转换为PIL图像,并转换为RGB颜色模式以匹配常见的图像处理需求。
- 将处理后的图像保存到
number_plates
目录下,文件名格式为licensed_car_{counter}.jpeg
,其中counter
用于追踪已下载图像的数量。 - 将图像的存储路径添加到
dataset["image_name"]
列表中。 - 解析记录中的
annotation
字段,提取车牌边界框的坐标信息。根据图像的实际宽度和高度,将标注中的相对坐标转换为绝对像素坐标,并存储到相应的列表中。 - 将车牌的类别名称(在本例中为"license_plate")添加到
dataset["class_name"]
列表中。
完成上述遍历后,我们打印出已下载的汽车图像数量,以确认数据集的完整性和规模。
print("Downloaded {} car images.".format(counter))
通过上述步骤,我们成功地从JSON文件中提取并整理了车牌图像及其标注信息,构建了一个完整的数据集,为后续的目标检测模型训练提供了有力的支持。
数据预处理与初步探索
在数据处理的初步阶段,我们首先利用Pandas库将数据集加载为一个DataFrame对象,以便进行后续的分析与操作。以下是加载数据集并查看其前几行数据的代码实现:
df = pd.DataFrame(dataset)
df.head()
此步骤不仅验证了数据成功加载,还通过head()
方法提供了数据集的概览,有助于初步了解数据的结构和内容。
图像对象可视化函数
为了更直观地展示数据集中的图像及其包含的特定对象(如通过边界框标记的对象),我们定义了一个名为show_image_objects
的函数。该函数接收DataFrame中的一行数据作为输入,该数据行包含图像路径和对象边界框的坐标信息。
示例应用
为了演示show_image_objects
函数的功能,我们可以从DataFrame中选取一行数据作为示例,并调用该函数来展示图像及其包含的边界框:
show_image_objects(df.iloc[0])
通过上述步骤,我们不仅能够展示数据集中的图像,还能直观地看到图像中特定对象的边界框:
数据预处理
在数据准备阶段,为了有效地训练模型并评估其性能,我们首先将数据集划分为训练集和测试集。这通过train_test_split
函数实现,该函数从sklearn.model_selection
模块中导入,用于随机分割数据集。具体地,我们将原始数据集df
按照80%训练集和20%测试集的比例进行划分,并设置随机种子RANDOM_SEED
以确保结果的可重复性。
train_df, test_df = train_test_split(
df,
test_size=0.2,
random_state=RANDOM_SEED
)
接下来,为了后续训练过程中的便利,我们将训练集的注释信息(即标注数据)保存至annotations.csv
文件中,并去除索引和表头信息以简化文件结构。同时,我们定义了一个包含所有类别名称的集合classes
,在这个例子中仅包含'license_plate'
一个类别。然后,我们将这些类别名称及其对应的索引(从0开始)写入classes.csv
文件,该文件用于模型训练时指定类别标签。
最后,为了验证上述步骤是否按预期执行,我们使用!head
命令(通常在Jupyter Notebook或类似环境中可用)来查看classes.csv
和annotations.csv
文件的前几行内容。这有助于快速检查文件内容是否符合预期格式,从而确保后续处理流程的顺利进行。
训练
这段代码主要是进行了模型的下载和训练操作。
首先,定义了一个预训练模型的路径 PRETRAINED_MODEL
,并指定了一个模型的 URL URL_MODEL
。然后,使用 urllib.request.urlretrieve
函数从指定的 URL 下载模型,并保存到指定的路径。
最后,通过执行 keras_retinanet/bin/train.py
脚本来进行模型的训练。其中,--freeze-backbone
表示冻结骨干网络,--random-transform
可能是用于数据增强的随机变换,--weights {PRETRAINED_MODEL}
指定了使用刚刚下载的预训练模型的权重,--batch-size 8
设定了批处理大小为 8,--steps 500
可能是每个 epoch 中的训练步数,--epochs 10
设定了训练的轮数为 10 ,并使用 csv annotations.csv classes.csv
来指定数据的相关文件。
加载训练模型
首先,确定模型的路径。然后,加载模型。
例如,如果 CLASSES_FILE
中的内容为 0,cat\n1,dog\n2,rabbit
,那么 labels_to_names
字典可能为 {0: 'cat', 1: 'dog', 2: 'rabbit'}
。这种方式能够方便地将模型预测的类别标签转换为对应的名称,从而提高模型结果的可读性和可理解性。
预测
设置了分数阈值: 并定义了根据检测结果在图像上绘制框和标注的函数:
还定义了展示检测到的物体的函数:
plt.axis('off')
plt.imshow(draw)
plt.show()
最后,查看测试数据框的前 10 行:
例如,假设一张图像中有一个物体被标注为“cat”,其预测分数为 0.8 ,且超过了阈值 0.6 。那么在图像上将会绘制出一个框,并标注“cat 0.800”。又如,对于另一张图像,如果多个物体的预测分数都高于阈值,将会相应地绘制多个框和标注。
展示检测结果
通过以下代码对测试数据集中的前三个样本进行检测结果的展示: