背景
问题陈述
目标
范围
加载和准备图像
图像格式化和转换
特征提取和选择
逻辑回归
线性判别分析
K 最近邻
决策树
随机森林
朴素贝叶斯
支持向量机
准确性和性能指标
机器学习模型的比较
限制和挑战
成果总结
贡献及意义
未来的工作和改进
植物病害对农业生产力构成重大威胁,导致产量损失和农民的经济困难。及时、准确地检测植物病害对于实施有效的病害管理策略和最大限度地减少作物损失至关重要。传统的手动疾病诊断方法耗时、主观且容易出错。因此,机器学习和图像处理等技术的集成已成为自动化和增强植物病害检测的一种有前途的方法
该项目的主要目标是利用机器学习算法和图像处理技术开发植物病害检测系统。该系统旨在通过分析叶子的数字图像来准确地将植物叶子分类为健康或患病。通过自动化检测过程,农民和农业专家可以及时识别和解决植物病害,从而能够及时干预并优化作物管理实践
该项目的主要目标如下
开发强大而准确的植物病害检测系统
实施机器学习算法对植物叶子进行自动分类
利用图像处理技术从叶子图像中提取相关特征
评估不同机器学习模型的性能和准确性
提供用户友好的界面,方便直观地与系统交互
该项目的重点是检测植物病害,特别是苹果叶中的病害。用于训练和测试模型的数据集来自 Plant-Village 数据集,其中包含健康苹果叶子和受苹果黑星病、黑腐病和雪松苹果锈病等疾病影响的叶子的图像。该系统的目标是在病害分类,为农民和农业专业人员有效识别和管理植物病害提供实用工具。该项目不涉及现场实时疾病检测或图像采集的硬件设备集成
用于该植物病害检测系统的数据集包括从植物村数据集中获得的苹果叶图像。该数据集分为四个主要类别,代表不同类别的苹果叶状况 Apple___Apple_scab、Apple___Black_rot、Apple___Cedar_apple_rust 和 Apple___healthy
Apple___Apple_scab:该类别包含 630 张图像,其中 598 张图像用于训练,32 张图像用于测试
Apple___Black_rot:该数据集包含该类别中的 621 张图像,其中 589 张图像分配用于训练,32 张图像用于测试
Apple___Cedar_apple_rust:该数据集由 275 张受雪松苹果锈病影响的叶子图像组成,其中 261 张图像用于训练,14 张图像用于测试
Apple___healthy:此类别包含 1645 张健康苹果叶的图像。其中,1562 张图像指定用于训练,83 张图像保留用于测试。
训练图像用于教导机器学习模型识别模式并区分健康和患病的叶子。测试图像用于评估经过训练的模型在未见过的数据上的性能和准确性通过利用这个多样化的数据集,植物病害检测系统旨在准确地将苹果叶分类为健康的或受苹果黑星病、黑腐病或苹果病等疾病影响的叶子。雪松苹果锈病。该数据集的组成使系统能够从各种叶子状况中学习,并提高其准确概括和识别植物病害的能力
加载和准备图像
在苹果叶病检测项目中,第一步是获取由受不同病害影响的苹果叶图像组成的数据集。然后将这些图像加载到系统中,以便可以进行进一步处理。此外,通过执行必要的调整来准备图像,例如将其大小调整为一致的分辨率、裁剪掉不必要的部分或标准化颜色分布图像格式和转换一旦加载苹果叶图像,就需要对它们进行格式化和转换,以确保与项目后续阶段的兼容性。这涉及通过将图像格式转换为特定的文件类型(如 JPEG 或 PNG)来标准化图像格式。此外,可以对色彩空间分辨率或其他图像属性进行调整,以确保一致性并促进准确分析
特征提取和选择
特征提取是检测苹果叶片病害的关键步骤。使用各种技术从叶子图像中提取相关特征。这些技术包括分析纹理以捕获与疾病相关的纹理图案,检查颜色以识别与特定疾病相关的变化,以及研究形状以检测叶子形态的不规则性。通过提取这些独特的特征,后续的机器学习算法可以有效区分健康和患病的苹果叶子
特征选择
此步骤涉及根据提取的特征的相关性和辨别力来选择提取的特征的子集。特征选择通过消除噪声或冗余信息来帮助降低数据集的维度。通过选择信息量最大的特征,可以提高疾病检测模型的效率和准确性
苹果叶病检测项目利用一系列机器学习算法来开发有效的疾病分类模型。采用以下算法
逻辑回归:逻辑回归用于根据提取的特征来预测苹果叶健康或患病的概率
线性判别分析:线性判别分析通过找到最能区分健康和患病样本的特征线性组合来帮助对苹果叶进行分类
K 最近邻 (KNN):K 最近邻通过将苹果叶子的特征与特征空间中最近邻居的特征进行比较来对苹果叶子进行分类
决策树:决策树使用一系列 if-else 条件根据样本的特征及其层次关系对样本进行分类
随机森林:随机森林是一种集成学习方法,结合多个决策树来增强分类精度
朴素贝叶斯:朴素贝叶斯是一种概率算法,用于计算苹果叶属于特定疾病类别的概率
支持向量机(SVM):支持向量机在高维特征空间中构造超平面来对苹果叶子进行分类
选择机器学习算法后,使用由带有相应疾病标签的苹果叶图像组成的标记数据集来训练模型。模型在训练阶段学习识别特征和疾病类别之间的模式和关系。为了确保模型的可靠性和泛化性,需要执行验证过程。使用训练期间未使用的单独验证数据集对训练后的模型进行评估。这有助于评估模型准确分类看不见的苹果叶样本的能力
一旦模型经过训练和验证,就会在包含新的、看不见的苹果叶图像的单独测试数据集上进行测试。模型预测每个样本的疾病类别,并计算准确率、精确率、召回率和F1分数等性能评估指标,以衡量模型在疾病检测方面的有效性
在[1]中:
# -----------------------------------# 全局特征提取# --------- --------------------------from sklearn.preprocessing import LabelEncoderfrom sklearn.preprocessing import MinMaxScalerimport numpy as npimport mahotasimport cvimport osimport h5py# ----- ---------------# 可调参数# --------------------------------images_per_class = 800fixed_size = tuple(( 500 , 500 ))train_path =“../dataset/train”test_path =“../dataset/test”h5_train_features =“../embeddings/features/features.h5”h5_train_labels =“../embeddings/labels/labels.h5” bins = 8##### BGR To RGB ConversionIn [2]:# 将每个图像从 BGR formatdef 转换为 RGB rgb_bgr(image):rgb_img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)return rgb_img##### RGB 到 HSV(色相饱和度值) ConversionIn [3]:# 从 RGB 转换为 HSV 图像格式def bgr_hsv(rgb_img): hsv_img = cv2.cvtColor(rgb_img, cv2.COLOR_RGB2HSV)return hsv_img##### Image SegmentationIn [4]:# 用于提取绿色和棕色 colordef img_segmentation(rgb_img, hsv_img):lower_green = np.array([ 25 , 0 , 20 ])upper_green = np.数组([ 100 , 255 ,第255章30 , 255 , 255 ])disease_mask = cv2.inRange(hsv_img, lower_brown, upper_brown)disease_result = cv2.bitwise_and(rgb_img, rgb_img, mask=disease_mask)final_mask =healthy_mask +isease_maskfinal_result = cv2.bitwise_and(rgb_img, rgb_img, mask=final_mask)return Final_result##### 确定特征描述符###### 1. Hu MomentsIn [5]:# feature-descriptor-1: Hu Momentsdef fd_hu_moments(image):image = cv2.cvtColor(image , cv2.COLOR_BGR2GRAY)feature = cv2.HuMoments(cv2.moments(image)).flatten()返回特征###### 2. HaralickTexturesIn [6]:# feature-descriptor-2: HaralickTexturedef fd_haralick(image):gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)haralick = mahotas.features.haralick(gray).mean(axis= 0 )return haralick###### 3. 颜色直方图In [7]:# feature-descriptor-3:颜色直方图def fd_histogram(image, mask=None):image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)hist = cv2.calcHist( [图像],[ 0 , 1 , 2 ],无,[箱,箱,箱],[ 0 , 256 , 0 , 256 , 0 ,256 ] )cv2.normalize(hist, hist)return hist.flatten()######加载训练数据集In [8]:# 获取训练标签train_labels = os.listdir(train_path)# 对训练标签进行排序train_labels.sort() print(train_labels)# 保存特征向量和标签的空列表global_features = []labels = [] ['Apple___Apple_scab', 'Apple___Black_rot', 'Apple___Cedar_apple_rust','Apple___healthy']###### 从数据集中生成特征和标签嵌入[9]:# 循环遍历训练数据子文件夹fortrain_labels中的training_name:# join训练数据路径和每个物种的训练文件夹img_dir_path = os.path.join(train_path, Training_name)#获取当前训练标签current_label = Training_name#循环遍历每个子文件夹中的图像for img in os.listdir(img_dir_path):#获取图像文件名file = os.path.join(img_dir_path, img)#读取图像并将其调整为固定大小image = cv2.imread(file)image = cv2.resize(image,fixed_size)#运行函数Bit By BitRGB_BGR = rgb_bgr(image)BGR_HSV = bgr_hsv(RGB_BGR)IMG_SEGMENT = img_segmentation(RGB_BGR, BGR_HSV)# 调用全局特征描述符fv_hu_moments = fd_hu_moments(IMG_SEGMENT)fv_haralick = fd_haralick(IMG_SEGMENT)fv_histogram = fd_histogram(IMG_SEGMENT)# 连接全局特征global_feature = np.hstack([fv_histogram, fv_haralick,fv_hu_moments])# 更新标签和特征向量列表labels.append(current_label)global_features.append(global_feature)print("[STATUS] 已处理文件夹: {}".format(current_label))print("[STATUS] 已完成全局功能提取...”) [STATUS] 已处理的文件夹:Apple___Apple_scab[STATUS] 已处理的文件夹:Apple___Black_rot[STATUS] 已处理的文件夹:Apple___Cedar_apple_rust[STATUS] 已处理的文件夹:Apple___healthy[STATUS] 已完成全局特征提取...在 [10]:# print(global_features)In [ 41]:# 获取整体特征向量 sizeprint("[STATUS]特征向量大小{}".format(np.array(global_features).shape)) [STATUS]特征向量大小(3010, 532)在[12]中:#获取整体训练标签大小# print(labels)print("[STATUS]训练标签{}".format(np.array(labels).shape )) [状态] 培训标签 (3010,)
标签编码值Apple___Apple_scab 0Apple___Black_rot 1Apple___Cedar_apple_rust 2Apple___healthy 3
在[13]中:
targetNames = np.unique(labels) le = LabelEncoder() target = le.fit_transform(labels) print(targetNames) print("[STATUS] 训练标签已编码...") ['Apple___Apple_scab' 'Apple___Black_rot' 'Apple___Cedar_apple_rust' ' Apple___healthy'] [状态] 训练标签编码...
在[14]中:
from sklearn.preprocessing import MinMaxScalerscaler = MinMaxScaler(feature_range=( 0 , 1 ))rescaled_features = scaler.fit_transform(global_features)print("[STATUS] 特征向量归一化...")rescaled_features[STATUS] 特征向量归一化...输出[14]:数组([[0.8974175, 0.03450962, 0.01845123, ..., 0.02027887, 0.12693291,0.96573218], [0.89815922, 0.13025558, 0.02774864, ..., 0.02027767, 0.12692423,0.96573354], [0.56777027, 0., 0.01540143, ..., 0.02027886, 0.12693269,0.96573218], ..., [0.95697685, 0.01228793, 0.00548476, ..., 0.02027886, 0.12693346,0.96573218], [0.97704002, 0.10614054, 0.03136325, ..., 0.02027885, 0.12692424,0.96573217], [0.95214074, 0.03819411, 0.03671892, ..., 0.02027886, 0.12692996,0.96573217]])print("[STATUS] 目标标签:{}".format(target))print("[STATUS] 目标标签形状:{}" .format(目标.形状)) [状态]目标标签:[0 0 0 ... 3 3 3] [状态]目标标签形状:(3010,)
一个。特征
h5f_data = h5py.File(h5_train_features, "w")h5f_data.create_dataset("dataset_1", data=np.array(rescaled_features))Out[16]:
h5f_label = h5py.File(h5_train_labels, "w")h5f_label.create_dataset("dataset_1", data=np.array(target))Out[17]:在[43]中:h5f_data.close()h5f_label.close()
# -----------------------------------# 训练我们的模型# --------- --------------------------导入 h5py 导入 numpy 作为 np 导入 os导入 cv 导入警告 from matplotlib 导入 pyplotfrom sklearn.model_selection 导入 train_test_split, cross_val_scorefrom sklearn.model_selection 导入 KFold, StratifiedKFoldfrom sklearn.metrics import fusion_matrix,准确度分数,classification_reportfrom sklearn.linear_model 导入LogisticRegressionfrom sklearn.tree 导入DecisionTreeClassifierfrom sklearn.ensemble 导入RandomForestClassifierfrom sklearn.neighbors 导入KNeighborsClassifierfrom sklearn.discriminant_analysis 导入LinearDiscriminantAnalysisfrom sklearn.naive_bayes 导入GaussianNBfrom sklearn.svm import SVCimport joblibwarnings.filterwarnings("ignore")# --------------------# 可调参数# ----------- ---------num_trees = 100test_size = 0.seed = 9scoring = "accuracy"# 获取训练标签train_labels = os.listdir(train_path)# 对训练标签进行排序train_labels.sort()如果没有os.path.exists(test_path):os.makedirs(test_path)# 创建所有机器学习模型models = []models.append(("LR", LogisticRegression(random_state=seed)))models.append(("LDA" , LinearDiscriminantAnalysis()))models.append(("KNN", KNeighborsClassifier()))models.append(("DTC", DecisionTreeClassifier(random_state=seed)))models.append(("RF", RandomForestClassifier(n_estimators=num_trees,random_state=seed)))models.append(("NB ", GaussianNB()))models.append(("SVM", SVC(random_state=seed)))# 保存结果和名称的变量results = []names = []# 导入特征向量和训练好的标签sh5f_data = h5py.File(h5_train_features, "r")h5f_label = h5py.File(h5_train_labels, “r”)global_features_string = h5f_data[“dataset_1”]global_labels_string = h5f_label["dataset_1"]global_features = np.array(global_features_string)global_labels = np.array(global_labels_string)h5f_data.close()h5f_label.close()#验证特征向量和标签的形状print("[STATUS] features shape: {}".format(global_features.shape))print("[状态] 标签形状: {}".format(global_labels.shape))print("[STATUS] 训练开始...")print(global_labels, len(global_labels), len(global_features)) [状态]特征形状:(3010, 532) [状态]标签形状:(3010,) [状态] 训练开始... [0 0 0 ... 3 3 3] 3010 3010
在[38]中:
(trainDataGlobal、testDataGlobal、trainLabelsGlobal、testLabelsGlobal、 ) = train_test_split(np.array(global_features), np.array(global_labels),test_size=test_size, random_state=seed)print("[STATUS] 分割训练和测试数据...")print("训练数据:{} ".format(trainDataGlobal.shape))print("测试数据:{}".format(testDataGlobal.shape)) [状态] 分割训练和测试数据...训练数据:(2408, 532)测试数据:(602, 532)In [40]:trainDataGlobalOut[40]:array([[9.47066972e-01, 1.97577832e-02 , 5.34481987e-04, ...,2.02788613e-02、1.26936845e-01、9.65732178e-01]、 [9.67673181e-01、4.20456024e-02、5.76285634e-02、...、2.02788294e-02、1.26933581e-01、9.65732217e-01], [9.84705756e-01、2.97800312e-02、1.34500344e-02、...、2.02788553e-02、1.26941878e-01、9.65732187e-01], ..., [8.64347882e-01、5.89053245e-02、4.27430333e-02、...、2.02791643e-02、1.26961451e-01、9.65733689e-01], [9.85818416e-01、1.47428536e-03、3.35008392e-03、...、2.02767694e-02、1.26792776e-01、9.65732951e-01], [9.93152188e-01、1.31020292e-03、8.50637768e-04、...、2.02910354e-02、1.27475382e-01、9.65721108e-01]])
在[22]中:
对于名称,模型中的模型:kfold = KFold(n_splits= 10 )cv_results = cross_val_score(model, trainDataGlobal, trainLabelsGlobal, cv=kfold,scoring=scoring)results.append(cv_results)names.append(name)msg = "%s : %f (%f)" % (名称, cv_results.mean(), cv_results.std())打印(msg)LR:0.900346(0.020452)LDA:0.892038(0.017931)KNN:0.884978(0.019588)CART:0.886210(0.014771)RF:0.967191 (0.012676)NB: 0.839293 (0.014065)SVM: 0.885813 (0.021190)
在[23]中:
Fig = pyplot.figure()fig.suptitle("机器学习算法比较")ax = Fig.add_subplot( 111 )pyplot.boxplot(results)ax.set_xticklabels(names)pyplot.show()
从上面的结果可以看出,随机森林分类器模型的准确率最高,为96.7%,高斯NB模型的准确率最低,为83.9%