深度学习花朵识别系统的设计与实现
摘要:该项目是基于Keras的VGG16模型微调实现的深度学习花朵识别检测系统,使用Python语言中的cv2和numpy库对图像进行预处理,使用keras的ImageDataGenerator进行数据增强,采用Pyqt5实现功能的可视化,方便用户对图片进行检测。在实验过程中,发现当数据集较小,很难在一个新的网络结构上训练出具有很高准确率的模型,可以借助预训练网络模型(即已经训练好的网络模型,如VGG16)。我们利用自己的数据集来重新训练这些模型的分类层,就可以获得比较高的准确率。在此基础上该模型调参优化得到了98%以上的准确率验证了微调模型有助于训练小样本模型。
一、项目设计的意义
1.1 研究背景和意义
二、项目采用的原理
2.1卷积神经网络
彩色图像有RGB三个颜色通道,可以用二维数组来表示。比如一张160x60的彩色图片,可以用160*60*3的数组表示。
Width= (5-3+2x0)/1+1,Height=(5-3+2x0)/1+1
对上述的例子进行padding填充,那么卷积后图片大小不会发生改变,如5x5的图像大小。
Padding=1变成为7x7,再用3x3的Filter进行卷积,那么卷积后的宽高为(7-3+2x1)/1+1=7
池化操作可以进行降维操作,有最大池化和平均池化,其中最大池化(Max Pooling)最为常用。
最大池化(Max Pooling)就是Filter对应区域内最大像素值替代该像素点值,其作用是降维池化使用的滤波器都是2x2大小,因此池化后得到的图像大小为原来的1/2。
Flatten可以将池化后的数据变成一维向量,方便输入到全连接网络。
全连接层是第n层的每个节点在进行计算的时候,激活函数的输入是n-1层所有节点的加权。
Dropout可以按照一定的比例将网络中的神经元进行丢弃,防止模型在训练过程中出现过拟合的情况。
2.2卷积神经网络VGG16详解
由上图所知,VGG16一共有五段卷积,每段卷积之后紧接着最大池化层,最后几层使用三层全连接层,最终接一个softmax。网络的输入是224x224大小的图像,输出的是图像分类结果。
在VGG网络的最后三层全连接层的参数在VGG的整体参数中占据了很大一部分,为了减少参数量,后几层的全连接网络都被全局平均池化和卷积操作代替了,但是全局平均池化也有很大的优点。
VGG对于Alexnet来说,改进并不是很大,主要改进就在于使用了小卷积核,网络是分段卷积网络,通过maxpooling过度,同时网络更深更宽。
基本概念理解之后,现在就可以进入到理解VGG16的网络模型了。
1.从Input到Conv_1:由于224不太好计算,使用input图片大小300x300x3举例:
Pooling使用Filter是2x2x64,且步长为2,得到的矩阵维数刚好为原来的一半,第三个维度64不改变,因为那个指的是Filter的个数。
Input为300x300x3的图片,经过第一层(里面由64个卷积核)。之后变成150x150x64。第二层里面由128个卷积核,由上述的规律可以推出第二层得到75x75x128。
第二层里面由256个卷积核,由上述的规律可以推出第二层得到75x75x256。
Layer (type) Output Shape Param # |
conv2d_1 (Conv2D) (None, 224, 224, 64) 1792 |
conv2d_2 (Conv2D) (None, 224, 224, 64) 36928 |
max_pooling2d_1 (MaxPooling2 (None, 112, 112, 64) 0 |
conv2d_3 (Conv2D) (None, 112, 112, 128) 73856 |
conv2d_4 (Conv2D) (None, 112, 112, 128) 147584 |
max_pooling2d_2 (MaxPooling2 (None, 56, 56, 128) 0 |
conv2d_5 (Conv2D) (None, 56, 56, 256) 295168 |
conv2d_6 (Conv2D) (None, 56, 56, 256) 590080 |
conv2d_7 (Conv2D) (None, 56, 56, 256) 590080 |
max_pooling2d_3 (MaxPooling2 (None, 28, 28, 256) 0 |
conv2d_8 (Conv2D) (None, 28, 28, 512) 1180160 |
conv2d_9 (Conv2D) (None, 28, 28, 512) 2359808 |
conv2d_10 (Conv2D) (None, 28, 28, 512) 2359808 |
max_pooling2d_4 (MaxPooling2 (None, 14, 14, 512) 0 |
conv2d_11 (Conv2D) (None, 14, 14, 512) 2359808 |
conv2d_12 (Conv2D) (None, 14, 14, 512) 2359808 |
conv2d_13 (Conv2D) (None, 14, 14, 512) 2359808 |
max_pooling2d_5 (MaxPooling2 (None, 7, 7, 512) 0 |
flatten_1 (Flatten) (None, 25088) 0 |
dense_1 (Dense) (None, 4096) 102764544 |
dropout_1 (Dropout) (None, 4096) 0 |
dense_2 (Dense) (None, 4096) 16781312 |
dropout_2 (Dropout) (None, 4096) 0 |
dense_3 (Dense) (None, 1000) 4097000 |
Total params: 138,357,544 |
Trainable params: 138,357,544 |
Non-trainable params: 0 |
三、项目设计方案
3.1关于数据的处理和分析
3.1.1基本概念
训练集:顾名思义指的是用于训练的样本集合,主要用来训练神经网络中的参数。
测试集:对于训练完成的神经网络,测试集用于客观的评价神经网络的性能。
# -*- coding:utf8 -*-
import os
class BatchRename():'''批量重命名文件夹中的图片文件'''def __init__(self):self.path = r'E:\flower_10\Blanket flower' self.label = ' Blanket flower_'def rename(self):filelist = os.listdir(self.path)total_num = len(filelist) #获取文件夹内所有文件个数i = 0 #表示文件的命名是从1开始的for item in filelist:if item.endswith(('.jpeg','png','jpg')):src = os.path.join(os.path.abspath(self.path), item)dst = os.path.join(os.path.abspath(self.path),
str(self.label)+str(i) + '.jpg')try:os.rename(src, dst)print ('converting %s to %s ...' % (src, dst))i = i + 1except:continueprint ('total %d to rename & converted %d jpgs' % (total_num, i))
if __name__ == '__main__':demo = BatchRename()demo.rename()
2.使用keras已有的数据增强的方法ImageDataGenerator
from keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(rescale=1./255,rotation_range=25,width_shift_range=0.1,height_shift_range=0.1,shear_range=0.1,zoom_range=0.1,horizontal_flip=True,vertical_flip = True,fill_mode = 'nearest')
1.在已经训练好的基网络(base network)上添加自定义网络
做特征提取的时候已经完成了前三个步骤。继续进行第四步:先解冻conv_base 然后冻结其中的部分层。
conv_base.trainable = True
set_trainable = False
for layer in conv_base.layers:if layer.name == 'block5_conv1':set_trainable = Trueif set_trainable:layer.trainable = Trueelse:layer.trainable = False
我们将微调最后三个卷积层,也就是说,知道block4_pool的所有层都应该被冻结,而block5_conv1,block_conv2和block_conv3三层应该是可以训练的。
为什么不微调更多的层数?为什么不微调整个卷积基?你当然可以这么做,但是需要考虑一下几点:
1.卷积基中更加靠近底部的层编码的是更加通用的可复用的特征,而更靠近顶部的层编码的是更专业化的特征。
3.训练的参数越多,过拟合的风险就越大。卷积基有1500万个参数,所以在小型数据集上训练这么多参数是有风险的。
# 微调模型
model.compile(loss='categorical_crossentropy',optimizer=optimizers.RMSprop(lr=1e-5),metrics=['acc'])
history = model.fit_generator(train_generator,steps_per_epoch=25,epochs=100,validation_data=validation_generator, validation_steps=32,shuffle=True)
# 测试集的准确率
test_datagen = test_datagen.flow_from_directory(test_dir,target_size=(100,100),batch_size=30,class_mode='categorical'
)
test_loss,test_acc = model.evaluate_generator(test_datagen,steps=30)
print('test acc:',test_acc)
# 良好实践,保存模型
model.save(r'.\model\flower.h5')
# 绘制训练过程中的损失函数曲线和精度曲线
import matplotlib.pyplot as plt
acc=history.history['acc']
val_acc=history.history['val_acc']
loss=history.history['loss']
val_loss=history.history['val_loss']
epochs=range(1,len(acc)+1)
plt.plot(epochs,acc,'bo',label='Training acc')
plt.plot(epochs,val_acc,'b',label='Validation acc')
plt.title('Training and Validation acc')
plt.legend()
plt.figure()
plt.plot(epochs,loss,'bo',label='Training loss')
plt.plot(epochs,val_loss,'b',label='Validation loss')
plt.title('Trainig and Validation loss')
plt.legend()
plt.show()
Training and Validation acc/loss图
公式:模型的错误率=预测的类别和已知的类别标签不同的个数/总的预测标签数
import os
flower_lst = ['Blanket flower', 'Daisy', 'Echinacea purpurea', 'Gazania rigens', 'Lily of the Valley', 'Lotus flower', 'Michelia figo Spreng', 'Pansy', 'Passion flower', 'Plumeria Acutifolia']
import numpy as np
from keras.models import load_model
model=load_model(r".\CNN_Flower\WY_6.h5")
from keras.preprocessing.image import ImageDataGenerator
test_datagen = ImageDataGenerator(rescale=1./255)
path = r'.\dir'
flower_path=r".\test"
test_generator = test_datagen.flow_from_directory(path, target_size=(100, 100),batch_size=1,class_mode='categorical', shuffle=False,)
#建立预测结果和文件名之间的关系
filenames = test_generator.filenames
length = len(os.listdir(flower_path))
test_generator.reset()
pred = model.predict_generator(test_generator, verbose=1, steps=length)
predicted_class_indices = np.argmax(pred, axis=1)
correct=0
error=0
filenames = test_generator.filenames
for i in range(len(filenames)):if filenames[i].split("\\")[1].split("_")[0]==flower_lst[predicted_class_indices[i]]:correct=correct+1else:error=error+1print("这张图片检测错误!!!!!!!", filenames[i].split("\\")[1])
print("模型识别图片的正确个数是:",correct)
print("模型识别图片的错误个数是:",error)
print("模型识别图片的准确率是:",correct/(correct+error))
from keras.models import load_model
import cv2
import imageio
from keras.models import Model, load_model
from keras.applications.imagenet_utils import preprocess_input
from keras.preprocessing import image
import numpy as np
import matplotlib.pyplot as plt
test_model=load_model(r".\CNN_Flower\model.h5")
import os
import numpy as np
all_path = r".\test"
lst = os.listdir(all_path)
for file_path in os.listdir(all_path):path = os.path.join(all_path,lst[label])for file_name in os.listdir(path)[0:len(os.listdir(path))]:img_path = os.path.join(path,file_name)src=cv2.imread(img_path)src=cv2.resize(src,(100,100))src=src.reshape((1,100,100,3))src=src.astype("int32")src=src/255predict = test_model.predict(src)predict = np.argmax(predict, axis=1)print(predict)
四、项目可视化
4.1 UI界面设计
首先进入cmd,然后执行命令pip install pyqt5和pip install pyqt5 pyqt5-tools。然后在这个画布上设计布局和空间,如下图所示。设计好之后在将其转为py文件。
def open_img(self):global imgNameimgName, imgType = QtWidgets.QFileDialog.getOpenFileNames(self.pushButton_2, "多文件选择","./test", "所有文件 (*);;文本文件 (*.txt)")if len(self.imglist) == 0:self.imglist = imgNameelse:for i in range(len(imgName)):self.imglist.append(imgName[i])from functools import reduceimg_func = lambda x, y: x if y in x else x + [y]self.imglist = reduce(img_func, [[], ] + self.imglist)slm = QStringListModel()slm.setStringList(self.imglist)self.listView.setModel(slm)print("HEHEDA")
def clicked(self, qModelIndex):global pathjpg = QtGui.QPixmap(self.imglist[qModelIndex.row()]).scaled(self.label.width(), self.label.height())self.label.setPixmap(jpg)path = self.imglist[qModelIndex.row()]self.pic_exists = 1self.predict_request = 1real_imglabel = path.split('/')real_imglabel = "真实花名:" + str(real_imglabel[-2])self.label_4.setText(real_imglabel)predict_flower_name = '预测花名:'self.label_5.setText(predict_flower_name)
def predict_request_add(self):if self.predict_request<1:self.predict_request = self.predict_request + 1
def predict(self):if self.pic_exists and self.predict_request:print("模型测试正式开始")import osimport cv2import numpy as npimg_path = pathsrc = cv2.imread(img_path)src = cv2.resize(src, (100, 100))src = src.reshape((1, 100, 100, 3))src = src.astype("int32")src = src / 255predict = self.model.predict(src)predict = np.argmax(predict, axis=1)print("预测结果是:")print(self.img_label[predict[0]])predict_flower_name = self.img_label[predict[0]]predict_flower_name = '预测花名:' + predict_flower_nameself.label_5.setText(predict_flower_name)print("执行中....")self.predict_request = 0else:print("请选择图片!!!!!")print("执行结束")
我是热爱学习的呵呵哒~如果你觉得文章很棒,对你有帮助的话,可以点赞+收藏+加关注喔~
如果文章有不正确的地方,欢迎交流指正,我将虚心请教~o(>ω<)o
我会定期更新文章,继续为您提供优质文章
后期呵呵哒将会把整个项目发到Github和其他平台供大家参考学习!!!
深度学习花朵识别系统的设计与实现相关推荐
- keras冻结_【连载】深度学习第22讲:搭建一个基于keras的迁移学习花朵识别系统(附数据)...
在上一讲中,和大家探讨了迁移学习的基本原理,并利用 keras 基于 VGG16 预训练模型简单了在 mnist 数据集上做了演示.鉴于大家对于迁移学习的兴趣,本节将继续基于迁移学习利用一些花朵数据搭 ...
- 【毕业设计】深度学习水果识别系统 - python CNN
文章目录 1 前言 2 开发简介 3 识别原理 3.1 传统图像识别原理 3.2 深度学习水果识别 4 数据集 5 部分关键代码 5.1 处理训练集的数据结构 5.2 模型网络结构 5.3 训练模型 ...
- 【毕业设计】深度学习车牌识别系统 - opencv 卷积神经网络 机器学习
文章目录 0 简介 1 车牌识别原理和流程 1.1 车牌定位 1.2 基于图形图像学的定位方法. 1.3 基于机器学习的定位方法. 1.4 字符分割 1.5 字符识别 2 基于机器学习的车牌识别 2. ...
- 【毕业设计】深度学习身份证识别系统 - 机器视觉 python
文章目录 0 前言 1 实现方法 1.1 原理 1.1.1 字符定位 1.1.2 字符识别 1.1.3 深度学习算法介绍 1.1.4 模型选择 2 算法流程 3 部分关键代码 4 效果展示 5 最后 ...
- 【毕业设计】深度学习人脸识别系统 - python opencv 卷积神经网络
文章目录 0 简介 1 人脸识别 - 常用实现技术 1.1 基于几何特征的人脸识别方法 1.2 初级神经网络方法. 1.3 深度学习方法. 2 人脸识别算法缺陷 3 人脸识别流程 3.1 相关数据集 ...
- 【毕业设计】深度学习花卉识别系统 - 卷积神经网络 机器视觉
文章目录 0 前言 1 项目背景 2 花卉识别的基本原理 3 算法实现 3.1 预处理 3.2 特征提取和选择 3.3 分类器设计和决策 3.4 卷积神经网络基本原理 4 算法实现 4.1 花卉图像数 ...
- 【毕业设计】深度学习动物识别系统 - python 卷积神经网络 机器视觉
文章目录 0 前言 1 背景 2 算法原理 2.1 动物识别方法概况 2.2 常用的网络模型 2.2.1 B-CNN 2.2.2 SSD 3 SSD动物目标检测流程 4 实现效果 5 部分相关代码 5 ...
- 大数据毕设 - 深度学习植物识别系统(python OpenCV)
文章目录 0 前言 2 相关技术 2.1 VGG-Net模型 2.2 VGG-Net在植物识别的优势 (1) 卷积核,池化核大小固定 (2) 特征提取更全面 (3) 网络训练误差收敛速度较快 3 VG ...
- 【毕业设计】深度学习车牌识别系统 - yolo python
文章目录 0 前言 1 课题介绍 2 算法简介 2.1网络架构 3 数据准备 4 模型训练 5 实现效果 5.1 图片识别效果 5.2视频识别效果 6 部分关键代码 7 最后 0 前言
最新文章
- 考夫曼:破解大脑代码并创建真正的人工智能
- java 通常在函数内部创建对象还是在外部创建对象_java中为什么在主函数中创建外部类对象可以,创建内部类对象就失败了呢?2类不都是非静态的吗?...
- linux mysql 密码文件怎么打开文件,Oracle数据库密码文件创建与使用
- 2011年5月19日盘后分析:把握行情运行主线 静待大盘明确信号
- WebBenchmark动态测试Webapi
- com.sec.android.app.smartclipservice,EPR Aerospace News
- xp变量 java_winxp系统设置java环境变量的详细教程
- 基于 Android NDK 的学习之旅-----Java 调用C(附源码)
- centos上部署java环境
- java+lua互相调用_Lua学习 2) —— Android与Lua互调
- 手机客户端应用功能测试方法总结
- 最小二乘法拟合直线-C++实现
- win10禁用uac_在Win 7、8或10上通过简便方法禁用用户帐户控制(UAC)
- uniapp,小程序返回到指定页面以及到指定页面左上角的房型默认返回首页
- GPGPU-Sim学习(二)搭建GPGPU-Sim环境(ubuntuServer 10.04 安装GPGPU-Sim)
- 电脑数据怎么迁移?6种旧电脑数据传输到新电脑方法分享
- Mac系统升级Python版本(Python2.7升级到Python3.8.2)
- 单反相机镜头的ldquo;三大纪律,八项注意rdquo;
- 2022年长安杯比赛复现
- Quartz定时任务调度框架
热门文章
- 高中物理应用计算机教学心得,高中物理教学心得
- 【工程源码】CYUSB3014芯片使用EEPROM无法下载固件说明
- 电子游戏设计与制作 第一章 计算机游戏概述
- Java多线程中wait, notify and notifyAll的使用
- Cannot create PoolableConnectionFactory (Communications link failure due to unde
- angular RxJs
- 轻雀协作客户最佳实践之凯叔讲故事
- react-router-dom ^6.0.2使用过程中报错 Error: A <Route> is only ever to be used as the child of <Routes>
- VLP-16第一课: Velodyne的工作原理和驱动安装
- 结合知识蒸馏的增量学习方法总结