【图像处理】植物叶识别和分类

news2024/12/25 9:28:53

一、说明

        这是国外某个学生团队尝试用机器学习方法对植物叶进行识别分类的实验。实验给出若干张植物叶图片,针对这些图片,对特征进行测量、提取、重组,最后用机器学习方法实现;该具备一定的参考价值。

        现在是我们将图像处理学习应用于实际机器学习问题的时候了。对于这个博客,让我们解决一个涉及叶子的简单分类问题。作为小组作业,我们的团队得到了一个目录,其中包含来自各种植物的叶子图像。这些图像如下所示:

可以看出,在目录中可以找到 5 类叶子。因此,我们留下了这个机器学习问题:

我们可以使用传统的监督机器学习方法区分各种类别的叶子吗?
阅读直到本文末尾以找出答案。

二、特征提取

2.1 图像处理

        您可能会问的第一个问题,我们将在分析中使用哪些功能?为了使机器学习发挥作用,我们需要检查每个叶子类别共有的特征,以便算法可以决定叶子与其他叶子的区别。深度学习的进步,特别是卷积神经网络(CNN),使我们能够提取大量特征,并在大多数时间获得高精度分数。但是,由于这是一个关于使用图像处理技术的博客,我们不使用CNN。

        那么,如果我们不允许使用CNN从树叶中提取特征,那么首先将如何获得它们呢?这就是本博客的重点,使用图像处理来提取叶子特征,以便在Python中进行机器学习。

        与往常一样,必须导入以下库才能开始讨论:

from skimage.io import imshow, imread
 from skimage.color import rgb2gray
 from skimage.filters import threshold_otsu
 from skimage.morphology import closing
 from skimage.measure import label, regionprops, regionprops_table from sklearn.ensemble import GradientBoostingClassifier,      
    RandomForestClassifier
 from sklearn.model_selection import train_test_split
 from sklearn.metrics import classification_report from matplotlib import pyplot as plt
 import pandas as pd
 import numpy as np
 from tqdm import tqdm
 import os

        让我们看一下我们的一张灰度图像。运行下面的代码:​

 # get the filenames of the leaves under the directory “Leaves”
 image_path_list = os.listdir("Leaves") # looking at the first image
 i = 0
 image_path = image_path_list[i]
 image = rgb2gray(imread("Leaves/"+image_path))
 imshow(image)
 

1)叶灰度图像

        现在,让我们开始使用 skimage '区域属性' 提取特征。但在此之前,我们需要预处理我们的图像,我们首先使用 Otsu 的方法对图像进行二值化,然后使用闭合形态操作对其进行清理。实现如下所示:

 binary = image < threshold_otsu(image)
 binary = closing(binary)
 imshow(binary)

2)叶子二值化图像:

                然后,我们可以标记预处理的图像以准备特征提取。

 label_img = label(binary)
 imshow(label_img)

3)带标签的叶子图像

        最后,让我们使用区域属性从图像中提取特征。这种图像中,我们可以轻易地从每个图读出区域,测量区域的几何特征值。

2.2 特征测量值获取

        为了便于说明,让我们首先考虑这张图片。稍后我们将从每个叶子中提取特征。代码实现如下所示:

table = pd.DataFrame(regionprops_table(label_img, image,
                                       ['convex_area', 'area',
                                        'eccentricity', 'extent',                   
                                        'inertia_tensor',
                                        'major_axis_length', 
                                        'minor_axis_length'])) table['convex_ratio'] = table['area']/table['convex_area']
 table['label'] = image_path[5]
 table

        这将为我们提供一个数据帧,其中包含我们从函数调用regionprops_table功能。

        确实有可能获得特征。但是,这仅适用于一个图像。让我们获得其余部分的功能。怎么做?不用担心,这个博客可以满足您的需求。下面提供了有关如何执行此操作的代码实现:

