Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中的可视化单词包实现的准确性非常差_Python_Image Processing_Machine Learning_Computer Vision - Fatal编程技术网

Python中的可视化单词包实现的准确性非常差

Python中的可视化单词包实现的准确性非常差,python,image-processing,machine-learning,computer-vision,Python,Image Processing,Machine Learning,Computer Vision,我正在尝试实现一个单词包分类器来对我拥有的数据集进行分类。为了确保我的实现是正确的,我只使用了加州理工学院数据集()中的两个类来测试我的实现:大象和电吉他。由于它们在视觉上完全不同,我相信正确实现视觉单词包(BOVW)分类可以准确地对这些图像进行分类 根据我的理解(如果我错了,请纠正我),正确的BOVW分类分为三个步骤: 从训练图像中筛选128个维度描述符,并用k-均值聚类 测试训练和测试图像,在k-means分类器中筛选描述符(在步骤1中训练),并制作分类结果的直方图 使用这些直方图作为SVM

我正在尝试实现一个单词包分类器来对我拥有的数据集进行分类。为了确保我的实现是正确的,我只使用了加州理工学院数据集()中的两个类来测试我的实现:大象和电吉他。由于它们在视觉上完全不同,我相信正确实现视觉单词包(BOVW)分类可以准确地对这些图像进行分类

根据我的理解(如果我错了,请纠正我),正确的BOVW分类分为三个步骤:

  • 从训练图像中筛选128个维度描述符,并用k-均值聚类

  • 测试训练和测试图像,在k-means分类器中筛选描述符(在步骤1中训练),并制作分类结果的直方图

  • 使用这些直方图作为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的理解或实施是否存在任何问题?我搞错了什么

    看起来您正在为每个图像创建簇和直方图。但是为了让它工作,你必须为所有的图像聚集sift特征,然后对论文进行聚类,并使用这些常见的聚类来创建直方图。还可以查看

    解决方案比我想象的要简单

    在这方面:

      hist, bin_edges=np.histogram(predict_kmeans)
    
    箱子的数量是numpy的标准箱子数量(我相信是10个)。通过这样做:

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

    使用1000个聚类和1000个维向量,准确率从我报告的53.62%提高到78.26%。

    我正在从所有训练图像中提取SIFT描述符,并将它们聚合到同一个矩阵中。该矩阵用于k-均值聚类。你也建议我从k-均值聚类中测试图像来考虑SIFT描述符吗?>我从所有训练图像中提取SIFT描述符,并将它们聚集在同一个矩阵中。啊,我没有注意到这一点。>您是否建议我在k-均值聚类中测试图像中的SIFT描述符?不,这不会是合理的,也不会导致过度拟合,因为人们会(隐式地)使用来自测试集的信息?我已经在使用所有训练图像中的所有SIFT特征,以k-means对它们进行聚类。在你建议我检查的代码中,作者说“聚合每个训练图像的视觉单词的直方图”,这对我来说是相当模糊的。在我的理解中,我们不聚合直方图,我们所做的是考虑来自同一图像的所有点(聚合其点)来计算其直方图。我在这里不明白什么?谢谢。我认为这意味着,直方图是为每幅图像计算的,所有这些直方图都“聚合”或更好地“收集”在一个“数据结构”中,并用作训练的功能。仅供参考:在他们使用
    sqrt
    的sift功能数作为簇数。@Framester根据您的建议,我使用RBF核SVM分类器,在成本和伽马参数上进行网格搜索,获得了84.05%的准确率。非常感谢你的建议。