基于卷积神经网络的野外可食用植物分类系统

2024-03-09 11:36

本文主要是介绍基于卷积神经网络的野外可食用植物分类系统,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 温馨提示:文末有 CSDN 平台官方提供的学长 QQ 名片 :) 

1. 项目简介

        本文详细探讨了一基于深度学习的可食用植物图像识别系统。采用TensorFlow和Keras框架,利用卷积神经网络(CNN)进行模型训练和预测,并引入迁移学习模型,取得91%的高准确率。通过搭建Web系统,用户能上传待测可食用植物图片,系统实现了自动实时的分类识别。该系统不仅展示了深度学习在生物学领域的实际应用,同时为用户提供了一种高效、准确的野外可食用支付分类识别服务。

【演示视频】基于卷积神经网络的野外可食用植物分类系统

2. 卷积神经网络

2.1 卷积层

卷积层作为输入层后的第一层,主要目的是提取输入的特征表示。卷积层是由多个特征图组成,每个特征图由多个神经元组成,每个神经元通过卷积核与上一层特征图的局部区域相连。卷积核是一个带权值的矩阵,用于提取和计算不同的特征映射。

2.1.1 卷积核

卷积核,又叫滤波器,给定输入图像,输入图像中一个小区域中像素,加权后成为输出图像中的每个对应像素,其中权值即为卷积核。也就是说,卷积核实际上可以理解为是一个权值矩阵。
卷积所得的输出的计算公式为:

式中:Xi为输入特征图,Yj为输出特征图,权值记为Wij,bj是其偏置参数。

2.1.2 卷积运算

如图所示,对应相乘:-1x1+1x(-1)+2x0+1x(-1)+(-1)x(-2)+2x3+0x1+(-1)x2+(-2)x(-2)=7,完成了一次卷积运算,可以将卷积核作为一个权值矩阵,对图片不同位置进行运算时,共享权值。卷积神经网络每一层输出的特征图上的像素点在输入图片上映射的区域大小叫做感受野(绿色框)。

Image Name

2.1.3 多通道卷积运算

灰度图:灰度图像只有一个通道,把白色与黑色之间按对数关系分为若干等级,称为灰度。灰度分为256阶(0-255),数字越大越接近白色,越小越接近黑色 。

RGB图:彩色图有三个通道,是通过对红R、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红、绿、蓝三个通道的颜色。(每像素颜色16777216(256 * 256 * 256)种)其中R、G、B由不同的灰度级来描述,每个分量有256级灰度(0-255)

多通道卷积运算:多通道输入,单核卷积,卷出来之后相加(以三通道,单核卷积为例子)

Image Name

简单说,卷积是乘法,通道间是加法

2.1.4 padding

以下图为例,5x5的图片矩阵,经过3x3的卷积核,滑动步长为1的卷积运算,得到的特征图大小为:(5-3+1)x(5-3+1)
很明显,随着卷积次数的增加,卷积后的矩阵会越变越小,而且图像的边缘计算次数会小于图像的内部。
所以进行padding操作,即边缘补0,如下图所示,变成了(7-3+1)x(7-3+1)=5x5,得到的特征图大小个原来一样
这样解决了图像越卷越小和边缘计算次数少的问题

Image Name

2.2 池化层

2.2.1 原理和计算方法

基于局部相关性的思想,通过从局部相关的一组元素中进行采样或信息聚合,从而得到新的元素值。
平均池化层:从局部相关元素集中计算平均值并返回
x = avg({1,0,-2,1})=0
最大池化层:从局部相关元素集中选取最大的一个元素值
x = max({1,0,-2,1})=1

Image Name

2.2.2 池化层选择

特征提取的误差主要来自两个方面:

(1)邻域大小受限造成的估计值方差增大;

(2)卷积层参数误差造成估计均值的偏移。

平均池化层能减小第一种误差,更多的保留图像的背景信息,最大池化层能减小第二种误差,更多的保留纹理信息。

2.3 Flatten层

用于将输入层的数据压成一维的数据,因为卷积层处理的是二维数据,全连接层只能接收一维数据,所以用在卷积层和全连接层之间,

2.4 激活函数

