今年国产造车新势力都有不俗的表现,身边开的最多的莫过于比亚迪的汽车了,这个也得益于比亚迪庞大的产品网络,有时候往往会觉得不同车系车型容易混淆,今天趁着有时间就想着自己开发一套识别比亚迪不同车型的图像识别系统,首先看下实例效果:
VGG(Visual Geometry Group)是由Simonyan和Zisserman在2014年提出的一种经典的卷积神经网络模型。VGG模型的构建原理如下:
-
输入图像以固定的尺寸传递给模型。
-
VGG模型由一系列卷积层和池化层组成。每个卷积层使用小尺寸(通常为3x3)的卷积核进行卷积操作,并使用ReLU激活函数进行非线性变换。池化层通常采用最大池化(Max Pooling)操作,通过对输入图像的不重叠区域进行子采样来减小特征图的尺寸。
-
VGG模型的核心思想是通过多个卷积层和池化层的堆叠来增加模型的深度。VGG模型以不同的配置命名,例如VGG16和VGG19,表示模型中卷积层和池化层的数量和顺序。
-
在VGG模型的顶部,通常包含一些全连接层。这些全连接层将特征图展平为一维向量,并通过一系列的全连接层进行分类。最后一层使用softmax激活函数输出不同类别的概率分布,用于图像分类任务。
VGG模型通过堆叠多个卷积层和池化层来构建深度神经网络,以实现对图像特征的学习和编码。VGG模型的深度和简单的卷积层结构使得它成为了一个经典的基准模型,在图像分类等计算机视觉任务上取得了很好的性能。
平时使用到的主要是VGG-16和VGG-19模型,这里基于keras给出对应的模型实现,可供直接集成到自己的项目中进行使用。
【VGG-16】
#coding=utf-8
from keras.models import Sequential
from keras.layers import Dense,Flatten,Dropout
from keras.layers.convolutional import Conv2D,MaxPooling2D
import numpy as np
seed = 7
np.random.seed(seed)
model = Sequential()
model.add(Conv2D(64,(3,3),strides=(1,1),input_shape=(224,224,3),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(Conv2D(64,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(128,(3,2),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(Conv2D(128,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(256,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(Conv2D(256,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(512,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(Conv2D(512,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(512,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(Conv2D(512,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Flatten())
model.add(Dense(4096,activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(4096,activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1000,activation='softmax'))
model.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])
model.summary()
【VGG-19】
#coding=utf-8
from keras.models import Sequential
from keras.layers import Dense,Flatten,Dropout
from keras.layers.convolutional import Conv2D,MaxPooling2D
import numpy as np
seed = 7
np.random.seed(seed)
model = Sequential()
model.add(Conv2D(64,(3,3),strides=(1,1),input_shape=(224,224,3),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(Conv2D(64,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(128,(3,2),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(Conv2D(128,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(256,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(Conv2D(256,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(Conv2D(256,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(512,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(Conv2D(512,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(Conv2D(512,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(512,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(Conv2D(512,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(Conv2D(512,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Flatten())
model.add(Dense(4096,activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(4096,activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1000,activation='softmax'))
model.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])
model.summary()
本文使用到的数据集来源于网络数据采集与人工处理,主要是收集了常见的100多种中药药材,数据集加载解析处理实现如下:
# 加载解析创建数据集
if not os.path.exists("dataset.json"):
train_dataset = []
test_dataset = []
all_dataset = []
classes_list = os.listdir(datasetDir)
classes_list.sort()
num_classes = len(classes_list)
if not os.path.exists("labels.json"):
with open("labels.json","w") as f:
f.write(json.dumps(classes_list))
print("classes_list: ", classes_list)
for one_label in os.listdir(datasetDir):
oneDir = datasetDir + one_label + "/"
for one_pic in os.listdir(oneDir):
one_path = oneDir + one_pic
one_ind = classes_list.index(one_label)
all_dataset.append([one_ind, one_path])
train_ratio = 0.90
train_num = int(train_ratio * len(all_dataset))
all_inds = list(range(len(all_dataset)))
train_inds = random.sample(all_inds, train_num)
test_inds = [one for one in all_inds if one not in train_inds]
for one_ind in train_inds:
train_dataset.append(all_dataset[one_ind])
for one_ind in test_inds:
test_dataset.append(all_dataset[one_ind])
简单看下实例数据:
【比亚迪e2】
【方程豹豹5】
【比亚迪护卫舰07】
【比亚迪仰望U8】
这里也没有收集到所有的车型,我这里只是个人兴趣实践性质的项目,我收集的车型清单如下所示:
默认100次epoch的迭代计算,等待训练完成后对整体训练过程进行可视化,如下所示:
【准确率曲线】
【损失曲线】
可视化推理实例如下所示:
感兴趣的话可以收集更全更细粒度的车型数据集来开发构建自己的识别模型。