当前位置: 首页 > news >正文

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

 温馨提示:文末有 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 精品实战案例

相关文章:

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

温馨提示:文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 本文详细探讨了一基于深度学习的可食用植物图像识别系统。采用TensorFlow和Keras框架,利用卷积神经网络(CNN)进行模型训练和预测,并引入迁移学习模型…...

Raingad IM即时聊天/即时通讯网站源码,附带系统搭建教程

支持功能 支持单聊和群聊,支持发送表情、图片、语音、视频和文件消息单聊支持消息已读未读的状态显示,在线状态显示群聊创建、删除和群成员管理、群公告、群禁言等支持置顶联系人,消息免打扰;支持设置新消息声音提醒,…...

for语句的实际应用(3)

3145:【例24.3】 奇数求和 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 9847 通过数: 5442 【题目描述】 计算非负整数 m 到 n(包括 m 和 n)之间的所有奇数的和,其中,m 不大于 n,且 n 不大…...

c++ Windows获取软件安装列表信息

链接 #include <windows.h> #include <stdio.h> #include <iostream> #include <vector>using namespace std;#ifndef MSVCR #define _T #define _tcscpy strcpy #define _stprintf sprintf #define _tcscmp strcmp #endifclass SetupSoftInfo { publ…...

音视频学习笔记——c++多线程(一)

✊✊✊&#x1f308;大家好&#xff01;本篇文章主要整理了部分多线程相关的内容重点&#x1f607;。首先讲解了多进程和多线程并发的区别以及各自优缺点&#xff0c;之后讲解了Thead线程库的基本使用。 本专栏知识点是通过<零声教育>的音视频流媒体高级开发课程进行系统…...

消息队列常见问题

总的来讲&#xff0c;消息队列常见问题要么消息不能多&#xff0c;要么不能少&#xff0c;还有顺序性&#xff0c;以及积压处理的问题等。 1.消息不能多 也就是说&#xff0c;消息不能重复消费&#xff0c;随之带来的幂等性问题。 解决&#xff1a;一般结合业务场景&#xf…...

【leetcode热题】二叉树的前序遍历

难度&#xff1a; 中等通过率&#xff1a; 49.5%题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定一个二叉树&#xff0c;返回它的 前序 遍历。 示例: 输入: [1,null,2,3] 1\2/3 输出: [1,2,3]进阶: 递归算法很简单&#xff0c;你可以通过迭代…...

Linux命令记不住?保姆级教程来了

在软件开发过程中&#xff0c;Linux操作系统因其稳定性、安全性和高效性而备受青睐。作为开发者&#xff0c;熟练掌握Linux常用命令&#xff0c;不仅可以提高工作效率&#xff0c;还能更好地管理服务器和进行代码部署。本文将介绍一些开发常用的Linux命令及其应用场景&#xff…...

基于GitBucket的Hook构建ES检索PDF等文档全栈方案

背景 之前已简单使用ES及Kibana和在线转Base64工具实现了检索文档的demo&#xff0c;预期建设方案是使用触发器类型从公共的文档源拉取最新的文件&#xff0c;然后调用Java将文件转Base64后入ES建索引&#xff0c;再提供封装接口给前端做查询之用。 由于全部内容过长&#xff…...

C语言:数组、字符串知识点整理:

数组&#xff1a;&#xff08;长度的计算&#xff09; 补充&#xff1a;数组长度sizeof(arr)/sizeof(arr[0]) 注意&#xff1a;&#xff01;&#xff01;&#xff01;不适用于当arr 充当形参时&#xff08;函数传参&#xff09;&#xff01;&#xff01;&#xff01; 因为函数…...

Linux mmap系统调用

文章目录 前言一、mmap()函数简介二、代码演示2.1 mmap使用场景2.2 私有匿名映射2.3 私有文件映射2.4 共享匿名映射2.5 共享文件映射 参考 前言 NAMEmmap, munmap - map or unmap files or devices into memorySYNOPSIS#include <sys/mman.h>void *mmap(void *addr, siz…...

