sift特征提取+Kmean+SVM分类

新手上路,从头讲起

1、工具

原版代码:http://www.cs.ubc.ca/~lowe/keypoints/

vlfeat工具:http://www.vlfeat.org/index.html

这两个工具都可以进行sift特征提取以及匹配。我使用的是vlfeat工具箱,使用环境为win10,matlab。

  • 下载:
  • 下载后得到一个压缩包:
  • 将压缩包放到任意文件夹下并解压,得到文件:
  • 在matlab中打开解压后的文件夹,进入toolbox子文件夹,如红色框;然后双击打开vl_setup.m脚本,如蓝色框。sift特征提取+Kmean+SVM分类_第1张图片
  • 运行vl_setup.m代码。sift特征提取+Kmean+SVM分类_第2张图片
  • 在matlab当中进入自己的工程所在文件夹就可以调用vlfeat里面的函数了。不过这个方法需要每次使用之前执行vl_setup.m文件比较麻烦。可以长期导入,方法自行百度。


2、sift特征提取

  • 我在本次实验中只需要提取sift特征,并不涉及匹配相关。
image=imread('1.jpg'); %读取图片,此处读取图片为RGB
I = single(rgb2gray(image)); %函数传入图片格式固定为二维图像的single或者double类型,因此此处转为灰度,并改数据格式为single
I=(I-min(min(I))+1)/(max(max(I))-min(min(I))+1); %因为single格式图片需要数据范围为0~1时才可以正常显示,因此在这里调整一次数据大小,方便显示。
                                                 %实际上上一步的I转为single格式之后就可以了,有无这一步的操作并不会影响特征提取。
[f,d] = vl_dsift(I) ; %特征提取,得到的f是一个2*n的矩阵,每一列是一个坐标;d是特征数据,是一个128*n的矩阵,每列是一个特征。
  • sift特征提取的详细过程讲解:https://ianlondon.github.io/blog/how-to-sift-opencv/

3、    k-mean

  • 因为sift特征的特征点个数(keypoint)对于每张图片都是不一样的,因此没有办法直接进行SVM分类。参考多方文献之后发现比较多的文献用的是一种叫做BagOfWordsModel的方法,使用该方法对sift特征进行投影并归一化使特征长度一致。
  • 相关的讨论1(有ppt):https://www.researchgate.net/post/Image_classification_using_SIFT_features_and_SVM2
  • 相关的讨论2:https://stackoverflow.com/questions/19048891/training-of-svm-classifier-using-sift-features
  • 然后看不懂BOW方法的我发现大家用的其实是K-MEAN。
X=[];
for i=1:sizepic %循环一个所有图片
    name=piclist(i).name;
    feature=load(name); %读取之前保存的每张图片的特征矩阵的*.mat文件
    d=vertcat(feature.d); %因为之间保存的时候将f和d都保存了,所以需要从feature结构体中读取矩阵d
    Xpos=[Xpos,d]; %将矩阵简单的叠加起来,这里每一列是一个keypoint,所以把矩阵横向叠加
end
Xpos=double(Xpos); %由于kmean的函数要求数据格式为single或者double,因此这里将矩阵的数据格式转换为double
[Cp, Ap] = vl_kmeans(Xpos, 50, 'verbose', 'distance', 'l1', 'algorithm', 'elkan'); %kmean聚类,具体函数详解查看vlfeat文档啊

  • 在这里有一个疑问,在参考的代码方法中,给每一个类的所有图片做一个k-mean,保证k-mean之后数据长度一致。这样使用K-mean分类后的准确高达99%。但是在测试的时候就产生了一个问题,收到的数据到底应该使用哪一个聚类中心进行特征转化,进而进行识别。
  • 针对这一问题,我做了一个测试,将所有训练数据都适应于两个聚类中心进行聚类,每张图片最终得到了两个1*50的特征,将这两个特征分别使用模型进行分类。分类结果发现96%数据都是使用A的聚类中心聚类后分类结果为A类,使用B的聚类中心进行聚类后分类结果为B。
  • 对此,我使用所有的sift特征进行k-mean聚类,对两类图片的sift特征进行聚类变换之后进行分类,发现其分类准确率降低到了90%。


4、将每一张图片的特征放入k-mean聚类中心中转换

name=list(i).name;
image=imread(name);
I = single(rgb2gray(image)) ;
I=(I-min(min(I))+1)/(max(max(I))-min(min(I))+1);

[f,d] = vl_dsift(I) ; % sift

featVec=zeros(1,50);
for j=1:size(d,2)
    fi = double(d(:,j));
    diffMat = repmat(fi, 1,50) - Cp;
    sqSum = sum(diffMat.^2,1);
    dist = sqrt(sqSum);
    [val,idx]=min(dist);
    featVec(1,idx) = 1+ featVec(1,idx) ;
end

feature(count,:)=[featVec,1]; % 将特征和标签一起放入特征集合
count=count+1;

5、分类模型

  • 使用matlab自带的APP工具进行分类,在尝试了SVM,KNN,随机森林等多种分类方法之后选择了随机森林的分类模型作为实验的分类模型。

6、分类测试

lab = module.predictFcn(featVec); #传入与训练模型一致的50维特征进行分类




其他参考网站链接

  • 参考代码:https://blog.csdn.net/u012874151/article/details/45457085

博主的代码是python代码,很详细。

  • 算法思路:https://blog.csdn.net/m0_37393277/article/details/74987165

博主很详细的讲解了sift+kmean+svm的算法思想,博主的论文里面的东西在博客当中基本已经讲解清楚了,除了一个不同数量聚类中心的对比试验在论文中详细讲解,其他都讲完了。

  • sift应用实例:https://blog.csdn.net/abcjennifer/article/details/7365882






你可能感兴趣的:(sift特征提取+Kmean+SVM分类)