本项目主要使用PYTHONKeras框架,对轿车、卡车、摩托车进行识别学习。
然后使用Keras的图片数据增强,来增加识别的准确度。
由于的图片数量集数量有限,所以我们采用数据增强(dataaugmentation)技术来降低过拟合,并提高神经网络的识别精度。
对于数据集,我采用的是百度旗下飞浆学习里面的数据集。
如果有需要可以去这个网址进行学习。
这个平台有非常多的数据集可以使用。
先对下载的数据集进行分类
我们先创建以下三个文件夹来作为不同的数据集
然后在训练集(train)里面再分为三个小类。
分别为:轿车(car)摩托车(motorcycle)卡车(truck)
这样我们的训练集都准备好了
检查一下每个分组(训练/测试)中分别包含多少张图像
1#检查一下每个分组(训练/测试)中分别包含多少张图像2importos34train_path="D:/data/train/"5print('totaltrainingcarimages:',len(os.listdir(train_path+"car")))6print('totaltrainingmotorcycleimages:',len(os.listdir(train_path+"motorcycle")))7print('totaltrainingtruckimages:',len(os.listdir(train_path+"truck")))8valid_path="D:/data/validation/"9print('totalvalidationcarimages:',len(os.listdir(valid_path+"car")))10print('totalvalidationmotorcycleimages:',len(os.listdir(valid_path+"motorcycle")))11print('totalvalidationtruckimages:',len(os.listdir(valid_path+"truck")))1213test_path="D:/data/test/"14print('totaltestimages:',len(os.listdir(test_path)))显示结果:
修改训练集的图片名称
1#修改训练集的图片名称2importos3defrename(path,name):4filelist=os.listdir(path)5total_num=len(filelist)6print(total_num)7i=08foriteminfilelist:9ifitem.endswith('.png'):10src=os.path.join(os.path.abspath(path),item)11dst=os.path.join(os.path.abspath(path),name+'.'+str(i)+'.png')12print(item,i)13try:1415os.rename(src,dst)16print("converting%sto%s..."%(src,dst))17i=i+118except:19continue202122rename('D:/data/train/car','car')23rename('D:/data/train/motorcycle','motorcycle')24rename('D:/data/train/truck','truck')显示结果
构建网络
在完成了数据集的清洗任务后,我们就需要搭建卷积神经网络了,我们使用Keras中的Sequential就可以完成网络构建的任务。
卷积神经网络结构由Conv2D层(使用relu函数激活)和MaxPooling2D层交替堆叠构成,这样既可以增大网络容量,也可以减少特征图的尺寸。
神经网络的最后两个层采用全连接层,分别采用relu和sigmoid激活。
在构建时我们先不采用数据增强,来查看训练的结果如何。
1#显示模型的层级结构2model.summary()显示结果
从输出可以看出,神经网络在dense_1(Dense)层的参数总数达到了900多万。
模型编译
使用RNSprop优化器。因为网络的最后一层时单一sigmoid单元,所以使用二元交叉熵作为损失函数。
1#编译模型2model.compile(optimizer=optimizers.RMSprop(lr=1e-4),loss='binary_crossentropy',metrics=['acc'])训练模型
1#训练模型2history=model.fit_generator(train_gen,epochs=15,validation_data=val_gen)显示结果
绘制损失曲线和精度曲线
1importmatplotlib.pyplotaspl23#绘制训练精度损失曲线4acc=history.history['acc']5val_acc=history.history['val_acc']6loss=history.history['loss']7val_loss=history.history['val_loss']89epochs=range(1,len(acc)+1)1011plt.plot(epochs,acc,'bo',label='Trainingacc')12plt.plot(epochs,val_acc,'b',label='Validationacc')13plt.title('Trainingandvalidationaccuracy')14plt.legend()1516plt.figure()1718plt.plot(epochs,loss,'bo',label='Trainingloss')19plt.plot(epochs,val_loss,'b',label='Validationloss')20plt.title('Trainingandvalidationloss')21plt.legend()2223plt.show()显示结果
而我们可以采用数据增强的方法来增强我们的准确值。
使用数据增强
ImageDataGenerator参数
1#定义ImageDataGenerator参数2datagen=ImageDataGenerator(3rotation_range=40,4width_shift_range=0.2,5height_shift_range=0.2,6shear_range=0.2,7zoom_range=0.2,8horizontal_flip=True,9fill_mode="nearest")这些的参数的意义如下:
1、rotaion_range是角度值,表示图像随机旋转的范围。
2、width_shift和height_shift是图像在水平和垂直方向上平移的范围。3、shear_range是随机错切变换的角度。
4、zoom_range是图像随机缩放的范围。
5、horizontal_flip是将图像随机做水平翻转。
6、fill_mode是用于填充新创建像素的方法。随机增强一个图片
1#利用ImageDataGenerator实现数据增强23fromkeras.preprocessing.imageimportImageDataGenerator4fromkeras.preprocessingimportimage5importos6importmatplotlib.pyplotasplt78#定义训练集目录9train_car_dir="D:/data/train/car"1011#获得所有样本名称12car_fanmes=[os.path.join(train_car_dir,fname)forfnameinos.listdir(train_car_dir)]131415#定义ImageDataGenerator参数16datagen=ImageDataGenerator(17rotation_range=40,18width_shift_range=0.2,19height_shift_range=0.2,20shear_range=0.2,21zoom_range=0.2,22horizontal_flip=True,23fill_mode="nearest")242526img_path=car_fanmes[14]#选一张图片观察27img=image.load_img(img_path,target_size=(150,150))#读取图像并调整大小28x=image.img_to_array(img)#转换为形状(150,150,3)的numpy数组29x=x.reshape((1,)+x.shape)#将其形状改变为(1,150,150,3)3031i=032forbatchindatagen.flow(x,batch_size=1):#循环是无限的,需要在某个时刻终止循环33plt.figure(i)34imgplot=plt.imshow(image.array_to_img(batch[0]))35i+=136ifi%4==0:37break38plt.show()显示结果
使用数据增强后重新构建模型
训练的数据展示
1importmatplotlib.pyplotasplt23#绘制训练精度损失曲线4acc=history.history['acc']5val_acc=history.history['val_acc']6loss=history.history['loss']7val_loss=history.history['val_loss']89epochs=range(1,len(acc)+1)1011plt.plot(epochs,acc,'bo',label='Trainingacc')12plt.plot(epochs,val_acc,'b',label='Validationacc')13plt.title('Trainingandvalidationaccuracy')14plt.legend()1516plt.figure()1718plt.plot(epochs,loss,'bo',label='Trainingloss')19plt.plot(epochs,val_loss,'b',label='Validationloss')20plt.title('Trainingandvalidationloss')21plt.legend()2223plt.show()显示结果
通过图表可以看出,随着训练批次的增加,对应的评价参数基本是一直上升的,没有出现严重的过拟合现象,最后使用测试及验证,准确率大概在89%左右。
图像增强时只增加了一层dropout层,如果再增加过滤器层和调节其他参数,可以得到更高的精度,大概能在95%。
保存模型
1#将训练过程产生的数据保存为h5文件2model.save('car.h5')对模型进行检测
读取自定义图像并改变形状
1#读取用户自定义图像文件,改尺寸后保存23importmatplotlib.pyplotasplt4fromPILimportImage5importos.path67defconvertjpg(jpgfile,outdir,width=224,height=224):#将图片缩小到(224,224)的大小8img=Image.open(jpgfile)9try:10new_img=img.resize((width,height),Image.BILINEAR)11new_img.save(os.path.join(outdir,os.path.basename(jpgfile)))12exceptExceptionase:13print(e)1415jpgfile='D:/data/test/car.27.jpg'#读取原图像16convertjpg(jpgfile,"D:/data/")#图像大小改变到(224,224)1718img_scale=plt.imread('D:/data/car.27.jpg')19plt.imshow(img_scale)#显示改变图像大小后的图片确实变到了(224,224)大小显示结果
实现识别
1###导入模型car.h523fromkeras.modelsimportload_model4model=load_model('car.h5')56img_scale=img_scale.reshape(-1,224,224,3).astype('float32')7img_scale=img_scale/255#归一化到0-1之间89result=model.predict(img_scale)#取图片信息10print(result)显示结果
再次识别
识别结果
结论
通过上面的两个列子可以得出。
我们自定义的图像对于轿车的识别率高达了84%,自定义的图像对于卡车的识别占有69%。说明我们对车辆的识别成功。
建议
1、后面我们可以增加数据集的数量,来提高一些准确度。
2、可以增加更多的汽车种类。
3、可以设计出图形化界面,这样就不用每一次都需要手动修改代码了。