VSCode搭建ARM开发环境

为了构建Cortex M系列单片机免费开源的开发环境&#xff0c;网络上了解来看VSCODEGCCJLINK是一套比较高效的组合方式&#xff0c;下面记录环境搭建的流程。 我这边的PC环境为 WIN7专业版64bit。 需要用到的工具 Visual Studio CodeSTM32CubemxARM GCC 交叉编译工具链&#x…...

centos7 python3.12.1 报错 No module named _ssl

https://blog.csdn.net/Amio_/article/details/126716818 安装python cd /usr/local/src wget https://www.python.org/ftp/python/3.12.1/Python-3.12.1.tgz tar -zxvf Python-3.12.1.tgz cd Python-3.12.1/ ./configure -C --enable-shared --with-openssl/usr/local/opens…...

探索HTTP协议:网络通信的基石

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…...

几大开源免费的 JavaScript 富文本编辑器测评

MarkDown 编辑器用的时间长了&#xff0c;发现发现富文本编辑器用起来是真的舒服。 一直以来写博客都是用的 MarkDown 编辑器&#xff0c;MarkDown 文档简单方便&#xff0c;使用几个简单的符号就可以定义出样式统一的富文本内容。写博客的时间长了&#xff0c;小玖就越来越排…...

MongoDB聚合运算符:$dateFromString

文章目录 语法使用使用例子对规则进行说明格式指示符 举例日期转换错误处理onError空值的粗粒 onNull $dateFromString聚合运算符将日期时间字符串转换为日期对象。 语法 { $dateFromString: {dateString: <dateStringExpression>,format: <formatStringExpression&g…...

Postman(注册,使用,作用)【详解】

目录 一、Postman 1. Postman介绍 2. 安装Postman 3. 注册帐号再使用(可保存测试记录) 4. 创建workspace 5. 测试并保存测试记录 一、Postman postman工具可以发送不同方式的请求,浏览器只能发送get请求(所有用这个工具) 在前后端分离开发模式下&#xff0c;前端技术人员…...

电商数据分析18——电商广告投放的数据分析与优化

目录 写在开头1. 电商广告投放的挑战与机遇1.1 广告投放的主要目标与挑战1.2 广告数据分析的价值 2. 数据分析在广告投放中的应用2.1 目标受众分析与精准定位2.2 广告效果评估与ROI分析2.3 A/B测试与广告内容优化 3. 广告投放优化的实践案例3.1 案例分享&#xff1a;精准定向提…...

Docker下Jenkins打包java项目并部署

docker 构建Jenkins sudo docker run --namezen_haslett --userjenkins --privilegedtrue --volume/home/cyf/server/jenkins/jenkins_home:/var/jenkins_home -v /usr/lib/jvm/java-17-openjdk-amd64:/usr/lib/jvm/java-17-openjdk-amd64 -v /usr/lib/maven/apache-mav…...

android 快速实现 recyclerview 的所有item 都执行动画

1.在adapter 里面重写onViewAttachedToWindow 和 onViewDetachedFromWindow 两个方法 package com.example.widget;import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.LinearInterpolator; import android.view.animat…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

PostgreSQL——环境搭建

一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在&#xff0…...

CppCon 2015 学习:Time Programming Fundamentals

Civil Time 公历时间 特点&#xff1a; 共 6 个字段&#xff1a; Year&#xff08;年&#xff09;Month&#xff08;月&#xff09;Day&#xff08;日&#xff09;Hour&#xff08;小时&#xff09;Minute&#xff08;分钟&#xff09;Second&#xff08;秒&#xff09; 表示…...

【Redis】Redis从入门到实战:全面指南

Redis从入门到实战:全面指南 一、Redis简介 Redis(Remote Dictionary Server)是一个开源的、基于内存的键值存储系统,它可以用作数据库、缓存和消息代理。由Salvatore Sanfilippo于2009年开发,因其高性能、丰富的数据结构和广泛的语言支持而广受欢迎。 Redis核心特点:…...