激活函数的主要作用是提供网络的非线性建模能力。如果没有激活函数,那么该网络仅能够表达线性映射,此时即便有再多的隐藏层,其整个网络跟单层神经网络也是等价的。因此也可以认为,只有加入了激活函数之后,深度神经网络才具备了分层的非线性映射学习能力。

3. 可食用植物分类建模

3.1 加载数据集

该数据集包含了 4005 个可食用植物的图片。数据集的创建者将图片分为了 52 个类别,利用 TensorFlow 的 `tf.keras.preprocessing.image_dataset_from_directory` 函数进行数据集的加载。

plt.figure(figsize=(20, 10))for images, labels in train_ds.take(1):labels = [tf.argmax(i) for i in labels]  for i in range(30):ax = plt.subplot(5, 10, i + 1)plt.imshow(images[i].numpy().astype("uint8"))plt.title(class_names[labels[i]])plt.axis("off")

folders = os.listdir('dataset')train_number = []
class_num = []for folder in folders:train_files = os.listdir('./dataset/' + folder)train_number.append(len(train_files))class_num.append(folder)# 不同类别数量,并进行排序
zipped_lists = zip(train_number, class_num)
sorted_pairs = sorted(zipped_lists)
tuples = zip(*sorted_pairs)
train_number, class_num = [ list(t) for t in  tuples]# 绘制不同类别数量分布柱状图
plt.figure(figsize=(21,10))  
plt.bar(class_num, train_number)
plt.xticks(class_num, rotation='vertical', fontsize=16)
plt.title('不同类别可食用植物样本数量分布柱状图', fontsize=30)
plt.show()

3.2 卷积神经网络模型构建

model = models.Sequential([layers.experimental.preprocessing.Rescaling(1./255, input_shape=(img_height, img_width, 3)),layers.Conv2D(16, (3, 3), activation='relu', input_shape=(img_height, img_width, 3)), # 卷积层1,卷积核3*3  layers.MaxPooling2D((2, 2)),               # 池化层1,2*2采样layers.Conv2D(32, (3, 3), activation='relu'),  # 卷积层2,卷积核3*3layers.MaxPooling2D((2, 2)),               # 池化层2,2*2采样layers.Conv2D(64, (3, 3), activation='relu'),  # 卷积层3,卷积核3*3layers.Dropout(0.2),  layers.Flatten(),                       # Flatten层,连接卷积层与全连接层layers.Dense(128, activation='relu'),   # 全连接层,特征进一步提取layers.Dense(len(class_names))               # 输出层,输出预期结果
])model.summary()  # 打印网络结构

3.3 模型训练与评估

from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStoppingepochs = 20# 保存最佳模型参数
checkpointer = ModelCheckpoint('best_model.h5',monitor='val_accuracy',verbose=1,save_best_only=True,save_weights_only=True)# 设置早停
earlystopper = EarlyStopping(monitor='val_accuracy', min_delta=0.001,patience=10, verbose=1)history = model.fit(train_ds,validation_data=val_ds,epochs=epochs,callbacks=[checkpointer, earlystopper]
)

 3.4 基于迁移学习的模型优化

 构建VGG模型结构,加载预训练的 VGG16 模型权重:

VGG16_model_con = models.Sequential([
#两次使用64个3*3的卷积核,池化后维度(112,112,64)layers.Conv2D(64, (3, 3),padding='same', activation='relu',name='block1_conv1', input_shape=(img_height, img_width, 3)), layers.Conv2D(64, (3, 3), padding='same',activation='relu',name='block1_conv2'),     layers.AveragePooling2D(pool_size=(2,2),strides=(2,2), name = 'block1_pool'),  
#两次使用128个3*3的卷积核,池化后维度(56,56,128)   layers.Conv2D(128, (3, 3),padding='same',activation='relu',name='block2_conv1'), layers.Conv2D(128, (3, 3),padding='same',activation='relu',name='block2_conv2'),     layers.AveragePooling2D(pool_size=(2,2),strides=(2,2), name = 'block2_pool'),  
#三次使用256个3*3的卷积核,池化后维度(28,28,256)layers.Conv2D(256, (3, 3), padding='same',activation='relu',name='block3_conv1'),     layers.Conv2D(256, (3, 3), padding='same',activation='relu',name='block3_conv2'),   layers.Conv2D(256, (3, 3),padding='same',activation='relu',name='block3_conv3'),     layers.AveragePooling2D(pool_size=(2,2),strides=(2,2), name = 'block3_pool'), 
#三次使用512个3*3的卷积核,池化后维度(14,14,512)layers.Conv2D(512, (3, 3),padding='same',activation='relu',name='block4_conv1'),     layers.Conv2D(512, (3, 3),padding='same',activation='relu',name='block4_conv2'),   layers.Conv2D(512, (3, 3),padding='same',activation='relu',name='block4_conv3'),     layers.AveragePooling2D(pool_size=(2,2),strides=(2,2), name = 'block4_pool'), layers.Conv2D(512, (3, 3),padding='same',activation='relu',name='block5_conv1'),     layers.Conv2D(512, (3, 3),padding='same',activation='relu',name='block5_conv2'),   layers.Conv2D(512, (3, 3),padding='same',activation='relu',name='block5_conv3'),     layers.AveragePooling2D(pool_size=(2,2),strides=(2,2), name = 'block5_pool'),    
])
VGG16_model_con.summary()# 加载模型参数
VGG16_model_con.load_weights('./vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5')
# 冻结前13层网络参数  保证加载的预训练参数不被改变
for layer in VGG16_model_con.layers[:13]:layer.trainable = False

Epoch 1/40
101/101 [==============================] - ETA: 0s - loss: 3.9311 - accuracy: 0.0471
Epoch 1: val_accuracy improved from -inf to 0.15231, saving model to best_model.h5
101/101 [==============================] - 220s 2s/step - loss: 3.9311 - accuracy: 0.0471 - val_loss: 3.5434 - val_accuracy: 0.1523
Epoch 2/40
101/101 [==============================] - ETA: 0s - loss: 3.2008 - accuracy: 0.2253
Epoch 2: val_accuracy improved from 0.15231 to 0.40574, saving model to best_model.h5
101/101 [==============================] - 220s 2s/step - loss: 3.2008 - accuracy: 0.2253 - val_loss: 2.4415 - val_accuracy: 0.4057
Epoch 3/40
101/101 [==============================] - ETA: 0s - loss: 2.0040 - accuracy: 0.4863
Epoch 3: val_accuracy improved from 0.40574 to 0.67291, saving model to best_model.h5
......
101/101 [==============================] - 235s 2s/step - loss: 0.0106 - accuracy: 0.9981 - val_loss: 0.5884 - val_accuracy: 0.9089
Epoch 17/40
101/101 [==============================] - ETA: 0s - loss: 0.0069 - accuracy: 0.9984
Epoch 17: val_accuracy did not improve from 0.90886
101/101 [==============================] - 225s 2s/step - loss: 0.0069 - accuracy: 0.9984 - val_loss: 0.6261 - val_accuracy: 0.9076
Epoch 17: early stopping

4.5 模型加载预测

 加载训练后的模型权重,对待测试植物图片进行类别预测:

from PIL import Image
import numpy as npfor cate in class_names:test_dir = f"./dataset/{cate}"files = os.listdir(test_dir)img = Image.open("./dataset/{}/{}".format(cate, files[0]))  img = np.array(img)plt.imshow(img)image = tf.image.resize(img, [img_height, img_width])img_array = tf.expand_dims(image, 0)predictions = VGG16_model_all.predict(img_array) pred_class = class_names[np.argmax(predictions)]if pred_class == cate:plt.title(f"实际类别:{cate}, 预测结果为:{pred_class}", color='green', size=18)else:plt.title(f"实际类别:{cate}, 预测结果为:{pred_class}", color='red', size=18)plt.show()

4. 可食用植物分类系统

4.1 首页介绍与注册登录

4.2 可食用植物在线预测 

5. 结论

        本文详细探讨了一基于深度学习的可食用植物图像识别系统。采用TensorFlow和Keras框架,利用卷积神经网络(CNN)进行模型训练和预测,并引入迁移学习模型,取得91%的高准确率。通过搭建Web系统,用户能上传待测可食用植物图片,系统实现了自动实时的分类识别。该系统不仅展示了深度学习在生物学领域的实际应用,同时为用户提供了一种高效、准确的野外可食用支付分类识别服务。

 欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。技术交流、源码获取认准下方 CSDN 官方提供的学长 QQ 名片 :)

