在自动驾驶中,人工智能是如何识别交通标志的?

2018 年 12 月 5 日,Google 旗下的 Waymo 推出了首个自动驾驶叫车服务软件 ——Waymo One,该服务在美国的 4 个地区 24 小时运行。乘客只需通过 APP 选定上下车地点,即可呼叫自动驾驶的汽车去往任何地方。

同样,在北京的 AI 公园里,阿波龙自动驾驶小巴也受到了人们的关注。这款迷你小巴可搭载 6 - 7 人,没有驾驶座也没有方向盘,等乘客落座系好安全带,就会关上车门自动起步。

自动驾驶已经来到了我们身旁,相比于其他噱头成分占多的“风口”行业,自动驾驶属于为数不多的有实际价值、有数据积累、且技术相对成熟的实力派,目前各大顶级车厂也都在合作研发自己的自动驾驶方案。

那么,你有没有想过,自动驾驶是如何实现的?

其实很简单,首先回忆一下,人平时是怎么开车的:

  • 观察:观察路况,如车距、行人、交通标志等;

  • 分析:根据经验作出分析,该加速、减速,还是停车;

  • 做出决策:作出相应的动作,踩油门或刹车。

明白了这个,就不难理解自动驾驶的原理。其实自动驾驶的过程和人类驾驶没什么区别:

  • 感知:通过摄像头、雷达等硬件,收集图像等数据,相当于人眼的观察;

  • 分析:通过深度学习模型,实时分析图像,得出下一步的决策;

  • 做出决策

摄像头在自动驾驶中有着举足轻重的作用,它就像人的眼睛一样,快速收集车辆、行人和交通标志信息,给自动驾驶技术提供足够的环境信息。今天我们就从交通标志识别这个角度入手,看一看自动驾驶系统的识别原理。

