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

 温馨提示:文末有 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*3
    layers.MaxPooling2D((2, 2)),               # 池化层2,2*2采样
    layers.Conv2D(64, (3, 3), activation='relu'),  # 卷积层3,卷积核3*3
    layers.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, EarlyStopping
 
epochs = 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 np

for 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 精品实战案例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/441661.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

.NET开源的两款第三方登录整合库

前言 我相信做开发的同学应该都对接过各种各样的第三方平台的登录授权,来获取用户信息(如:微信登录、支付宝登录、QQ登录、GitHub登录等等)。今天大姚分享两款.NET开源的第三方登录整合库。 MrHuo.OAuth MrHuo.OAuth是.NET项目…

加密与安全_PGP、OpenPGP和GPG加密通信协议

文章目录 PGPOpenPGPGPG工作原理工作流程用途案例说明过程 代码实现pom依赖PgpEncryptionUtilPgpDecryptionUtilCommonUtilsPgpEncryptionTest 小结 PGP PGP (Pretty Good Privacy) 是一种加密通信协议,用于保护电子邮件和文件的安全性和隐私。它通过使用加密、数字…

flink实战--Flink任务资源自动化优化

背景 在生产环境Flink任务资源是用户在实时平台端进行配置,用户本身对于实时任务具体配置多少资源经验较少,所以存在用户资源配置较多,但实际使用不到的情形。比如一个 Flink 任务实际上 4 个并发能够满足业务处理需求,结果用户配置了 16 个并发,这种情况会导致实时计算资…

打开stable diffusion webui时,提示缺少clip或clip安装不上怎么办

在当前数字化时代,软件工具的应用已经成为人们日常生活和工作中不可或缺的一部分。而在使用各种软件工具的过程中,遇到一些技术性问题也是常有的事情。比如,在打开 Stable Diffusion WebUI 这样一个功能强大的工具时,有时会遇到缺…

VMware虚拟机安装Centos7图解,提供软件包镜像(详细安装,小白入门必看)

目录 1. 安装vmware软件 2. 下载centos7镜像 3. 使用镜像安装centos操作系统 3.1 创建新的虚拟机 3.2 开机安装系统 4. 尝试网络连通性 5. 配置静态ip地址 1. 安装vmware软件 下载链接(包含激活码):VMware https://www.alipan…

Yolov8模型用torch_pruning剪枝

目录 🚀🚀🚀订阅专栏,更新及时查看不迷路🚀🚀🚀 原理 遍历所有分组 高级剪枝器 🚀🚀🚀订阅专栏,更新及时查看不迷路🚀&#x1f680…

C# winform 重启电脑

一、重启电脑指令 windows7系统的启动文件夹为“开始菜单”——“所有程序”里面就有“启动”文件夹,其位置是 “C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup” 如果没有,则需要将其中的"administrator…

flutter逆向 ACTF native ap

言 算了一下好长时间没打过CTF了,前两天看到ACTF逆向有道flutter逆向题就过来玩玩啦,花了一个下午做完了.说来也巧,我给DASCTF十月赛出的逆向题其中一道也是flutter,不过那题我难度降的相当之低啦,不知道有多少人做出来了呢~ 还原函数名 flutter逆向的一大难点就是不知道lib…

容器安全是什么?

容器安全定义 容器安全是指保护容器的完整性。这包括从其保管的应用到其所依赖的基础架构等全部内容。容器安全需要完整且持续。通常而言,企业拥有持续的容器安全涵盖两方面: 保护容器流水线和应用保护容器部署环境和基础架构 如何将安全内置于容器流…

【MySQL 系列】MySQL 语句篇_DQL 语句

DQL(Data Query Language),即数据查询语言,用来查询数据记录。DQL 基本结构由 SELECT FROM、WHERE、JOIN 等子句构成。 DQL 语句并不会改变数据库,而是让数据库将查询结果发送结果集给客户端,返回的结果是一…

代理IP以及动态拨号VPS的关系是什么?

在数字时代,网络安全和隐私保护已成为全球关注的热点话题。代理IP和动态拨号VPS作为提升网络匿名性和安全的重要技术,它们在维护网络隐私中扮演着至关重要的角色。虽然这两种技术在表面上看似相似,实际上它们在功能、应用场景以及用户需求满足…

生成对抗网络 (GAN)

生成对抗网络(Generative Adversarial Networks,GAN)是由Ian Goodfellow等人在2014年提出的一种深度学习模型。GAN由两部分组成:一个生成器(Generator)和一个判别器(Discriminator)&…

window vscode安装node.js

window vscode安装node.js 官网下好vscode 和nodejs 选.msi的安装 点这个安装 下载完 继续安装 完毕后倒杯水喝个茶等2分钟 重启VScode 或者在cmd 运行 npm -v node -v 显示版本号则成功

借助Aspose.html控件,在 Java 中将 URL 转换为 PDF

如果您正在寻找一种将实时 URL 中的网页另存为 PDF文档的方法,那么您来对地方了。在这篇博文中,我们将学习如何使用 Java 将 URL 转换为 PDF。从实时 URL转换HTML网页可以像任何其他文档一样保存所需的网页以供离线访问。将网页保存为 PDF 格式可以轻松突…

金智维售前总监屈文浩,将出席“ISIG-RPA超级自动化产业发展峰会”

3月16日,第四届「ISIG中国产业智能大会」将在上海中庚聚龙酒店拉开序幕。本届大会由苏州市金融科技协会指导,企智未来科技(RPA中国、AIGC开放社区、LowCode低码时代)主办。大会旨在聚合每一位产业成员的力量,深入探索R…

windows关闭copilot预览版

如果用户不想在windows系统当中启用Copilot,可以通过以下三种方式禁用。 第一种:隐藏Copilot 按钮 右键点击任务栏,取消勾选“显示 Copilot(预览版)按钮”,任务栏则不再显示,用户可以通过快捷键…

[N1CTF 2018]eating_cms 不会编程的崽

题倒是不难,但是实在是恶心到了。 上来就是登录框,页面源代码也没什么特别的。寻思抓包看一下,数据包直接返回了sql查询语句。到以为是sql注入的题目,直到我看到了单引号被转义。。。挺抽象,似乎sql语句过滤很严格。又…

C语言分析基础排序算法——插入排序

目录 插入排序 直接插入排序 希尔排序 希尔排序基本思路解析 希尔排序优化思路解析 完整希尔排序文件 插入排序 直接插入排序 所谓直接插入排序,即每插入一个数据和之前的数据进行大小比较,如果较大放置在后面,较小放置在前面&#x…

Flutter使用auto_updater实现windows/mac桌面应用版本升级功能

因为windows应用一般大家都是从网上下载的,后期版本肯定会更新,那用flutter开发windows应用,怎么实现应用内版本更新功能了?可以使用auto_updater库, 这个插件允许 Flutter 桌面 应用自动更新自己 (基于 sparkle 和 wi…

生活的色彩--爱摸鱼的美工(17)

题记 生活不如意事十之八九, 恶人成佛只需放下屠刀,善人想要成佛却要经理九九八十一难。而且历经磨难成佛的几率也很小,因为名额有限。 天地不仁以万物为刍狗! 小美工记录生活,记录绘画演变过程的一天。 厨房 食…