项目一:智能交通行业-交通标志分类
对AI方面很感兴趣,但是没有项目经验,几乎没有面试邀请。主文就想着来做几个项目,好写到简历中,加油!
本文主要内容是
机器视觉图像分类的基本原理
卷积神经网络的基本原理
熟练使用tensorflow和keras完成图像分类项目的开发
独立完成3个企业级项目:
- 智能交通行业-交通标志分类
- 智能交通行业-车辆图像分类
- 智慧零售-多标签服装与颜色图像分类
图像分类
根据各自在图像信息中所反映的不同特征,把不同类别的目标区分来的图像处理方法
如何写一个图像分类算法
输入:数据集
学习:这一步的任务是使用训练集来学习每个类到底长什么样。一般该步骤叫做训练分类器或者学习一个模型
评价:让分类器来预测它未曾见过的图像的分类标签,并以此来评价分类器的质量
图像分类项目的难点
- 视点变化
- 缩放变化
- 变形
- 闭合变化
- 背景杂乱
- 处理类内变化
图像分类方法
经典方法:SVM,神经网络等
深度学习方法:卷积神经网络
卷积神经网络
- 数据输入层
- 卷积计算层
- 激励层
- 池化层:降采样,压缩数据和参数的量,减少过拟合
- 全连接层
局部感知
参数共享
特征提取不充分:用多个卷积核来弥补,学习多种特征
尺度不变
卷积神经网络的训练过程
第一个阶段是数据由底层次向高层次传播的阶段,即前向传播阶段
第二个阶段是当前向传播得出的结果与预期不相符时,将误差从高层次向底层次进行传播训练的阶段,即反向传播阶段
经典模型
LeNet-5:7层,输入图像是32*32大小
AlexNet:使用Relu激活函数,Dropout(防止过拟合),标准化
VGGNet:常用的是VGG16,VGG19。卷积块的概念。
ResNet:深度残差网络,网络结构比较小
ResNeXt:新的block模块设计思路,网络结构简明,模块化,需要手动调节的超参少
项目一:智能交通行业-交通标志分类
无人驾驶汽车在运行中需要对交通标志进行有效的识别,从而完成决策。
训练集有39000个图像,测试集有12000个图像,61个类别。
项目流程:
- 图像预处理:图像亮度直方图均衡化;图像大小修改
- 图像网络架构
- 网络训练
- 网络可视化
- 效果评估
- 图像增强
- 图像再训练与评估
- 总结
训练的网络
class Triffic_Net: @staticmethod def build(width, height, depth, classes): model = Sequential() inputShape = (height, width, depth) if K.image_data_format() == 'channels_first': inputShape = (depth, height, width) 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))) model.add(Conv2D(50, (5, 5), padding='same')) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2))) model.add(Flatten()) model.add(Dense(500)) model.add(Activation('relu')) model.add(Dense(classes)) model.add(Activation('softmax')) return model
解析:
1.
@staticmethod:返回函数的静态方法。 静态方法无需实例化,也可以实例化后调用
class Time(): def __init__(self,sec): self.sec = sec #声明一个静态方法 @staticmethod def sec_minutes(s1,s2): #返回两个时间差 return abs(s1-s2)t = Time(10)#分别使用类名调用和使用实例调用静态方法print(Time.sec_minutes(10,5),t.sec_minutes(t.sec,5))#结果为5 5
2.Keras
Keras 的核心数据结构是 model,一种组织网络层的方式。最简单的模型是 Sequential 顺序模型,它由多个网络层线性堆叠。对于更复杂的结构,你应该使用 Keras 函数式 API,它允许构建任意的神经网络图。
网络层、损失函数、优化器、初始化策略、激活函数、正则化方法都是独立的模块,你可以使用它们来构建自己的模型。
![7e4da3f6d14482d68e557b4f467bbcc1.png](https://i-blog.csdnimg.cn/blog_migrate/6294b82c7cf0458be17e0cb1178e14cc.jpeg)
对keras的图解很详细,清晰https://www.cnblogs.com/Anita9002/p/8136357.html
3.
if K.image_data_format() == 'channels_first':image_data_format
返回默认图像的维度顺序
4.
from keras import backend as K
自定义各种层的时候,一般会import这个
数据输入
def load_data(path): data = [] labels = [] imagePaths = sorted(list(paths.list_images(path))) random.seed(42) random.shuffle(imagePaths) for imagePath in imagePaths: image = cv2.imread(imagePath) #图像大小32*32 image = cv2.resize(image, (image_size, image_size)) #转成keras类型 image = img_to_array(image) data.append(image) label = int(imagePath.split(os.path.sep)[-2]) labels.append(label) #归一化 data = np.array(data, dt ype='float')/255.0 labels = np.array(labels) #传入数据到keras labels = to_categorical(labels, num_classes=CLASSES_NUM) return data,labels
1.imutils是Adrian Rosebrock开发的一个python工具包,它整合了opencv、numpy和matplotlib的相关操作,主要是用来进行图形图像的处理,如图像的平移、旋转、缩放、骨架提取、显示等等,后期又加入了针对视频的处理,如摄像头、本地文件等。imutils同时支持python2和python3。
2. random.seed(42)
可以看到当seed()没有参数时,每次生成的随机数是不一样的,而当seed()有参数时,每次生成的随机数是一样的,同时选择不同的参数生成的随机数也不一样
3.random.shuffle(imagePaths)
随机把这些路径排序
4. label = int(imagePath.split(os.path.sep)[-2])
从图像路径中提取类标签并更新标签列表
os.path.join() 将分离的部分合成一个整体
os.path.splitext()将文件名和扩展名分开
os.path.split()返回文件的路径和文件名
5.labels = to_categorical(labels, num_classes=CLASSES_NUM)
把标签从整数变成矢量
to_categorical就是将类别向量转换为二进制(只有0和1)的矩阵类型表示
训练
def train(aug, trainX, trainY, testX, testY): print("[INFO] compiling model...") model = Triffic_Net.build(width=image_size, height=image_size, depth=3, classes=CLASSES_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) # save the model to disk print("[INFO] serializing network...") mp = "iris_model.h5" model.save(mp) model.save('class.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") plt.title("Training Loss and Accuracy on traffic-sign classifier") plt.xlabel("Epoch #") plt.ylabel("Loss/Accuracy") plt.legend(loc="lower left")
1.keras中的fit_generator是keras用来为训练模型生成批次数据的工具。它的输入可以是一个python生成器,也可以是一个Keras Sequence。
用生成器喂数据的优点,除了不依赖大内存以外,还具有非常多的优点。比如,它可以并行预处理数据,咱们的模型是运行在GPU上的,generator运行在CPU上,所以GPU跑模型,CPU预处理数据,这样就可以达到很高的时效性。
main
if __name__ == '__main__': trainpath = 'C:/Users/admin/Desktop/photoclass/S2/traffic-sign/traffic-sign/train' testpath = 'C:/Users/admin/Desktop/photoclass/S2/traffic-sign/traffic-sign/test' trainx, trainy = load_data(trainpath) testx, testy = load_data(testpath) 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)
主要函数:ImageDataGenerator 实现了大多数上文中提到的图像几何变换方法.
- rotation_range: 旋转范围, 随机旋转(0-180)度;
- width_shift and height_shift: 随机沿着水平或者垂直方向,以图像的长宽小部分百分比为变化范围进行平移;
- rescale: 对图像按照指定的尺度因子, 进行放大或缩小, 设置值在0 - 1之间,通常为1 / 255;
- shear_range: 水平或垂直投影变换, 参考这里 https://keras.io/preprocessing/image/
- zoom_range: 按比例随机缩放图像尺寸;
- horizontal_flip: 水平翻转图像;
- fill_mode: 填充像素, 出现在旋转或平移之后.
来强化图像
测试结果
![94f3ac5cce105706e2afc1abcccbe1e9.png](https://i-blog.csdnimg.cn/blog_migrate/772bbd5db646e479cae3a3318291dd3c.jpeg)
![845cc415a325310829752c92e6928670.png](https://i-blog.csdnimg.cn/blog_migrate/c71d2d375ee7a648283dc63223400ae8.jpeg)
模型肯定还需要优化!