精彩专栏推荐订阅:

1. Python数据挖掘精品实战案例

2. 计算机视觉 CV 精品实战案例

3. 自然语言处理 NLP 精品实战案例

这篇关于基于卷积神经网络的野外可食用植物分类系统的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/790553

相关文章

基于Python实现一个简单的题库与在线考试系统

《基于Python实现一个简单的题库与在线考试系统》在当今信息化教育时代,在线学习与考试系统已成为教育技术领域的重要组成部分,本文就来介绍一下如何使用Python和PyQt5框架开发一个名为白泽题库系... 目录概述功能特点界面展示系统架构设计类结构图Excel题库填写格式模板题库题目填写格式表核心数据结构

Linux系统中的firewall-offline-cmd详解(收藏版)

《Linux系统中的firewall-offline-cmd详解(收藏版)》firewall-offline-cmd是firewalld的一个命令行工具,专门设计用于在没有运行firewalld服务的... 目录主要用途基本语法选项1. 状态管理2. 区域管理3. 服务管理4. 端口管理5. ICMP 阻断

Windows 系统下 Nginx 的配置步骤详解

《Windows系统下Nginx的配置步骤详解》Nginx是一款功能强大的软件,在互联网领域有广泛应用,简单来说,它就像一个聪明的交通指挥员,能让网站运行得更高效、更稳定,:本文主要介绍W... 目录一、为什么要用 Nginx二、Windows 系统下 Nginx 的配置步骤1. 下载 Nginx2. 解压

如何确定哪些软件是Mac系统自带的? Mac系统内置应用查看技巧

《如何确定哪些软件是Mac系统自带的?Mac系统内置应用查看技巧》如何确定哪些软件是Mac系统自带的?mac系统中有很多自带的应用,想要看看哪些是系统自带,该怎么查看呢?下面我们就来看看Mac系统内... 在MAC电脑上,可以使用以下方法来确定哪些软件是系统自带的:1.应用程序文件夹打开应用程序文件夹

windows系统上如何进行maven安装和配置方式

《windows系统上如何进行maven安装和配置方式》:本文主要介绍windows系统上如何进行maven安装和配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录1. Maven 简介2. maven的下载与安装2.1 下载 Maven2.2 Maven安装2.

使用Python实现Windows系统垃圾清理

《使用Python实现Windows系统垃圾清理》Windows自带的磁盘清理工具功能有限,无法深度清理各类垃圾文件,所以本文为大家介绍了如何使用Python+PyQt5开发一个Windows系统垃圾... 目录一、开发背景与工具概述1.1 为什么需要专业清理工具1.2 工具设计理念二、工具核心功能解析2.

Linux系统之stress-ng测压工具的使用

《Linux系统之stress-ng测压工具的使用》:本文主要介绍Linux系统之stress-ng测压工具的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、理论1.stress工具简介与安装2.语法及参数3.具体安装二、实验1.运行8 cpu, 4 fo

ubuntu20.0.4系统中安装Anaconda的超详细图文教程

《ubuntu20.0.4系统中安装Anaconda的超详细图文教程》:本文主要介绍了在Ubuntu系统中如何下载和安装Anaconda,提供了两种方法,详细内容请阅读本文,希望能对你有所帮助... 本文介绍了在Ubuntu系统中如何下载和安装Anaconda。提供了两种方法,包括通过网页手动下载和使用wg

ubuntu系统使用官方操作命令升级Dify指南

《ubuntu系统使用官方操作命令升级Dify指南》Dify支持自动化执行、日志记录和结果管理,适用于数据处理、模型训练和部署等场景,今天我们就来看看ubuntu系统中使用官方操作命令升级Dify的方... Dify 是一个基于 docker 的工作流管理工具,旨在简化机器学习和数据科学领域的多步骤工作流。

使用Python和SQLAlchemy实现高效的邮件发送系统

《使用Python和SQLAlchemy实现高效的邮件发送系统》在现代Web应用中,邮件通知是不可或缺的功能之一,无论是订单确认、文件处理结果通知,还是系统告警,邮件都是最常用的通信方式之一,本文将详... 目录引言1. 需求分析2. 数据库设计2.1 User 表(存储用户信息)2.2 CustomerO