sift & surf & bag-of-words 在目标识别中的应用详解
SIFT和SURF的每一个特征点的描述符维度固定,但不同图像获取的特征点数量不一致,从而导致不同图像的特征维度不一致。而 SVM模型训练时,要求每个样本的特征维度相同。如何实现用SIFT和SURF特征点来训练SVM模型呢?这是我在opencv3.1 SVM sample_HOG特征在车牌判断中的应用 一文中挖的坑,本文为填此坑而生,欢迎围观和指教。
1. 前言
开发环境说明
win10专业版 64位操作系统 + VS2013中文版 + opencv3.x(20161003源码) + opencv_contrib(20161003源码),本文讲述的例程已上传至CSDN和Github。
本文例程简介
本文的例程以opencv3.1 SVM sample_HOG特征在车牌判断中的应用 中的程序为母版,在此基础上根据opencv 3.1中的例程bagofwords_classification的结构添加了用SIFT和SURF特征训练SVM模型的部分,数据集和测试方法仍然是车牌识别系统EasyPR的车牌图像库。
EasyPR作者的博客计算机的潜意识, EasyPR在Github上的地址https://github.com/liuruoze/EasyPR。
2. SIFT & SURF SVM模型测试结果对比
下图是LBP, HOG,SIFT,SURF四种特征点进行SVM模型训练后的测试结果,四种特征使用的训练数据集和测试数据集均相同。我们可以在图中看到LBF和HOG特征测试总数为2332,SIFT的测试总数为2113,SURF的测试总数为2104。事实上,实际测试数据总量为2332,也就是说每一张测试图片都可得到LBP和HOG特征,但并不是每张图片都有SIFT和SURF特征点,因此在训练和测试时需要剔除那些没有SIFT或SURF特征点或者无法用SIFT或SURF组成的词汇表表达的训练图片和测试图片。
SIFT和SURF测试时,计算precise/recall/fscore时用的时实际测试总数2113/2104。
bagofwords_classification范例中默认取每张图片30%的特征点用于训练词汇表,词汇表的数量为1000。LBP/HOG/SIFT/SURF四个特征点对比图中,SIFT使用的是0.6_1000的测试结果。下图是SIFT特征点在0.3_1000和0.6_1000下的测试结果对比,虽然用于训练的特征总量翻倍,但测试结果并没有明显改善。
3.例程的使用方法
3.1 例程要求在当前项目的工程文件.vcproj相同目录下有一个名为param.xml的文件,程序产生的文件存储路径,切换特征点类型,BOW词汇表的总量等参数均需要在此文件中设置。该文件中的内容如下图所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<?xml version="1.0" ?> <opencv_storage> <!--path of the generated files--> <resPath>The path of the generated files</resPath> <!--featureType choices: LBP/HOG/SIFT/SURF/ORB/BRISK/KAZE/AKAZE--> <featureType>SIFT</featureType> <ddmParams><!--parameters of bag of words--> <detectorType>SIFT</detectorType> <descriptorType>SIFT</descriptorType> <matcherType>BruteForce</matcherType> </ddmParams> <vocabTrainParams> <vocabSize>1000</vocabSize><!--number of visual words in vocabulary to train--> <memoryUse>200</memoryUse> <!--Memory to preallocate (in MB) when training vocab.--> <!--pecifies the number of descriptors to use from each image as a proportion of the total num descs.--> <descProportion>0.3</descProportion> </vocabTrainParams> <svmTrainParamsExt> <descPercent>0.5</descPercent><!-- Percentage of extracted descriptors to use for training.--> <targetRatio>0.4</targetRatio><!-- Try to get this ratio of positive to negative samples (minimum)--> <!--Balance class weights by number of samples in each (if true cSvmTrainTargetRatio is ignored)--> <balanceClasses>true</balanceClasses> </svmTrainParamsExt> </opencv_storage> |
3.2 例程的大致执行流程如下图所示:
3.3 例程的特点
在学习opencv范例的bagofwords_classification之前,我在尝试SIFT和SURF特征点训练SVM模型时,曾参考网络上的一些使用BOW的基本例程训练词汇表并进行验证,训练的手法与bagofwords_classification基本一致,最大的不同点:用了所有图片的所有特征点进行BOW训练,结果预测所有测试图片均为负样本。基于此经历,我觉得bagofwords_classification中取每张图片的一部分特征点用于训练BOW词汇表是一个关键点。
此外,将每一张图片的特征点保存下来也是一个明智之举,当与特征点无关的参数需要微调时,可以节省大量的时间。
4.总结
opencv的源码和例程是学习opencv最好的资料,没有之一。
为什么每次保存的svm和训练的svm效果不一样呢
请确认训练的SVM文件保存且加载成功:)
文件肯定是保存了,然后在trainSVMClassifier()中load。这都没问题,但是之后predict任何目标返回都是0,可能是svm加载过程中出了问题,但具体在哪,还没查出来。
楼主不会在哪里又埋了什么坑吧
我可能真的挖了个坑,麻烦检查一下文件夹中的params.xml文件,将resPath修改为训练文件的保存路径。
这个坑早被我发现了 不管用
也是,这是个明坑,我在github上有介绍运行前需要先根据实际条件更改params.xml文件的。
另外我特意从github上下载了项目,重新训练,然后再加载,得到的predict结果是一样的,所以很抱歉你这个忙我估计帮不上了
查了一下 可能是版本问题 我用的是opencv3.0
我测试了一下,也是出现加载训练好的分类器测试,结果全为0。。。。不晓得为何
是否与opencv版本有关系呢?