(以下内容出自课程——《使用卷积神经网络识别交通标志》https://www.shiyanlou.com/courses/1507)

介绍:

本实验采用德国交通标志数据集,使用 TensorFlow 实现的卷积神经网络解决交通标志分类问题。训练前对原数据进行了数据扩充保证了训练集数据类型的平衡,并对数据进行了预处理,来改善特征提取。使用深度神经网络分类器作为模型,采用扩充后的平衡数据集进行训练,其准确率达到 98% 以上,可以通过预训练或者降低学习率对模型进行微调来进一步提高模型性能。

知识点
  • 数据预处理

  • 数据扩充

  • 深度神经网络分类器

  • Tensorflow 卷积网络实现

数据导入

我们首先定义一个加载数据集的函数 load_pickled_data(file, columns),这里用到了 pickle 模块,pickle 它可以序列化和反序列化对象并保存到磁盘中,并在需要的时候读取出来。本实验用 pickle.load() 将文件反序列读出,将文件中的数据解析为一个 Python 对象。

反序列化后的数据 (the pickled data) 是具有 4 个键值对的字典:

  • features 是一个 4 D 数组,其中包含交通标志图像的原始像素数据(样本数,宽度,高度,通道)。

  • labels 是一个 2 D 数组,其中包含交通标志的标签和类别 ID。文件 signnames.csv 包含 id 到每个 id 名称的映射。

  • sizes 是一个包含元组的列表,元组(宽度,高度)代表图像的原始宽度和高度。

  • coords 是一个包含元组的列表,(x1,y1,x2,y2)表示图像中符号周围的边界框的坐标。

我们的输入 file 是我们需要加载的数据集文件,columns 是我们需要的部分,后面代码中可以看到我们选择了 features 和 labels,返回值是给定列数据集的元祖。

 教学代码:

import pickle

def load_pickled_data(file, columns):
    # mode='rb' 表示以二进制可读模式打开文件
    with open(file, mode='rb') as f:
        dataset = pickle.load(f)
    return tuple(map(lambda c: dataset[c], columns))

首先,导入我们的数据集,本实验数据来源于 德国交通标志数据集,为了方便写入,实验从实验楼服务器下载该数据集。

# 从实验楼服务器下载数据集
!wget -nc "https://labfile.oss.aliyuncs.com/courses/1507/traffic-signs-data.zip"
!unzip -o "traffic-signs-data.zip"

接下来加载数据集并查看训练集和测试集的大小、交通标志种类数和每类的名称:

import csv
import numpy as np
from pandas.io.parsers import read_csv

signnames = read_csv("./traffic-signs-data/signnames.csv").values[:, 1]
train_dataset_file = "./traffic-signs-data/train.p"
test_dataset_file = "./traffic-signs-data/test.p"

# 用 load_pickled_data 函数加载训练集、测试集
X_train, y_train = load_pickled_data(
    train_dataset_file, ['features', 'labels'])
X_test, y_test = load_pickled_data(test_dataset_file, ['features', 'labels'])

n_train = y_train.shape[0]
n_test = y_test.shape[0]
image_shape = X_train[0].shape
image_size = image_shape[0]
sign_classes, class_indices, class_counts = np.unique(
    y_train, return_index=True, return_counts=True)
n_classes = class_counts.shape[0]

print("Number of training examples =", n_train)
print("Number of testing examples =", n_test)
print("Image data shape =", image_shape)
print("Number of classes =", n_classes)

with open('./traffic-signs-data/signnames.csv', 'r') as csvfile:
    # 跳过文件开头
    next(csvfile, None)
    reader = csv.reader(csvfile, delimiter=',')
    for row in reader:
        signnames[int(row[0])] = row[1]
        print("the class {} has the name: {}".format(int(row[0]), row[1]))

以上代码运行结果得到我们的训练集数据共有 34799 个,测试集数据共有 12630 个,且都是 32x32 的彩色图像,每个图像都是 43 个类别中的一种,类别编码为 0-42 的整数。

我们还想知道数据集在这 43 类的不同类中的数据量是否平衡,所以我们遍历所有类别,记录下不同类别的数据量并绘制每个类别 10 张随机图像。其中, zip() 函数以可迭代对象为输入参数,将可迭代对象里元素分别取出再组合成一个个元组,返回一个列表。

import random
from matplotlib import pyplot
%matplotlib inline

col_width = max(len(name) for name in signnames)

# 显示每一类的名称和数据量
for c, c_index, c_count in zip(sign_classes, class_indices, class_counts):
    print("Class %i: %-*s  %s samples" %
          (c, col_width, signnames[c], str(c_count)))
    fig = pyplot.figure(figsize=(6, 1))
    fig.subplots_adjust(left=0, right=1, bottom=0,
                        top=1, hspace=0.05, wspace=0.05)
    random_indices = random.sample(range(c_index, c_index + c_count), 10)
    for i in range(10):
        axis = fig.add_subplot(1, 10, i + 1, xticks=[], yticks=[])
        axis.imshow(X_train[random_indices[i]])
    pyplot.show()
    print("--------------------------------------------------------------------------------------\n")

pyplot.bar(np.arange(43), class_counts, align='center')
pyplot.xlabel('Class')
pyplot.ylabel('Number of training examples')
pyplot.xlim([-1, 43])
pyplot.show()

从不同类别的数据量的柱形图看,显然,数据集非常不平衡,一些类别的数目很少,只有 210 个样本,而另一些类的数目明显优于其他,这使得模型不能很好得泛化。

从 43 个类别的具体图像看出,图像在对比度和亮度方面存在显著差异,因此我们可以应用某种直方图均衡化,这将明显改善我们的特征提取,于是我们先进行数据预处理。

数据预处理

原始图像:

预处理后的图像:

篇幅有限,后续的图像处理、建模过程,请在实验楼边敲代码边学习~

????????????点击阅读原文,学习准确率 98% 以上的交通标志识别项目。

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值