image_path_list = os.listdir("Leaves")
df = pd.DataFrame()for i in range(len(image_path_list)):
   
  image_path = image_path_list[i]
  image = rgb2gray(imread("Leaves/"+image_path))
  binary = image < threshold_otsu(image)
  binary = closing(binary)
  label_img = label(binary)
  
  table = pd.DataFrame(regionprops_table(label_img, image
                          ['convex_area', 'area', 'eccentricity',
                           'extent', 'inertia_tensor',                         
                           'major_axis_length', 'minor_axis_length',
                           'perimeter', 'solidity', 'image',
                           'orientation', 'moments_central',
                           'moments_hu', 'euler_number',
                           'equivalent_diameter',
                           'mean_intensity', 'bbox']))  table['perimeter_area_ratio'] = table['perimeter']/table['area']  real_images = []
  std = []
  mean = []
  percent25 = []
  percent75 = []  for prop in regionprops(label_img): 
      
      min_row, min_col, max_row, max_col = prop.bbox
      img = image[min_row:max_row,min_col:max_col]
      real_images += [img]
      mean += [np.mean(img)]
      std += [np.std(img)]
      percent25 += [np.percentile(img, 25)] 
      percent75 += [np.percentile(img, 75)]  table['real_images'] = real_images
  table['mean_intensity'] = mean
  table['std_intensity'] = std
  table['25th Percentile'] = mean
  table['75th Percentile'] = std
  table['iqr'] = table['75th Percentile'] - table['25th Percentile']  table['label'] = image_path[5]
  df = pd.concat([df, table], axis=0)df.head()

2.3 从测量值到特征

        实现代码后,它为图像中的所有叶子生成了总共 51 个特征。现在,我们已经为机器学习的实施做好了准备。但在此之前,让我们解释一些提取以提供上下文的特征。

        我们根据区域属性计算了 4 个特征。

1inertia_tensor — 这是一个表示惯性张量的元组。这与该段围绕其质量的旋转有关。注意,转动惯量是个有效物理指标,需要重视。

2. minor_axis_length — 这是指短轴的长度或段的较短轴。

3. solidity — 这只是凸包面积与二值图像面积的比率。

4. eccentricity — 偏心率是焦距(焦点之间的距离)与长轴长度的比值。

        我们还从灰度原始图像段中得出了这些属性。下面的所有功能都只是灰度值的统计信息。IQR 只是第 25 个百分位数和第 75 个百分位数的差值。

  • 25th Percentile
  • 75th Percentile
  • mean_intensity
  • std_intensity
  • IQR

三、机器学习实现

        让我们继续机器学习实现。

X = df.drop(columns=['label', 'image', 'real_images'])#features
X = X[['iqr','75th Percentile','inertia_tensor-1-1',
       'std_intensity','mean_intensity','25th Percentile',
       'minor_axis_length', 'solidity', 'eccentricity']]#target
y = df['label']
columns = X.columns#train-test-split
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.25, random_state=123, stratify=y)

        选择分类器算法。实验表明,表现最好的是梯度提升分类器。实现如下:

clf = GradientBoostingClassifier(n_estimators=50, max_depth=3, random_state=123)clf.fit(X_train, y_train)#print confusion matrix of test set
print(classification_report(clf.predict(X_test), y_test))#print accuracy score of the test set
print(f"Test Accuracy: {np.mean(clf.predict(X_test) ==            
                             y_test)*100:.2f}%")

        运行上述算法可提供以下结果:

四、分类报告

        性能最好的算法是GBM,因为它的测试准确度高于所有分类器,测试准确率约为87%,而随机森林的第二好测试准确率为82%。考虑到PCC仅为20%,我们实现了极高的精度。此外,有限的样本数量使得训练集很容易被分类器过度拟合。这可以通过更多地扩充数据集以实现泛化性来解决。

    

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

生成测试数据的4种方法、5种工具介绍

