1

Everyone I made a machine learning project using binary patterns to detect plant diseases using haralick textures from images, I trained it with 5 different set of data and it predicting in 60% accuracy. Now i got a situation that to print 3 probable diseases on one image. Example i uploaded one image and predicted it got ‘Mites’ and also want to check is there any other 3 probable diseases in image of plant.

how to achieve the 3 probable in python using local binary patterns?

image

Full code am trying

import cv2
import numpy as np
import os
import glob
import mahotas as mt
from sklearn.svm import LinearSVC
from sklearn.metrics import mean_squared_error
import joblib


# function to extract haralick textures from an image
def extract_features(image):
    # calculate haralick texture features for 4 types of adjacency
    textures = mt.features.haralick(image)

    # take the mean of it and return it
    ht_mean  = textures.mean(axis=0)
    return ht_mean

def ResizeWithAspectRatio(image, width=None, height=None, inter=cv2.INTER_AREA):
    dim = None
    (h, w) = image.shape[:2]

    if width is None and height is None:
        return image
    if width is None:
        r = height / float(h)
        dim = (int(w * r), height)
    else:
        r = width / float(w)
        dim = (width, int(h * r))

    return cv2.resize(image, dim, interpolation=inter)

# load the training dataset
train_path  = "D:/ai training/aphids/Anothertest"
train_names = os.listdir(train_path)

# empty list to hold feature vectors and train labels
train_features = []
train_labels   = []
# loop over the training dataset
print ("[STATUS] Started extracting haralick textures..")

for train_name in train_names:
    cur_path = train_path + "/" + train_name
    cur_label = train_name
    i = 1
    for file in glob.glob(cur_path + "/*.jpg"):
        
        print ("Processing Image - {} in {}".format(i, cur_label))
        
        # read the training image
        image = cv2.imread(file)
        resize = ResizeWithAspectRatio(image, width=1250, height=1000) # Resize by width OR
        # convert the image to grayscale
        gray = cv2.cvtColor(resize, cv2.COLOR_BGR2GRAY)
        # extract haralick texture from the image
        features = extract_features(gray)

        # append the feature vector and label
        train_features.append(features)
        train_labels.append(cur_label)
        
        # otherwise create the model, train the model and save the model
if os.path.exists("D:/ai training/aphids/joblib_model.sav"):
    print("Loading Trained Model")
    clf_svm = joblib.load("D:/ai training/aphids/Anothertest/joblib_model.sav")
else:
        # have a look at the size of our feature vector and labels
        print ("Training features: {}".format(np.array(train_features).shape))
        print ("Training labels: {}".format(np.array(train_labels).shape))

        # create the classifier
        print ("[STATUS] Creating the classifier..")
        clf_svm = LinearSVC(random_state=9, dual=False, max_iter=1000)

        # fit the training data and labels
        print ("[STATUS] Fitting data/label to model..")
        clf_svm.fit(train_features, train_labels)

        #savemodel
        joblib_file = 'D:/ai training/aphids/joblib_model.sav'
        joblib.dump(clf_svm, joblib_file)
    
   
        
        
        
        








#epoch
#clf_svm.fit(train_features, train_labels, epochs=10, validation_data=(X_test), y_test), batch_size=64)
#clf_svm.fit(train_features, train_labels, epochs=10, validation_data=(X_test, y_test), batch_size=64)

# loop over the test images
test_path = "D:/ai training/aphids/tata"
for file in glob.glob(test_path + "/*.jpg"):
    # read the input image
    image = cv2.imread(file)
    resize = ResizeWithAspectRatio(image, width=1250, height=1000) # Resize by width OR
    # convert to grayscale
    gray = cv2.cvtColor(resize, cv2.COLOR_BGR2GRAY)

    # extract haralick texture from the image
    features = extract_features(gray)       

    # evaluate the model and predict label
    prediction = clf_svm.predict(features.reshape(1, -1))[0]
    
    clf_svm.fit(train_features, train_labels)
     
     # show the label
    cv2.putText(resize, prediction, (10,30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0,0,255), 3)
    print ("Prediction - {}".format(prediction))
    print("Accuracy - ", clf_svm.score(train_features, train_labels))
    
    # display the output image
    cv2.namedWindow
    cv2.imshow("Test_Image", resize)
    cv2.waitKey(0)
Al Hathami
  • 43
  • 6

1 Answers1

2

LinearSVC does not provide predict_proba (which would give you the top 3 predicted classes), but it provides the decision_function which gives the signed distance from the hyperplane. (see related question)

So, change this part:

# evaluate the model and predict label
prediction = clf_svm.predict(features.reshape(1, -1))[0]

clf_svm.fit(train_features, train_labels)
 
 # show the label
cv2.putText(resize, prediction, (10,30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0,0,255), 3)
print ("Prediction - {}".format(prediction))
print("Accuracy - ", clf_svm.score(train_features, train_labels))

To this:

# evaluate the model and predict label
top_n_classes = 3
predictions = clf_svm.decision_function( features.reshape(1, -1)).argsort()[:,-top_n_classes:][:,::-1]
predictions = [train_names[i] for i in predictions[0]]

clf_svm.fit(train_features, train_labels)
 
# show the label
y_coordinate = 30
for prediction in predictions:
  cv2.putText(resize, prediction, (10,y_coordinate), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0,0,255), 3)
  y_coordinate += 30
  print("Prediction - {}".format(prediction))

print("Accuracy - ", clf_svm.score(train_features, train_labels))

Demo in Google Colab

BioGeek
  • 21,897
  • 23
  • 83
  • 145
  • Nothing changed , same old result – Al Hathami Apr 07 '21 at 08:54
  • Can you print `predictions` and see if `clf_svm.predict(features.reshape(1, -1))` returns multiple predictions? – BioGeek Apr 07 '21 at 09:23
  • any idea to achieve this? Thanks – Al Hathami Apr 07 '21 at 11:16
  • in this "D:/ai training/aphids/tata" got 3 photos after changing to this code only one image pops up, before the this code show all images in that folder – Al Hathami Apr 07 '21 at 12:57
  • I've got 3 things to mention , after this code now showing wrong prediction before this code it was showing mites thats the right one, and now it only take one image from the folder but got 3 windows , ive to close each windows to get the 3rd probability like bolt - bolt -bolt – Al Hathami Apr 07 '21 at 14:33
  • if it put any image it says bolting :( – Al Hathami Apr 07 '21 at 14:36
  • I'm sharing my training images https://drive.google.com/drive/folders/1-iBzmOEhvrs1Fb5jMkLyFScTsPMvrPJa?usp=sharing – Al Hathami Apr 07 '21 at 15:19
  • I did this changes to the code got the predict proba and printed binary. still have no idea how to print the 3 probabilities from this clf_svm = LinearSVC(random_state=9, dual=False, max_iter=1000) model = CalibratedClassifierCV(clf_svm) prediction = model.predict(features.reshape(1, -1))[0] model.fit(train_features, train_labels) y_proba = model.predict_proba(train_features) #y_proba = regressor.predict(np.array([6.5]).reshape(1, 1)) top_3 = np.argsort(y_proba, axis = 1)[:,4] print ("probably" , top_3 ) – Al Hathami Apr 08 '21 at 08:57
  • I made a typo, `train_labels` should be `train_names`. See my [latest edit](https://stackoverflow.com/posts/66982544/revisions). – BioGeek Apr 08 '21 at 11:41
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/230889/discussion-between-biogeek-and-al-hathami). – BioGeek Apr 08 '21 at 12:08