zoukankan      html  css  js  c++  java
  • 图像识别sift+bow+svm

    本文概述

    利用SIFT特征进行简单的花朵识别

    SIFT算法的特点有:

    1. SIFT特征是图像的局部特征,其对旋转、尺度缩放、亮度变化保持不变性,对视角变化、仿射变换、噪声也保持一定程度的稳定性;
    2. SIFT算法提取的图像特征点数不是固定值,维度是统一的128维。
    3. 独特性(Distinctiveness)好,信息量丰富,适用于在海量特征数据库中进行快速、准确的匹配;
    4. 多量性,即使少数的几个物体也可以产生大量的SIFT特征向量;
    5. 高速性,经优化的SIFT匹配算法甚至可以达到实时的要求;
    6. 可扩展性,可以很方便的与其他形式的特征向量进行联合。

    KMeans聚类获得视觉单词,构建视觉单词词典

    现在得到的是所有图像的128维特征,每个图像的特征点数目还不一定相同(大多有差异)。现在要做的是构建一个描述图像的特征向量,也就是将每一张图像的特征点转换为特征向量。这儿用到了词袋模型,词袋模型源自文本处理,在这儿用在图像上,本质上是一样的。词袋的本质就是用一个袋子将所有维度的特征装起来,在这儿,词袋模型的维度需要我们手动指定,这个维度也就确定了视觉单词的聚类中心数。

    将图像特征点映射到视觉单词上,得到图像的特征向量:

    熟悉聚类算法的同学已经明白了,上面讲的簇就是通过聚类算法得到的,聚类算法将类别相近,属性相似的样本框起来,是一种无监督学习算法。在本文中,我使用了Kmeans算法来聚类得到视觉单词,通过聚类得到了聚类中心,通过聚类得到了表征词袋的特征点。

    我们得到k个聚类中心(一个聚类中心表征了一个维度特征,k由自己手动设置)和先前SIFT得到的所有图片的特征点,现在就是要通过这两项来构造每一张图像的特征向量。
    在本文中,构造的思路跟简单,就是比对特征点与所有聚类中心的距离,将特征点分配到距离最近的特征项,比如经计算某特征点距离leg这个聚类中心最近,那么这个图像中leg这个特征项+1。以此类推,每一张图像特征向量也就构造完毕。

    pickle读取文件

    pickle可以存储什么类型的数据呢?

    1. 所有python支持的原生类型:布尔值,整数,浮点数,复数,字符串,字节,None。

    2. 由任何原生类型组成的列表,元组,字典和集合。

    3. 函数,类,类的实例

    4. pickle模块中常用的方法有:

       1.pickle.dump(obj, file, protocol=None,)
      

      必填参数obj表示将要封装的对象

      必填参数file表示obj要写入的文件对象,file必须以二进制可写模式打开,即“wb”

      可选参数protocol表示告知pickler使用的协议,支持的协议有0,1,2,3,默认的协议是添加在Python 3中的协议3

       2.pickle.load(file,*,fix_imports=True,encoding="ASCII", errors="strict")
      

      必填参数file必须以二进制可读模式打开,即“rb”,其他都为可选参数

    支持向量机

    支持向量机的两个参数(调参增大准确率)

    SVM模型有两个非常重要的参数C与gamma。其中 C是惩罚系数,即对误差的宽容度。c越高,说明越不能容忍出现误差,容易过拟合。C越小,容易欠拟合。C过大或过小,泛化能力变差

    gamma是选择RBF函数作为kernel后,该函数自带的一个参数。隐含地决定了数据映射到新的特征空间后的分布,gamma越大,支持向量越少,gamma值越小,支持向量越多。支持向量的个数影响训练与预测的速度。

    此外大家注意RBF公式里面的sigma和gamma的关系如下:

    这里面大家需要注意的就是gamma的物理意义,大家提到很多的RBF的幅宽,它会影响每个支持向量对应的高斯的作用范围,从而影响泛化性能。我的理解:如果gamma设的太大,会很小,很小的高斯分布长得又高又瘦, 会造成只会作用于支持向量样本附近,对于未知样本分类效果很差,存在训练准确率可以很高,(如果让无穷小,则理论上,高斯核的SVM可以拟合任何非线性数据,但容易过拟合)而测试准确率不高的可能,就是通常说的过训练;而如果设的过小,则会造成平滑效应太大,无法在训练集上得到特别高的准确率,也会影响测试集的准确率。

    算法流程:

    1. SIFT提取每幅图像的特征点:

       import csv
       import os
       from sklearn.cluster import KMeans
       import cv2
       import numpy as np
       
       
       def knn_detect(file_list,cluster_nums, randomState = None):
           content = []
           input_x = []
           labels=[]
           features = []
           count = 0
           csv_file = csv.reader(open(file_list,'r'))
       	#读取csv文件
           for line in csv_file:
               if(line[2] !='label'):
                   subroot = 'F:\train\g' + str(line[2])
       			#路径拼接成绝对路径
                   filename =os.path.join(subroot, line[1])
                   sift = cv2.xfeatures2d.SIFT_create(200)
                   img = cv2.imdecode(np.fromfile(filename,dtype=np.uint8),-1)
       			#用np读图像,避免了opencv读取图像失败的问题
                   if img is not None:
       
                       gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
                       kpG, desG = sift.detectAndCompute(gray, None)
       				#关键点描述符
       
                       if desG is None:
       					#关键点不存在就结束循环
                           continue 
                       print(count)
                       count+=1
                       ll = np.array(line[2]).flatten()
                       labels.append(ll)
       				#得到标签
                       features.append(desG) 
       				#得到图像的特征矩阵
                       input_x.extend(desG)
           print(len(input_x))
           return features,labels,input_x
      
      
       #训练集图片处理
       des_list = []
       labelG = []
       input_x1 = []
       des_list,labelG,input_x1 = knn_detect('E:\py\train.csv',50)
       #测试机图片处理
       festures_test = []
       labels_test  = []
       input_x2 = []
       features_test,labels_test,input_x2 = knn_detect('E:\py\test.csv',50)
      

    结果截图:

    1. 保存中间变量:

       #利用pickle保存中间变量
       import numpy as np
       import matplotlib.pyplot as plt
       import pandas as pd
       import pickle
       
       output = open('input_x2.pkl', 'wb')
       pickle.dump(input_x2, output)
       output.close()
       
       output = open('features_test.pkl', 'wb')
       pickle.dump(features_test, output)
       output.close()
       
       output = open('labels_test.pkl', 'wb')
       pickle.dump(labels_test, output)
       output.close()
       
       output = open('input_x22.pkl', 'wb')
       pickle.dump(input_x2, output,protocol=2)
       output.close()
      
    2. 将图像特征点映射到视觉单词上,得到图像特征:

       df=open('input_x2.pkl','rb')#注意此处是rb
       #此处使用的是load(目标文件)
       input_x1=pickle.load(df)
       df.close()
       kmeans = KMeans(n_clusters = 50, n_jobs =4,random_state = None).fit(input_x1)
       #开四个线程加快计算
       centers = kmeans.cluster_centers_
      
    3. 将图像特征点映射到视觉单词上,得到图像的特征向量:

       def des2feature(des,num_words,centures):
       '''
       des:单幅图像的SIFT特征描述
       num_words:视觉单词数/聚类中心数
       centures:聚类中心坐标  
       计算特征矩阵中特征点离聚类中心最近的加1 
       return: feature vector 1*num_words
       '''
       img_feature_vec=np.zeros([num_words])
       for fi in des:
           diffMat = np.tile(fi, (50, 1)) - centers
           sqSum = (diffMat**2).sum(axis=1)
           dist = sqSum**0.5
           sortedIndices = dist.argsort()
           idx = sortedIndices[0] # index of the nearest center
       	#排序得到距离最近的聚类中心坐标的索引
           img_feature_vec[idx] += 1
       return img_feature_vec
      
       def get_all_features(des_list,num_words):
       # 获取所有图片的特征向量
       allvec=np.zeros((len(des_list),num_words),'float32')
       for i in range(len(des_list)):
           if des_list[i].any()!=None:
               allvec[i]=des2feature(centures=centers,des=des_list[i],num_words=num_words)
       return allvec
      
       df=open('des_list.pkl','rb')#注意此处是rb
       #此处使用的是load(目标文件)
       des_list=pickle.load(df)
       df.close()
       a =get_all_features(des_list,50)
       print(len(a))
       output = open('特征向量.pkl', 'wb')
       pickle.dump(a, output)
       output.close()
      
    4. svm训练,查看准确率:

       import numpy as np
       import matplotlib.pyplot as plt
       import pandas as pd
       import pickle
       from sklearn.preprocessing import StandardScaler
       df=open('label_train.pkl','rb')#注意此处是rb
       #此处使用的是load(目标文件)
       label_train=pickle.load(df)
       df.close()
       df=open('label_test.pkl','rb')#注意此处是rb
       #此处使用的是load(目标文件)
       label_test =pickle.load(df)
       df.close()
       sc = StandardScaler()
       X_train = sc.fit_transform(a)
       X_test = sc.fit_transform(b)
       
       from sklearn.svm import SVC
       classifier = SVC(C=15)
       #适当调整参数,不是一个固定值
       classifier.fit(X_train,label_train)
       
       y_pred = classifier.predict(X_test)
       
       print(classifier.score(X_train,label_train))
       from sklearn.metrics import classification_report
       print(classification_report(label_test,y_pred))
      

    结果截图:

  • 相关阅读:
    AS2 tween缓动
    flash 绑定 swc类文件
    jsfl自运行与被调运行
    一键清除fla文件中的TLF文本
    as 2的 Event.REMOVED_FROM_STAGE
    jsfl 添加代码
    jsfl 删除库指定内容
    文件上传待研究
    SpringMVC单文件上传、多文件上传、文件列表显示、文件下载
    shiro配置参考(二)可以和mybatis的配置放在一个文件中(不建议这样,可以拆分开来,注意相关配置即可)
  • 原文地址:https://www.cnblogs.com/gzyc/p/11221963.html
Copyright © 2011-2022 走看看