在软件测试中&#xff0c;测试数据是测试用例的基础&#xff0c;对测试结果的准确性和全面性有着至关重要的影响。 因此&#xff0c;在进行软件测试时&#xff0c;需要生成测试数据以满足测试场景和要求。本文将介绍什么情况下需要生成测试数据&#xff0c;如何生成测试数据&a…

100 行 C++ 代码,教你快速实现视频画面动态分割!

作者&#xff1a; 一去、二三里 个人微信号&#xff1a; iwaleon 微信公众号&#xff1a; 高效程序员 在进行视频或者图像处理时&#xff0c;经常会出现画面分割的场景。 当然了&#xff0c;这里说画面分割是对视频/图像画面的切割&#xff0c;即将同一视频/图像分割成不同的部…

javassist 入门以及dubbo中的使用案例

javassite 入门 概述原理 简单的demo记录方法执行的时间带参数和返回值javassite 占位符 dubbo中的使用代理工厂 JavassistProxyFactory代理类 org.apache.dubbo.common.bytecode.Proxyorg.apache.dubbo.rpc.proxy.InvokerInvocationHandler创建类的工具类 ClassGenerator 概述…

uniapp-ios打包安装测试

我们在做uniapp需要打ios包测试的时候&#xff0c;会有证书私钥密码、证书profile文件、私钥证书三项必填项&#xff0c;这是苹果三件套&#xff0c;必须要有的。就是下图所示 下面说一下如何获取&#xff1a; 一、申请账号 1. 申请Apple id 登录&#xff1a; https://app…

Vue3:组件高级(下)

Vue3&#xff1a;组件高级&#xff08;下&#xff09; Date: May 25, 2023 Sum: ref引用、动态组件、插槽、自定义指令 目标&#xff1a; ◆ 能够知道如何使用 ref 引用 DOM 和组件实例 ◆ 能够知道 $nextTick 的调用时机 ◆ 能够说出 keep-alive 元素的作用 ◆ 能够掌握插…

TiDB亿级数据亚秒响应查询扩缩容

目录 1 查看数据分布2 当前集群部署拓扑3 扩容TiKV节点3.1 编写扩容脚本3.2 执行扩容命令3.2.1 命令格式3.2.2 执行命令 3.3 验证扩容信息3.3.1 查看节点信息3.3.2 通过dashboard查看 4 缩容TiKV节点4.1 查看节点信息4.2 执行缩容操作4.2.1 缩容命令4.2.2 执行命令 4.3 验证缩容…

Redis集群(分布式缓存):详解持久化、主从同步原理、哨兵机制、Cluster分片集群,实现高并发高可用

0、引言 单机式Redis存在以下问题&#xff0c;因此需要Redis集群化来解决这些问题 1、持久化 1.1 RDB&#xff08;Redis Database Backup file &#xff09;持久化 Redis数据快照&#xff0c;简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后&#xff0c…

CSS 布局备忘录

CSS 布局 元素布局display:blockdisplay:inlinedisplay:inline-blockdisplay:inheritdisplay:none Position 布局Flex 布局父元素属性flex-directionflex-wrapflex-flowjustify-contentalign-itemsalign-content 子元素属性orderflex-growflex-shrinkflex-basisfelxalign-self …

电商--抢购总结

文章目录 业务流程业务难点技术难点技术方案技术方向具体落地客户端流控网关流控容器流控后端接口流控数据库流控 流控总结优化读取加速异步化流程处理系统扩容 压测监控 总结参考文献 业务流程 客户端抢购流程中会涉及到商品数据的读取用于商品展示&#xff0c;运营活动数据的…

MM32F3273G8P火龙果开发板MindSDK开发教程8 - MutilButton的移植

MM32F3273G8P火龙果开发板MindSDK开发教程8 - MutilButton的移植 1、MutilButton简介 MultiButton 是一个小巧简单易用的事件驱动型按键驱动模块&#xff0c;可无限量扩展按键&#xff0c;按键事件的回调异步处理方式可以简化你的程序结构&#xff0c;去除冗余的按键处理硬编…

