Реализация пакета визуальных слов в Python дает ужасную точность - PullRequest
0 голосов
/ 04 июля 2018

Я пытаюсь реализовать классификатор наборов слов, который у меня есть. Чтобы убедиться, что моя реализация верна, я использовал всего два класса из набора данных Caltech (http://www.vision.caltech.edu/Image_Datasets/Caltech101/)) для тестирования моей реализации: слон и электрогитара. Поскольку они визуально совершенно разные, я считаю, что правильная реализация Bag Классификация визуальных слов (BOVW) может точно классифицировать эти изображения.

Насколько я понимаю (пожалуйста, исправьте меня, если я ошибаюсь), правильная классификация BOVW происходит в три этапа:

  1. Обнаружение SIFT 128-мерных дескрипторов из обучающих изображений и кластеризация их с помощью k-средних.

  2. Проверьте дескрипторы SIFT обучающих и тестовых изображений в классификаторе k-средних (обучены на шаге 1) и составьте гистограмму результатов классификации.

  3. Используйте эти гистограммы в качестве векторов признаков для классификации SVM

Как я объяснял ранее, я пытался решить очень простую задачу классификации двух совершенно разных классов. Я читаю обучающие и тестовые файлы из текстового файла, использую дескрипторы SIFT обучающих изображений для обучения классификатора k-средних, использую обучающие и тестовые изображения для получения гистограммы классификаций и, наконец, использую их как векторы признаков для классификации.

Исходный код моего решения следующий:

import numpy as np
from sklearn import svm
from sklearn.metrics import accuracy_score

#this function will get SIFT descriptors from training images and 
#train a k-means classifier    
def read_and_clusterize(file_images, num_cluster):

    sift_keypoints = []

    with open(file_images) as f:
        images_names = f.readlines()
        images_names = [a.strip() for a in images_names]

        for line in images_names:
        print(line)
        #read image
        image = cv2.imread(line,1)
        # Convert them to grayscale
        image =cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
        # SIFT extraction
        sift = cv2.xfeatures2d.SIFT_create()
        kp, descriptors = sift.detectAndCompute(image,None)
        #append the descriptors to a list of descriptors
        sift_keypoints.append(descriptors)

    sift_keypoints=np.asarray(sift_keypoints)
    sift_keypoints=np.concatenate(sift_keypoints, axis=0)
    #with the descriptors detected, lets clusterize them
    print("Training kmeans")    
    kmeans = MiniBatchKMeans(n_clusters=num_cluster, random_state=0).fit(sift_keypoints)
    #return the learned model
    return kmeans

#with the k-means model found, this code generates the feature vectors 
#by building an histogram of classified keypoints in the kmeans classifier 
def calculate_centroids_histogram(file_images, model):

    feature_vectors=[]
    class_vectors=[]

    with open(file_images) as f:
        images_names = f.readlines()
        images_names = [a.strip() for a in images_names]

        for line in images_names:
        print(line)
        #read image
        image = cv2.imread(line,1)
        #Convert them to grayscale
        image =cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
        #SIFT extraction
        sift = cv2.xfeatures2d.SIFT_create()
        kp, descriptors = sift.detectAndCompute(image,None)
        #classification of all descriptors in the model
        predict_kmeans=model.predict(descriptors)
        #calculates the histogram
        hist, bin_edges=np.histogram(predict_kmeans)
        #histogram is the feature vector
        feature_vectors.append(hist)
        #define the class of the image (elephant or electric guitar)
        class_sample=define_class(line)
        class_vectors.append(class_sample)

    feature_vectors=np.asarray(feature_vectors)
    class_vectors=np.asarray(class_vectors)
    #return vectors and classes we want to classify
    return class_vectors, feature_vectors


def define_class(img_patchname):

    #print(img_patchname)
    print(img_patchname.split('/')[4])

    if img_patchname.split('/')[4]=="electric_guitar":
        class_image=0

    if img_patchname.split('/')[4]=="elephant":
    class_image=1

    return class_image

def main(train_images_list, test_images_list, num_clusters):
    #step 1: read and detect SURF keypoints over the input image (train images) and clusterize them via k-means 
    print("Step 1: Calculating Kmeans classifier")
    model= bovw.read_and_clusterize(train_images_list, num_clusters)

    print("Step 2: Extracting histograms of training and testing images")
    print("Training")
    [train_class,train_featvec]=bovw.calculate_centroids_histogram(train_images_list,model)
    print("Testing")
    [test_class,test_featvec]=bovw.calculate_centroids_histogram(test_images_list,model)

    #vamos usar os vetores de treino para treinar o classificador
    print("Step 3: Training the SVM classifier")
    clf = svm.SVC()
    clf.fit(train_featvec, train_class)

    print("Step 4: Testing the SVM classifier")  
    predict=clf.predict(test_featvec)

    score=accuracy_score(np.asarray(test_class), predict)

    file_object  = open("results.txt", "a")
    file_object.write("%f\n" % score)
    file_object.close()

    print("Accuracy:" +str(score))

if __name__ == "__main__":
    main("train.txt", "test.txt", 1000)
    main("train.txt", "test.txt", 2000)
    main("train.txt", "test.txt", 3000)
    main("train.txt", "test.txt", 4000)
    main("train.txt", "test.txt", 5000)

Как видите, я пытался сильно варьировать количество кластеров в классификаторе kmeans. Однако, независимо от того, что я пытаюсь, точность всегда составляет 53,62%, что ужасно, учитывая, что классы изображений весьма различны.

Итак, есть ли проблемы с моим пониманием или реализацией BOVW? Что я здесь ошибаюсь?

Ответы [ 2 ]

0 голосов
/ 04 июля 2018

Решение проще, чем я думал.

В этой строке:

  hist, bin_edges=np.histogram(predict_kmeans)

Количество бинов - это стандартное количество бинов от numpy (я полагаю, это 10). Делая это:

   hist, bin_edges=np.histogram(predict_kmeans, bins=num_clusters)

Точность увеличилась с 53,62%, о которых я сообщил, до 78,26% при использовании 1000 кластеров и, следовательно, 1000 размерных векторов.

0 голосов
/ 04 июля 2018

Похоже, вы создаете кластеры и гистограммы для каждого изображения. Но для того, чтобы это работало, вам нужно объединить функции просеивания для всех изображений, а затем сгруппировать тезисы и использовать эти общие кластеры для создания гистограммы. Проверьте также https://github.com/shackenberg/Minimal-Bag-of-Visual-Words-Image-Classifier

...