一、概述

本文主要记录的在使用Keras过程中,实现交通标志分类。

文本主要使用的环境为:

Python3.5.2

Tensorflow 1.7

Keras 2.1.4

win10

所有程序均亲测可以通过。文中将使用Keras对图像进行分类处理,处理过程包括了

1.图像的预处理

2.神经网络的训练,得到训练后的模型

3.使用训练后的模型,对图像进行预测。

二、图像预处理

本文获取的交通标志图片,是从德国一家交通标志数据集的站点 上获取图像,因为从网站上获取的图像是PPM格式的,所以使用Opencv将图像从PPM转换为png。具体实现代码如下:

import cv2
import os
# 训练集路径
ORIGINAL_TRAIN_PATH = 'datasets/Train'
# 测试集路径
ORIGINAL_TEST_PATH = 'datasets/Test'
# 处理训练集的图像,将其转换为同名称的PNG格式
for train_class in os.listdir(ORIGINAL_TRAIN_PATH):
# train_class:当前文件夹的文件夹名称
for pic in os.listdir(ORIGINAL_TRAIN_PATH + '/' + train_class):
# pic:当前的PPM文件名称
if not (pic.split('.')[1] == 'ppm'):
continue
# 读取图像文件
im = cv2.imread(ORIGINAL_TRAIN_PATH + '/' + train_class + '/' + pic)
# 获取文件名称
name = pic.split('.')[0]
# 生成新的文件名称
new_name = name + '.png'
print(new_name)
# 生成图像文件
cv2.imwrite('datasets/GTSRB_Final_Training_Images/GTSRB/Final_Training/Images/' + train_class + '/' + new_name, im)
# 注释与训练集解析相同
for test_class in os.listdir(ORIGINAL_TEST_PATH):
for pic in os.listdir(ORIGINAL_TRAIN_PATH + '/' + test_class):
if not (pic.split('.')[1] == 'ppm'):
continue
im = cv2.imread(ORIGINAL_TRAIN_PATH + '/' + test_class + '/' + pic)
name = pic.split('.')[0]
new_name = name + '.png'
print(new_name)
cv2.imwrite('datasets/GTSRB_Online-Test-Images-Sorted/GTSRB/Online-Test-sort/' + test_class + '/' + new_name, im)

三、训练神经网络

此过程使用了Keras搭建神经网络,使用的CNN是经典的LeNet,实验相对简单,适用性好。在图像的处理用,对图像分类存储的要求:

  • 图像按照一个文件类型一个文件夹的形式存放
  • 文件夹使用整数型表示,从0开始

完整的实现的代码如下:

# 导入必要的模块
from keras.models import Sequential
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers.core import Activation
from keras.layers.core import Flatten
from keras.layers.core import Dense
from keras import backend as K
import matplotlib
matplotlib.use("Agg")
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import Adam
from keras.preprocessing.image import img_to_array
from keras.utils import to_categorical
from imutils import paths
import matplotlib.pyplot as plt
import numpy as np
import argparse
import random
import cv2
import os
import sys
sys.path.append('..') # matplotlib中,显示中文,置换字体
from pylab import*
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 搭建的神经网络模型(LeNet)
class LeNet:
@staticmethod
def build(width, height, depth, classes):
# 初始化模型
model = Sequential()
inputShape = (height, width, depth)
# 如果使用了 "channels last", 更新输入shape
if K.image_data_format() == "channels_first": # for tensorflow
inputShape = (depth, height, width)
# 设置第一层 CONV => RELU => POOL 层
model.add(Conv2D(20, (5, 5), padding="same", input_shape=inputShape))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
# 设置第二层CONV => RELU => POOL 层
model.add(Conv2D(50, (5, 5), padding="same"))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
# 首先 (也是唯一设置) FC => RELU 层
model.add(Flatten())
model.add(Dense(500))
model.add(Activation("relu")) # softmax 分类器
model.add(Dense(classes))
model.add(Activation("softmax")) # 返回构建好的网络体系结构
return model
# 基本的参数配置信息:
#训练迭代次数
EPOCHS = 8
#
INIT_LR = 1e-3
# 一个训练batch中的训练数据个数
BS = 64
# 分类数(分类个数,此模型是按照文件夹的个数分类的)
CLASS_NUM = 43
# 图像尺寸的大小(这个需要根据实际情况进行调整,此模型均归一化成正方形)
norm_size = 64 # 加载数据信息,图像与标签信息(图像与数字标签)
def load_data(path):
print("[INFO] loading images...")
# 图像数据数组即:x
data = []
# 标签数据数组即:y
labels = []
# 获取图像路径
imagePaths = sorted(list(paths.list_images(path)))
random.seed(43)
# 对图像路径随机分配处理
random.shuffle(imagePaths)
# 循环输入图像
for imagePath in imagePaths:
# 加载图像,预处理图像,并将其存储在数据列表中
image = cv2.imread(imagePath)
image = cv2.resize(image, (norm_size, norm_size))
image = img_to_array(image)
data.append(image) # 从图像路径中提取类标签并更新标签列表
label = int(imagePath.split(os.path.sep)[-2])
labels.append(label) # 数据进行归一化处理 将原始像素强度缩放到范围[0,1]
data = np.array(data, dtype="float") / 255.0
labels = np.array(labels) # 将标签从整数转换为矢量(即每个位置转换为0或1,)
# to_categorical(y, num_classes=None)
# 将类别向量(从0到nb_classes的整数向量)映射为二值类别矩阵,
# 用于应用到以categorical_crossentropy为目标函数的模型中.
# y: 类别向量
# num_classes:总共类别数
labels = to_categorical(labels, num_classes=CLASS_NUM)
return data, labels # 训练神经网络
def train(aug, trainX, trainY, testX, testY, args): print("[INFO] compiling model...")
# 初始化模型
model = LeNet.build(width=norm_size, height=norm_size, depth=3, classes=CLASS_NUM)
opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS)
model.compile(loss="categorical_crossentropy", optimizer=opt,
metrics=["accuracy"]) # 训练神经网络
print("[INFO] training network...")
H = model.fit_generator(aug.flow(trainX, trainY, batch_size=BS),
validation_data=(testX, testY), steps_per_epoch=len(trainX) // BS,
epochs=EPOCHS, verbose=1) # 将模型保存至硬盘
print("[INFO] serializing network...")
model.save(args["model"]) # 绘制训练损失和准确性曲线并保存
plt.style.use("ggplot")
plt.figure()
N = EPOCHS
plt.plot(np.arange(0, N), H.history["loss"], label="train_loss")
plt.plot(np.arange(0, N), H.history["val_loss"], label="val_loss")
plt.plot(np.arange(0, N), H.history["acc"], label="train_acc")
plt.plot(np.arange(0, N), H.history["val_acc"], label="val_acc")
# 标题 X轴名称 Y轴名称
plt.title("图像分类识别")
plt.xlabel("迭代步数#")
plt.ylabel("误差")
plt.legend(loc="lower left")
# 保存图像曲线
plt.savefig(args["plot"]) # 主程序入口
if __name__=='__main__':
args = {}
# 存储模型的地址
args['model'] = 'MODE/traffic_sign.model'
# 输出训练曲线的地址
args['plot'] = 'MODE/plot.png'
# 训练图像集合文件夹路径
args['dataset_train'] = "datasets/GTSRB_Final_Training_Images/GTSRB/Final_Training/Images"
# 测试图像集合文件夹路径
args['dataset_test'] = "datasets/GTSRB_Online-Test-Images-Sorted/GTSRB/Online-Test-sort" train_file_path = args['dataset_train']
test_file_path = args['dataset_test']
# 加载训练集合的输入端数据与输出端数据
trainX,trainY = load_data(train_file_path)
# 加载测试集合的输入端数据与输出端数据
testX,testY = load_data(test_file_path)
# 构建用于数据增强的图像生成器
aug = ImageDataGenerator(rotation_range=30, width_shift_range=0.1,
height_shift_range=0.1, shear_range=0.2, zoom_range=0.2,
horizontal_flip=True, fill_mode="nearest")
# 开始训练
train(aug,trainX,trainY,testX,testY,args)