NodeJS SessionToken验证⑧

文章目录 ✨文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持&#x1f618;前言登录鉴权Cookie&Session ExpressSession中间件 MVC演示登录鉴权JSON Web Token (JWT) Jsonwebtoken参数sign 方法verify 方法 封装JsonWebToke…

北邮22信通:第六章查找:BST树表(代码超详细逐步图解)

北邮22信通一枚~ 跟随课程进度每周更新数据结构与算法的代码和文章 持续关注作者 解锁更多邮苑信通专属代码~ 获取更多文章 请访问专栏&#xff1a; 北邮22信通_青山如墨雨如画的博客-CSDN博客 目录 讲解 1.构造函数 2.析构函数 3.查询函数 4.删除操作 &#xf…

全新出品!阿里 P5 工程师~P8 架构师晋升路线揭秘

阿里巴巴终于公开了从初级程序员到架构师的学习路线图&#xff0c;这里相对应的基本上就是从P5到P8的晋升体系&#xff01;今天老师将会带着大家从初级程序员开始一点点分享整个晋升体系&#xff01; 职级&#xff1a;初级程序员 薪资&#xff1a;6-12K 开发年限&#xff1a;0-…

PureComponent和Component的区别和底层处理机制

PureComponent和Component都是React中的组件类&#xff0c;但它们在实现细节和使用上有些差别。 Component是React中定义组件的基类&#xff0c;它的shouldComponentUpdate方法默认返回true&#xff0c;也就是说&#xff0c;每次调用setState或forceUpdate方法都会引发组件重新…

代码随想录第55天

1.判断子序列&#xff1a; 动态规划五部曲分析如下&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][j] 表示以下标i-1为结尾的字符串s&#xff0c;和以下标j-1为结尾的字符串t&#xff0c;相同子序列的长度为dp[i][j]。 注意这里是判断s是否…

百度新闻源调整:自媒体权重降低,官方媒体优势突显

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 根据黑猫发稿的消息&#xff0c;自6月1日起&#xff0c;百度新闻源取消了大部分自媒体新闻源的收录&#xff0c;包括搜狐自媒体、企鹅号、网易号&#xff0c;甚至百度自己的百家号也受到了影响。 …

X2000 Linux 低功耗

一、进入休眠 当系统启动后&#xff0c;在命令终端输入&#xff1a; echo mem> /sys/power/state 即可立即进入休眠&#xff0c;功耗也随之降低。 二、配置中断唤醒GPIO 1、确认kernel默认配置文件 进入到/tools/iconfigtool/IConfigToolApp/路径下&#xff0c;执行./…

【Pm4py第四讲】关于Conversion

本节用于介绍pm4py中的转换函数&#xff0c;包括日志、事件流、数据块的转换、Petei网、流程树、BPMN的转换、可达图、面向对象日志等。 1.函数概述 本次主要介绍Pm4py中一些常见的转换函数&#xff0c;总览如下表&#xff1a; 函数名说明convert_log_to_networkx&#xff08;…

Java(30天拿下---第一天)

Java开发&#xff08;30天拿下---第一天&#xff09; 一 hello world以及JDK,JRE,JVM二 转义字符三 注释四 代码规范五 DOS命令&#xff08;了解&#xff09;六 变量1.加号的使用2.数据类型整型浮点型字符类型布尔类型自动类型转换强制类型转换String类型 七 API文档 一 hello …

React | Redux的使用详解

✨ 个人主页&#xff1a;CoderHing &#x1f5a5;️ React.js专栏&#xff1a;React.js Redux的使用详解 &#x1f64b;‍♂️ 个人简介&#xff1a;一个不甘平庸的平凡人&#x1f36c; &#x1f4ab; 系列专栏&#xff1a;吊打面试官系列 16天学会Vue 7天学会微信小程序 N…