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

一、说明

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

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

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

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

二、特征提取

2.1 图像处理

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

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

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

from skimage.io import imshow, imreadfrom skimage.color import rgb2grayfrom skimage.filters import threshold_otsufrom skimage.morphology import closingfrom skimage.measure import label, regionprops, regionprops_table from sklearn.ensemble import GradientBoostingClassifier,      RandomForestClassifierfrom sklearn.model_selection import train_test_splitfrom sklearn.metrics import classification_report from matplotlib import pyplot as pltimport pandas as pdimport numpy as npfrom tqdm import tqdmimport os

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

 # get the filenames of the leaves under the directory “Leaves”image_path_list = os.listdir("Leaves") # looking at the first imagei = 0image_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.bboximg = 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_imagestable['mean_intensity'] = meantable['std_intensity'] = stdtable['25th Percentile'] = meantable['75th Percentile'] = stdtable['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.hqwc.cn/news/1483.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python:使用prometheus-client提交数据到实现prometheus+ grafana数据监控

相关资料 prometheus文档&#xff1a;https://prometheus.io/grafana文档&#xff1a;https://grafana.com/grafana github: https://github.com/grafana/grafanaPyhton客户端https://pypi.org/project/prometheus-client/ 目录 1、使用Python提供数据源2、启动 prometheus3、…

基于高精度三维机器视觉的新能源汽车锂电池表面缺陷检测

​Part.1 行业背景 ​随着新能源汽车在全球范围内成为焦点发展领域&#xff0c;企业对电池质量控制和检测的要求也变得更加严格。在机器视觉行业迅速发展的背景下&#xff0c;市场上提供了功能强大且种类齐全的3D相机系列&#xff0c;可以满足锂电池从电芯到模组各个工艺和工位…

如何修改 Linux 的时区

文章结构 一、查看 Linux 当前时区二、获取时区 TZ 值&#xff08;可选做&#xff09;三、配置 TZ 值四、加载配置并检验是否生效 TZ 是 time zone 的缩写&#xff01; 一、查看 Linux 当前时区 你可以使用如下命令非常容易地就查看到 Linux 系统的当前时区&#xff1a; # 查…

Java 设计模式实战系列—工厂模式

在 Java 开发中&#xff0c;对象的创建是一个常见的场景&#xff0c;如果对象的创建和使用都写在一起&#xff0c;代码的耦合度高&#xff0c;也不利于后期的维护。我们可以使用工厂模式来解决这个问题&#xff0c;工厂模式是一个创建型模式&#xff0c;将对象的创建和使用分离…

【Visual Studio】使用 C++ 语言,配合 Qt,开发了一个串口通信界面

知识不是单独的&#xff0c;一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏&#xff1a;Visual Studio。 文章目录 1. 获取串口名字1.1 文件 GUI.ui1.2 文件 GUI.h1.3 文件 GUI.cpp潜在 Bug&#xff1a;LN2019 2. 配置串口连接2.1 文件 GUI.ui2.2 文件 GUI.h2.3 文…

【C#】简单聊下Framework框架下的事务

框架用的多了&#xff0c;之前版本的事务都忘记了。本次简单聊下.net framework 4.8框架下本身的事务 目录 1、SqlClient2、TransactionScope3、引用 1、SqlClient 在 C# 中&#xff0c;使用 using 块可以方便地实现对资源的自动释放&#xff0c;但它不适用于实现事务处理。为…

一种基于linux内核双向链表的移植

1.简介 双向链表&#xff08;Doubly Linked List&#xff09;是一种常见的数据结构&#xff0c;由一系列的节点组成&#xff0c;每个节点都包含两个指针&#xff0c;分别指向前一个节点和后一个节点。与单向链表不同&#xff0c;双向链表可以在 O(1) 的时间复杂度内向前或向后遍…

虚拟机VMware+Ubuntu配置DPDK环境并运行Helloworld

虚拟机VMwareUbuntu配置DPDK环境并运行Helloworld 文章目录 虚拟机VMwareUbuntu配置DPDK环境并运行Helloworld安装虚拟机虚拟机中安装DPDK运行Helloworld 首先需要强调的是&#xff0c;版本的影响很大&#xff0c;有可能会因为版本不匹配而导致无法成功配置DPDK环境。 安装虚拟…

火山引擎 Iceberg 数据湖的应用与实践

在云原生计算时代&#xff0c;云存储使得海量数据能以低成本进行存储&#xff0c;但是这也给如何访问、管理和使用这些云上的数据提出了挑战。而 Iceberg 作为一种云原生的表格式&#xff0c;可以很好地应对这些挑战。本文将介绍火山引擎在云原生计算产品上使用 Iceberg 的实践…

Scrapy框架之认识MongoDB

目录 MongoDB 简介 特点 MongoDB的适用场景 MongoDB的行业具体应用 如何抉择是否使用MongoDB MongoDB 简介 MongoDB 是免费开源的跨平台 NoSQL 数据库&#xff0c;命名源于英文单词 humongous&#xff0c;意思是「巨大无比」&#xff0c;可见开发组对 MongoDB 的定位。…

函数模板和类模板 知识点总结 C++程序设计与算法笔记总结(七) 北京大学 郭炜

函数模板 交换两个整型变量的值的Swap函数&#xff1a; void Swap(int & x,int & y) { int tmp x; x y; y tmp; } 交换两个double型变量的值的Swap函数: void Swap(double & x,double & y) { double tmp x; x y; y tmp; }用函数模板解决&#xff1a; …

计算几何——gitf-wrapping算法

几何中的"gift-wrapping"算法&#xff0c;又称为"Jarvis算法"&#xff0c;是一种用于计算凸包(convex hull)的方法。下面我将为你解释一下该算法的步骤&#xff1a; 1. 找到具有最小x坐标的点P&#xff0c;我们将其作为凸包的起点。 2. 将P标记为当前点&a…