四、图像预测

预测图像时,程序执行的步骤如下:

  1. 加载训练好的模型
  2. 对输入图像进行必要的前处理,如修改尺寸,序列化;
  3. 将序列化的图像输入模型中
  4. 得到序列结果,找到最大概率与对应位置

测过程即为输入图像,得到它是哪种分类的可能性最大以及对应的概率。

具体实现代码如下:


# 加载工程中必要的库
from keras.preprocessing.image import img_to_array
from keras.models import load_model
import numpy as np
import argparse
import imutils
import cv2 # 根据使用的模型,确定图像需要resize的尺寸
norm_size = 64 # 预测函数,
# 输入: 包含配置参数的字典
def predict(args): # 加载训练好的卷积神经网络
print("[INFO] loading network...")
model = load_model(args["model"]) # 加载图像
image = cv2.imread(args["image"])
# 因为对图像需要进行写入标签,影响较大所以复制一个图像
orig = image.copy() # 预处理图像进行分类
# 图像的尺寸重载
image = cv2.resize(image, (norm_size, norm_size))
# 图像的序列的归一化处理
image = image.astype("float") / 255.0
# 将图像进行序列化
image = img_to_array(image)
# 展开数组的形状.
# 插入一个新的轴,该轴将出现在扩展阵列形状的轴位置
image = np.expand_dims(image, axis=0) # 对输入的图像进行分类
result = model.predict(image)[0]
# print (result.shape)
proba = np.max(result)
label = str(np.where(result == proba)[0])
label = "{}: {:.2f}%".format(label, proba * 100)
print(label)
# 在需要加载图像的情况下
if args['show']:
output = imutils.resize(orig, width=400)
# 在图像上绘制标签字符串
cv2.putText(output, label, (10, 25), cv2.FONT_HERSHEY_SIMPLEX,
0.7, (0, 255, 0), 2)
# 显示带标签的图像
cv2.imshow("Output", output)
cv2.waitKey(0) # python predict.py --model traffic_sign.model -i ../2.png -s
if __name__ == '__main__':
args = {}
# 模型的输入路径
args['model'] = 'MODE/traffic_sign2.model'
# 图像的输入路径
args['image'] = 'predict/00000_00005.png'
args['show'] = 'true'
# 执行预测
predict(args)

训练的图像如下图:

使用Keras对交通标志进行分类的更多相关文章

  1. 人工智能深度学习框架MXNet实战:深度神经网络的交通标志识别训练

    人工智能深度学习框架MXNet实战:深度神经网络的交通标志识别训练 MXNet 是一个轻量级.可移植.灵活的分布式深度学习框架,2017 年 1 月 23 日,该项目进入 Apache 基金会,成为 ...

  2. TSR交通标志检测与识别

    TSR交通标志检测与识别 说明: 传统图像处理算法的TSR集成在在ARM+DSP上运行,深度学习开发的TSR集成到FPGA上运行. 输入输出接口 Input: (1)图像视频分辨率(整型int) (2 ...

  3. AI在汽车中的应用:实用深度学习

    https://mp.weixin.qq.com/s/NIza8E5clC18eMF_4GMwDw 深度学习的“深度”层面源于输入层和输出层之间实现的隐含层数目,隐含层利用数学方法处理(筛选/卷积)各 ...

  4. 【Keras】从两个实际任务掌握图像分类

    我们一般用深度学习做图片分类的入门教材都是MNIST或者CIFAR-10,因为数据都是别人准备好的,有的甚至是一个函数就把所有数据都load进来了,所以跑起来都很简单,但是跑完了,好像自己还没掌握图片 ...

  5. 深度学习应用系列(二) | 如何使用keras进行迁移学习,以训练和识别自己的图片集

    本文的keras后台为tensorflow,介绍如何利用预编译的模型进行迁移学习,以训练和识别自己的图片集. 官网 https://keras.io/applications/ 已经介绍了各个基于Im ...

  6. TB3_Autorace之交通杆检测

    利用blob检测算法识别交通杆,控制TB3机器人完成对交通杆的起停动作! 上一篇博文中<TB3_Autorace之路标检测>订阅了原始图像信息,经过SIFT检测识别出道路交通标志,这里我们 ...

  7. GAN︱生成模型学习笔记(运行机制、NLP结合难点、应用案例、相关Paper)

    我对GAN"生成对抗网络"(Generative Adversarial Networks)的看法: 前几天在公开课听了新加坡国立大学[机器学习与视觉实验室]负责人冯佳时博士在[硬 ...

  8. 预测学习、深度生成式模型、DcGAN、应用案例、相关paper

    我对GAN"生成对抗网络"(Generative Adversarial Networks)的看法: 前几天在公开课听了新加坡国立大学[机器学习与视觉实验室]负责人冯佳时博士在[硬 ...

  9. TensorFlow和最近发布的slim

    笔者将和大家分享一个结合了TensorFlow和最近发布的slim库的小应用,来实现图像分类.图像标注以及图像分割的任务,围绕着slim展开,包括其理论知识和应用场景. 之前自己尝试过许多其它的库,比 ...

随机推荐

  1. JavaWeb学习笔记四 request&response

    HttpServletResponse 我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和代表响应res ...

  2. 网络推广 免费推广产品网站 B2B网站如何推广

    云集网(yunjinet.com)免费发布各类服务和产品信息,在平台上推广你的产品.帮助商家推广优质的产品和服务.如何提高信息的点击量为了提高分类信息网的信息质量,对重复度高.相似度高的信息进行了过滤 ...

  3. C语言--函数嵌套

    一.实验作业 注意: 1.可以先初始化2个结构体数组数据以便测试. 2.要求用模块化方式组织程序结构,合理设计各自定义函数.同时,程序能够进行异常处理,检查用户输入数据的有效性,用户输入数据有错误,如 ...

  4. JAVA序列化基础知识

    1.序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来.虽然你可以用你自己的各种各样的方法来保 存object states, ...

  5. 20145237 《Java程序设计》第4周学习总结

    20145237 <Java程序设计>第4周学习总结 教材学习内容总结 一. 继承  . 定义:面向对象中,涉及对象过多时容易出现重复行为,为了避免这种情况,就可把重复的部分写成父类,由子 ...

  6. 201621123043 《Java程序设计》第1周学习总结

    1. 本章学习总结 Jdk的安装: eclipse的基本使用方法 Java发展史 jdk.jre.jvm 关键词之间的联系:是整个java的核心,包括了一堆java.java基础的类库.java运行环 ...

  7. 在Eclipse中调用Algs4库

    首先下载Eclipse,我选择的是Eclipse IDE for Java Developers64位版本,下载下来之后解压缩到喜欢的位置然后双击Eclipse.exe启动 然后开始新建项目,File ...

  8. 顺企网 爬取16W数据保存到Mongodb

    import requests from bs4 import BeautifulSoup import pymongo from multiprocessing.dummy import Pool ...

  9. wamp的mysql设置用户名和密码

    wamp下修改mysql root用户的登录密码 感谢作者:http://www.3lian.com/edu/2014/02-25/131010.html               1.安装好wam ...

  10. Linq 连接运算符:Concat

    //Concat()方法附加两个相同类型的序列,并返回一个新序列(集合)IList<string> strList = new List<string>() { "O ...