Hintergrund
Problemstellung
Ziele
Umfang
Bilder laden und vorbereiten
Bildformatierung und -konvertierung
Merkmalsextraktion und -auswahl
Logistische Regression
Lineare Diskriminanzanalyse
K Nächste Nachbarn
Entscheidungsbäume
Zufälliger Wald
Naiver Bayes
Unterstützt Vektormaschine
Genauigkeits- und Leistungsmetriken
Vergleich maschineller Lernmodelle
Einschränkungen und Herausforderungen
Zusammenfassung der Erfolge
Beiträge und Bedeutung
Zukünftige Arbeit und Verbesserungen
Pflanzenkrankheiten stellen eine erhebliche Bedrohung für die landwirtschaftliche Produktivität dar und führen zu Ertragsverlusten und wirtschaftlichen Schwierigkeiten für Landwirte. Die rechtzeitige und genaue Erkennung von Pflanzenkrankheiten ist entscheidend für die Umsetzung wirksamer Strategien zur Krankheitsbekämpfung und die Minimierung von Ernteschäden. Herkömmliche manuelle Methoden zur Krankheitsdiagnose können zeitaufwändig, subjektiv und fehleranfällig sein. Daher hat sich die Integration von Technologien wie maschinellem Lernen und Bildverarbeitung als vielversprechender Ansatz zur Automatisierung und Verbesserung der Erkennung von Pflanzenkrankheiten herausgestellt
Das Hauptziel dieses Projekts ist die Entwicklung eines Systems zur Erkennung von Pflanzenkrankheiten unter Verwendung von Algorithmen für maschinelles Lernen und Bildverarbeitungstechniken. Das System zielt darauf ab, Pflanzenblätter durch die Analyse digitaler Bilder von Blättern genau als gesund oder krank zu klassifizieren. Durch die Automatisierung des Erkennungsprozesses können Landwirte und Agrarexperten Pflanzenkrankheiten umgehend erkennen und bekämpfen, was zeitnahe Eingriffe und eine Optimierung der Pflanzenbewirtschaftungspraktiken ermöglicht
Die Hauptziele dieses Projekts sind wie folgt
Entwickeln Sie ein robustes und genaues System zur Erkennung von Pflanzenkrankheiten
Implementieren Sie Algorithmen für maschinelles Lernen zur automatisierten Klassifizierung von Pflanzenblättern
Nutzen Sie Bildverarbeitungstechniken, um relevante Merkmale aus Blattbildern zu extrahieren
Bewerten Sie die Leistung und Genauigkeit verschiedener Modelle für maschinelles Lernen
Stellen Sie eine benutzerfreundliche Oberfläche für eine einfache und intuitive Interaktion mit dem System bereit
Der Schwerpunkt dieses Projekts liegt auf der Erkennung von Pflanzenkrankheiten speziell in Apfelblättern. Der zum Training und Testen der Modelle verwendete Datensatz stammt aus dem Plant-Village-Datensatz, der Bilder von gesunden Apfelblättern und Blättern enthält, die von Krankheiten wie Apfelschorf, Schwarzfäule und Zedern-Apfelrost befallen sind. Das System zielt darauf ab, eine hohe Genauigkeit zu erreichen Krankheitsklassifizierung und bieten Landwirten und Agrarfachleuten ein praktisches Werkzeug zur effektiven Erkennung und Bekämpfung von Pflanzenkrankheiten. Das Projekt umfasst nicht die Echtzeiterkennung von Krankheiten im Feld oder die Integration von Hardwaregeräten zur Bilderfassung
Der für dieses System zur Erkennung von Pflanzenkrankheiten verwendete Datensatz besteht aus Bildern von Apfelblättern, die aus dem Plant-Village-Datensatz stammen. Der Datensatz ist in vier Hauptkategorien unterteilt, die verschiedene Klassen von Apfelblattzuständen repräsentieren: Apple___Apple_scab, Apple___Black_rot, Apple___Cedar_apple_rust und Apple___healthy
Apple___Apple_scab: Diese Kategorie enthält 630 Bilder, wobei 598 Bilder für das Training und 32 Bilder für Tests vorgesehen sind
Apple___Black_rot: Der Datensatz umfasst 621 Bilder in dieser Kategorie, wobei 589 Bilder für das Training und 32 Bilder für Tests vorgesehen sind
Apple___Cedar_apple_rust: Der Datensatz besteht aus 275 Bildern von Blättern, die von Zedernapfelrost betroffen sind, wobei 261 Bilder für das Training und 14 Bilder für Tests verwendet werden
Apple___healthy: Diese Kategorie enthält 1645 Bilder von gesunden Apfelblättern. Davon sind 1562 Bilder für das Training vorgesehen und 83 Bilder für Tests reserviert.
Die Trainingsbilder werden verwendet, um den Modellen des maschinellen Lernens beizubringen, Muster zu erkennen und zwischen gesunden und kranken Blättern zu unterscheiden. Die Testbilder werden verwendet, um die Leistung und Genauigkeit der trainierten Modelle anhand unsichtbarer Daten zu bewerten. Durch die Nutzung dieses vielfältigen Datensatzes zielt das System zur Erkennung von Pflanzenkrankheiten darauf ab, Apfelblätter genau als gesund oder von Krankheiten wie Apfelschorf, Schwarzfäule usw. befallen zu klassifizieren Zedernapfelrost. Die Zusammensetzung des Datensatzes ermöglicht es dem System, aus einem breiten Spektrum von Blattzuständen zu lernen und seine Fähigkeit zu verbessern, Pflanzenkrankheiten genau zu verallgemeinern und zu identifizieren
Bilder laden und vorbereiten
Im Rahmen des Projekts zur Erkennung von Apfelblattkrankheiten besteht der erste Schritt darin, einen Datensatz zu erfassen, der aus Bildern von Apfelblättern besteht, die von verschiedenen Krankheiten befallen sind. Diese Bilder werden dann in das System geladen, um sie für die weitere Verarbeitung zugänglich zu machen. Darüber hinaus werden die Bilder vorbereitet, indem notwendige Anpassungen vorgenommen werden, wie z. B. die Größenänderung auf eine einheitliche Auflösung, das Ausschneiden unnötiger Teile oder die Normalisierung der Farbverteilung. Bildformatierung und -konvertierung. Sobald die Apfelblattbilder geladen sind, müssen sie zur Gewährleistung formatiert und konvertiert werden Kompatibilität mit den nachfolgenden Projektphasen. Dazu gehört die Standardisierung des Bildformats durch die Konvertierung in einen bestimmten Dateityp wie JPEG oder PNG. Darüber hinaus können Anpassungen an der Farbraumauflösung oder anderen Bildattributen vorgenommen werden, um Konsistenz sicherzustellen und eine genaue Analyse zu erleichtern
Merkmalsextraktion und -auswahl
Die Merkmalsextraktion ist ein entscheidender Schritt bei der Erkennung von Krankheiten in Apfelblättern. Um relevante Merkmale aus den Blattbildern zu extrahieren, werden verschiedene Techniken eingesetzt. Zu diesen Techniken gehören die Analyse der Textur, um mit Krankheiten verbundene Strukturmuster zu erfassen, die Untersuchung der Farbe, um Variationen im Zusammenhang mit bestimmten Krankheiten zu identifizieren, und die Untersuchung der Form, um Unregelmäßigkeiten in der Blattmorphologie zu erkennen. Durch die Extraktion dieser Unterscheidungsmerkmale können die nachfolgenden Algorithmen des maschinellen Lernens effektiv zwischen gesunden und kranken Apfelblättern unterscheiden
Funktionsauswahl
In diesem Schritt wird eine Teilmenge der extrahierten Merkmale auf der Grundlage ihrer Relevanz und Unterscheidungskraft ausgewählt. Die Merkmalsauswahl trägt dazu bei, die Dimensionalität des Datensatzes zu reduzieren, indem Rauschen oder redundante Informationen eliminiert werden. Durch die Auswahl der aussagekräftigsten Merkmale können die Effizienz und Genauigkeit des Krankheitserkennungsmodells verbessert werden
Das Projekt zur Erkennung von Apfelblattkrankheiten nutzt eine Reihe von Algorithmen für maschinelles Lernen, um ein effektives Krankheitsklassifizierungsmodell zu entwickeln. Die folgenden Algorithmen werden verwendet
Logistische Regression: Die logistische Regression wird verwendet, um die Wahrscheinlichkeit vorherzusagen, dass ein Apfelblatt gesund oder krank ist, basierend auf den extrahierten Merkmalen
Lineare Diskriminanzanalyse: Die lineare Diskriminanzanalyse hilft bei der Klassifizierung von Apfelblättern, indem sie eine lineare Kombination von Merkmalen findet, die gesunde und kranke Proben am besten trennt
K Nearest Neighbors (KNN): K Nearest Neighbors klassifiziert Apfelblätter, indem es ihre Merkmale mit denen der nächsten Nachbarn im Merkmalsraum vergleicht
Entscheidungsbäume: Entscheidungsbäume verwenden eine Reihe von If-Else-Bedingungen, um Stichproben anhand ihrer Merkmale und ihrer hierarchischen Beziehungen zu klassifizieren
Random Forest: Random Forest ist eine Ensemble-Lernmethode, die mehrere Entscheidungsbäume kombiniert, um die Klassifizierungsgenauigkeit zu verbessern
Naive Bayes: Naive Bayes ist ein probabilistischer Algorithmus, der die Wahrscheinlichkeit berechnet, dass ein Apfelblatt zu einer bestimmten Krankheitsklasse gehört
Support Vector Machine (SVM): Support Vector Machine konstruiert Hyperebenen in einem hochdimensionalen Merkmalsraum, um Apfelblätter zu klassifizieren
Nach Auswahl der Algorithmen für maschinelles Lernen werden die Modelle mithilfe eines beschrifteten Datensatzes trainiert, der aus Apfelblattbildern mit entsprechenden Krankheitsbezeichnungen besteht. In dieser Trainingsphase lernen die Modelle, Muster und Zusammenhänge zwischen Merkmalen und Krankheitsklassen zu erkennen. Um die Zuverlässigkeit und Generalisierung der Modelle sicherzustellen, wird ein Validierungsprozess durchgeführt. Die trainierten Modelle werden mithilfe eines separaten Validierungsdatensatzes bewertet, der während des Trainings nicht verwendet wurde. Dies hilft bei der Beurteilung der Fähigkeit der Modelle, unsichtbare Apfelblattproben genau zu klassifizieren
Sobald die Modelle trainiert und validiert sind, werden sie an einem separaten Testdatensatz getestet, der neue, noch nie gesehene Apfelblattbilder enthält. Die Modelle sagen die Krankheitsklasse für jede Probe voraus und Leistungsbewertungsmetriken wie Genauigkeit, Präzision, Erinnerung und F1-Score werden berechnet, um die Wirksamkeit der Modelle bei der Krankheitserkennung zu messen
In [1]:
# -----------------------------------# GLOBALE FEATURE-EXTRAKTION# --------- --------------------------von sklearn.preprocessing import LabelEncodervon sklearn.preprocessing import MinMaxScalerimport numpy as npimport mahotasimport cvimport osimport h5py# ----- --------------# tunable-parameters# --------------------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]:# Konvertieren jedes Bildes in RGB von BGR formatdef rgb_bgr(image):rgb_img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)return rgb_img##### RGB to HSV (Hue Saturation Value) ConversionIn [3]:# Konvertierung in das HSV-Bildformat von RGBdef bgr_hsv(rgb_img ):hsv_img = cv2.cvtColor(rgb_img, cv2.COLOR_RGB2HSV)return hsv_img##### Image SegmentationIn [4]:# für die Extraktion von grüner und brauner Farbedef img_segmentation(rgb_img, hsv_img):lower_green = np.array([ 25 , 0 , 20 ])upper_green = np.array([ 100 , 255 , 255 ])healthy_mask = cv2.inRange(hsv_img, Lower_green, Upper_green)result = cv2.bitwise_and(rgb_img, rgb_img, mask=healthy_mask)lower_brown = np.array([ 10 , 0 , 10 ])upper_brown = np.array([ 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 + Disease_maskfinal_result = cv2.bitwise_and(rgb_img, rgb_img, mask=final_mask)return final_result##### Bestimmen der Feature-Deskriptoren###### 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()return feature###### 2. Haralick TexturesIn [6]:# feature-descriptor-2: Haralick Texturedef fd_haralick(image):gray = cv2.cvtColor (Bild, cv2.COLOR_BGR2GRAY)haralick = mahotas.features.haralick(gray).mean(axis= 0 )return haralick###### 3. FarbhistogrammIn [7]:# feature-descriptor-3: Farbhistogrammdef fd_histogram(image, mask=None):image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)hist = cv2 .calcHist( [Bild], [ 0 , 1 , 2 ], Keine, [Behälter, Behälter, Behälter], [ 0 , 256 , 0 , 256 , 0 ,256 ] )cv2.normalize(hist, hist)return hist.flatten()##### Laden des TrainingsdatensatzesIn [8]:# Holen Sie sich die Trainingsetikettentrain_labels = os.listdir(train_path)# sortieren Sie die Trainingsetikettentrain_labels.sort() print(train_labels)# leere Listen zur Aufnahme von Feature-Vektoren und Labelsglobal_features = []labels = [] ['Apple___Apple_scab', 'Apple___Black_rot', 'Apple___Cedar_apple_rust','Apple___healthy']##### Generieren der Features und Label-Einbettungen aus dem DatensatzIn [9]:# Schleife über die Trainingsdaten-Unterordner für Training_Name in Train_Labels:# Join der Trainingsdatenpfad und jeder Art-Trainingsordnerimg_dir_path = os.path.join(train_path, training_name)# das aktuelle Trainingslabel abrufencurrent_label = training_name# Schleife über die Bilder in jedem Unterordner für img in os.listdir(img_dir_path):# den Bilddateinamen abrufenfile = os.path.join( img_dir_path, img)# liest das Bild und ändert seine Größe auf eine feste Größeimage = cv2.imread(file)image = cv2.resize(image, feste_größe)# Funktion Bit für Bit ausführenRGB_BGR = rgb_bgr(image)BGR_HSV = bgr_hsv(RGB_BGR)IMG_SEGMENT = img_segmentation(RGB_BGR, BGR_HSV)# Aufruf für globale Feature-Deskriptorenfv_hu_moments = fd_hu_moments(IMG_SEGMENT)fv_haralick = fd_haralick(IMG_SEGMENT)fv_histogram = fd_histogram(IMG_SEGMENT)# Globale Features verkettenglobal_feature = np.hstack([fv_histogram, fv_haralick,fv_hu_moments])# Liste der Beschriftungen und Features aktualisieren vectorslabels.append(current_label)global_features.append(global_feature)print("[STATUS] verarbeiteter Ordner: {}".format(current_label))print("[STATUS] abgeschlossene globale Feature-Extraktion...") [STATUS] verarbeiteter Ordner: Apple___Apple_scab[STATUS] verarbeiteter Ordner: Apple___Black_rot[STATUS] verarbeiteter Ordner: Apple___Cedar_apple_rust[STATUS] verarbeiteter Ordner: Apple___healthy[STATUS] abgeschlossen Global Feature Extraction...In [10]:# print(global_features)In [ 41]:# Gesamt-Feature-Vektor abrufen sizeprint("[STATUS] Feature-Vektor size{}".format(np.array(global_features).shape)) [STATUS] Feature-Vektorgröße (3010, 532)In [12]:# Gesamtgröße des Trainingsetiketts abrufen# print(labels)print("[STATUS] Training Labels {}".format(np.array(labels).shape )) [STATUS] Trainingsetiketten (3010,)
Label-codierter WertApple___Apple_scab 0Apple___Black_rot 1Apple___Cedar_apple_rust 2Apple___healthy 3
In [13]:
targetNames = np.unique(labels) le = LabelEncoder() target = le.fit_transform(labels) print(targetNames) print("[STATUS] Trainingslabels encoded...") ['Apple___Apple_scab' 'Apple___Black_rot' 'Apple___Cedar_apple_rust' ' Apple___healthy'] [STATUS] Trainingsbezeichnungen codiert...
In [14]:
from sklearn.preprocessing import MinMaxScalerscaler = MinMaxScaler(feature_range=( 0 , 1 ))rescaled_features = scaler.fit_transform(global_features)print("[STATUS] Feature-Vektor normalisiert...")rescaled_features[STATUS] Feature-Vektor normalisiert...Out [14]:array([[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] Zielbeschriftungen: {}".format(target))print("[STATUS] Zielbeschriftungen Form: {}" .format(target.shape)) [STATUS] Zielbezeichnungen: [0 0 0 ... 3 3 3] [STATUS] Form der Zielbeschriftungen: (3010,)
A. Merkmale
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]:In [43]:h5f_data.close()h5f_label.close()
# -----------------------------------# SCHULUNG UNSERES MODELLS# --------- ----------------------------------------import h5pyimport numpy as npimport osimport cvimport warningsfrom matplotlib import pyplotfrom sklearn.model_selection import train_test_split, cross_val_scorefrom sklearn.model_selection import KFold, StratifiedKFoldfrom sklearn.metrics import confusion_matrix, precision_score,classification_reportfrom sklearn.linear_model import LogisticRegressionfrom sklearn.tree import DecisionTreeClassifierfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.neighbors import KNeighborsClassifierfrom sklearn.discriminant_analysis import LinearDiscriminantAnalysisfrom sklearn.naive_bayes import GaussianNBfrom sklearn.svm import SVCimport joblibwarnings.filterwarnings("ignore")# --------------------# tunable-parameters# ---------- ----------num_trees = 100test_size = 0.seed = 9scoring = "accuracy"# holen Sie sich die Trainingslabelstrain_labels = os.listdir(train_path)# sortieren Sie die Trainingslabelstrain_labels.sort()wenn nicht os.path.exists(test_path):os.makedirs(test_path)# Alle Modelle für maschinelles Lernen erstellenmodels = []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)))# Variablen zum Speichern der Ergebnisse und nameresults = []names = []# Importieren Sie den Feature-Vektor und die trainierten Labels = np.array(global_features_string)global_labels = np.array(global_labels_string)h5f_data.close()h5f_label.close()# Überprüfen Sie die Form des Feature-Vektors und labelsprint("[STATUS] Features Shape: {}".format(global_features. shape))print("[STATUS] beschriftet Form: {}".format(global_labels.shape))print("[STATUS] Training gestartet ...")print(global_labels, len(global_labels), len(global_features)) [STATUS] Features Form: (3010, 532) [STATUS] Etikettenform: (3010,) [STATUS] Training begonnen... [0 0 0 ... 3 3 3] 3010 3010
In [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] aufgeteilte Zug- und Testdaten...")print("Train data : {} ".format(trainDataGlobal.shape))print("Testdaten: {}".format(testDataGlobal.shape)) [STATUS] aufgeteilte Zug- und Testdaten...Zugdaten: (2408, 532)Testdaten: (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]])
In [22]:
für Name, Modell in models: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)" % (Name, cv_results.mean(), cv_results.std())print(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)
In [23]:
fig = pyplot.figure()fig.suptitle("Vergleich des Algorithmus für maschinelles Lernen")ax = fig.add_subplot( 111 )pyplot.boxplot(results)ax.set_xticklabels(names)pyplot.show()
Aus dem obigen Ergebnis können wir ersehen, dass das Random Forest Classifier-Modell die höchste Genauigkeit von 96,7 % und das Gaußsche NB-Modell die niedrigste Genauigkeit von 83,9 % aufweist.