我正在尝试在OpenCV中实现词袋模型,并已经完成了下面的实现。我使用的是Caltech 101数据库。由于这是我第一次尝试,并且不太熟悉,我计划使用数据库中的两个图像集,椅子图像集和足球图像集。我使用这个来编写SVM的代码。
一切都进行得很顺利,除了当我调用classifier.predict(descriptor)
时,我没有得到预期的标签值。无论我的测试图像是什么,我总是得到0
而不是’1′。椅子数据集中的图像数量是10
,足球数据集中的图像数量是10
。我将椅子标记为0
,足球标记为1
。链接代表每个类别的样本,前10个是椅子,后10个是足球
function hello clear all; close all; clc; detector = cv.FeatureDetector('SURF'); extractor = cv.DescriptorExtractor('SURF'); links = { 'http://i.imgur.com/48nMezh.jpg' 'http://i.imgur.com/RrZ1i52.jpg' 'http://i.imgur.com/ZI0N3vr.jpg' 'http://i.imgur.com/b6lY0bJ.jpg' 'http://i.imgur.com/Vs4TYPm.jpg' 'http://i.imgur.com/GtcwRWY.jpg' 'http://i.imgur.com/BGW1rqS.jpg' 'http://i.imgur.com/jI9UFn8.jpg' 'http://i.imgur.com/W1afQ2O.jpg' 'http://i.imgur.com/PyX3adM.jpg' 'http://i.imgur.com/U2g4kW5.jpg' 'http://i.imgur.com/M8ZMBJ4.jpg' 'http://i.imgur.com/CinqIWI.jpg' 'http://i.imgur.com/QtgsblB.jpg' 'http://i.imgur.com/SZX13Im.jpg' 'http://i.imgur.com/7zVErXU.jpg' 'http://i.imgur.com/uUMGw9i.jpg' 'http://i.imgur.com/qYSkqEg.jpg' 'http://i.imgur.com/sAj3pib.jpg' 'http://i.imgur.com/DMPsKfo.jpg' }; N = numel(links); trainer = cv.BOWKMeansTrainer(100); train = struct('val',repmat({' '},N,1),'img',cell(N,1), 'pts',cell(N,1), 'feat',cell(N,1)); for i=1:N train(i).val = links{i}; train(i).img = imread(links{i}); if ndims(train(i).img > 2) train(i).img = rgb2gray(train(i).img); end; train(i).pts = detector.detect(train(i).img); train(i).feat = extractor.compute(train(i).img,train(i).pts); end; for i=1:N trainer.add(train(i).feat); end; dictionary = trainer.cluster(); extractor = cv.BOWImgDescriptorExtractor('SURF','BruteForce'); extractor.setVocabulary(dictionary); for i=1:N desc(i,:) = extractor.compute(train(i).img,train(i).pts); end; a = zeros(1,10)'; b = ones(1,10)'; labels = [a;b]; classifier = cv.SVM; classifier.train(desc,labels); test_im =rgb2gray(imread('D:\ball1.jpg')); test_pts = detector.detect(test_im); test_feat = extractor.compute(test_im,test_pts); val = classifier.predict(test_feat); disp('Value is: ') disp(val) end
这些是我的测试样本:
足球
(来源: timeslive.co.za)
椅子
通过搜索这个网站,我认为我的算法是可以的,尽管我对它不太有信心。如果有人能帮助我找到错误,将不胜感激。
根据Amro的代码,我的结果如下:
类别分布: 值 计数 百分比 1 62 49.21% 2 64 50.79%训练实例数量 = 61测试实例数量 = 65检测到的关键点数量 = 38845代码本大小 = 100SVM模型参数: svm_type: 'C_SVC' kernel_type: 'RBF' degree: 0 gamma: 0.5063 coef0: 0 C: 62.5000 nu: 0 p: 0 class_weights: 0 term_crit: [1x1 struct]混淆矩阵:ans = 29 1 1 34准确率 = 96.92 %
回答:
你的逻辑看起来不错。
现在我想你需要调整各种参数来提高分类准确性。这包括聚类算法的参数(如词汇表大小、聚类初始化、终止条件等)、SVM参数(核类型、C
系数等)、使用的局部特征算法(SIFT、SURF等)。
理想情况下,每当你想要进行参数选择时,你应该使用交叉验证。一些方法已经内置了这种机制(例如CvSVM::train_auto
),但大多数情况下你需要手动进行…
最后,你应该遵循一般的机器学习指导方针;查看整个偏差-方差权衡 困境。在线的Coursera机器学习课程在第6周详细讨论了这个话题,并解释了如何进行错误分析和使用学习曲线来决定下一步尝试什么(我们是否需要添加更多实例,增加模型复杂性,等等)。
话虽如此,我编写了自己的代码版本。你可能想将其与你的代码进行比较: