Matlab实现HOG+SVM图像分类

转载自:http://blog.csdn.net/cuixing001/article/details/70908064,版权归原作者所有。

我训练的图像在磁盘上位置如下,包含5个类别,省去了前人制作txt存储图像路径的过程:

Matlab实现HOG+SVM图像分类


测试图像分布为:

Matlab实现HOG+SVM图像分类

作者的代码写的非常工整,值得学习,尤其是利用了imageDatastore这种存储格式,使用起来就方便多了。

[plain] view plain copy
  1. %% 用hog特征对图像进行多分类,svm训练,1 VS 1    
  2. %% 1 数据集,包括训练的和测试的 (注意自己图片存放路径,附录我给出示例下载图片链接)   
  3. imdsTrain = imageDatastore('F:\svm_images\train_images',...    
  4.     'IncludeSubfolders',true,...    
  5.     'LabelSource','foldernames');    
  6. imdsTest = imageDatastore('F:\svm_images\test_image');    
  7.   
  8.   
  9. %% 显示训练的图片种类Labels和数量Count  
  10. Train_disp = countEachLabel(imdsTrain);  
  11. disp(Train_disp);  
  12.     
  13. %%   2 对训练集中的每张图像进行hog特征提取,测试图像一样    
  14. % 预处理图像,主要是得到features特征大小,此大小与图像大小和Hog特征参数相关    
  15. imageSize = [256,256];% 对所有图像进行此尺寸的缩放    
  16. image1 = readimage(imdsTrain,1);    
  17. scaleImage = imresize(image1,imageSize);    
  18. [features, visualization] = extractHOGFeatures(scaleImage);    
  19. imshow(scaleImage);hold on; plot(visualization)    
  20.     
  21. % 对所有训练图像进行特征提取    
  22. numImages = length(imdsTrain.Files);    
  23. featuresTrain = zeros(numImages,size(features,2),'single'); % featuresTrain为单精度    
  24. for i = 1:numImages    
  25.     imageTrain = readimage(imdsTrain,i);    
  26.     imageTrain = imresize(imageTrain,imageSize);    
  27.     featuresTrain(i,:) = extractHOGFeatures(imageTrain);    
  28. end    
  29.     
  30. % 所有训练图像标签    
  31. trainLabels = imdsTrain.Labels;    
  32.     
  33. % 开始svm多分类训练,注意:fitcsvm用于二分类,fitcecoc用于多分类,1 VS 1方法    
  34. classifer = fitcecoc(featuresTrain,trainLabels);    
  35.     
  36. %% 预测并显示预测效果图    
  37. numTest = length(imdsTest.Files);    
  38. for i = 1:numTest    
  39.     testImage = readimage(imdsTest,i);    
  40.     scaleTestImage = imresize(testImage,imageSize);    
  41.     featureTest = extractHOGFeatures(scaleTestImage);    
  42.     [predictIndex,score] = predict(classifer,featureTest);    
  43.     figure;imshow(testImage);    
  44.     title(['predictImage: ',char(predictIndex)]);    
  45. end    
  46.     
  47.       

命令行对训练集imdsTrain
统计输出结果如下:

Matlab实现HOG+SVM图像分类

Matlab实现HOG+SVM图像分类

Matlab实现HOG+SVM图像分类

Matlab实现HOG+SVM图像分类

Matlab实现HOG+SVM图像分类

Matlab实现HOG+SVM图像分类

第一张图像显示的是提取到的HOG特征,这个主要可以初步了解下特征是否选择的合适,不合适可以调节extractHOGFeatures里面的参数,如cellsize,blocksize,bins等,具体可以参考这个点击打开链接


补充一点svm一对一、一对多的相关知识。转载自:http://www.cnblogs.com/CheeseZH/p/5265959.html

SVM本身是一个二值分类器

  SVM算法最初是为二值分类问题设计的,当处理多类问题时,就需要构造合适的多类分类器。

  目前,构造SVM多类分类器的方法主要有两类

  (1)直接法,直接在目标函数上进行修改,将多个分类面的参数求解合并到一个最优化问题中,通过求解该最优化问题“一次性”实现多类分类。这种方法看似简单,但其计算复杂度比较高,实现起来比较困难,只适合用于小型问题中;

  (2)间接法,主要是通过组合多个二分类器来实现多分类器的构造,常见的方法有one-against-one和one-against-all两种。

一对多法(one-versus-rest,简称OVR SVMs)

  训练时依次把某个类别的样本归为一类,其他剩余的样本归为另一类,这样k个类别的样本就构造出了k个SVM。分类时将未知样本分类为具有最大分类函数值的那类。

  假如我有四类要划分(也就是4个Label),他们是A、B、C、D。

  于是我在抽取训练集的时候,分别抽取

  (1)A所对应的向量作为正集,B,C,D所对应的向量作为负集;

  (2)B所对应的向量作为正集,A,C,D所对应的向量作为负集;

  (3)C所对应的向量作为正集,A,B,D所对应的向量作为负集;

  (4)D所对应的向量作为正集,A,B,C所对应的向量作为负集;

  使用这四个训练集分别进行训练,然后的得到四个训练结果文件。

  在测试的时候,把对应的测试向量分别利用这四个训练结果文件进行测试。

  最后每个测试都有一个结果f1(x),f2(x),f3(x),f4(x)。

  于是最终的结果便是这四个值中最大的一个作为分类结果。

评价:

  这种方法有种缺陷,因为训练集是1:M,这种情况下存在biased.因而不是很实用。可以在抽取数据集的时候,从完整的负集中再抽取三分之一作为训练负集。

一对一法(one-versus-one,简称OVO SVMs或者pairwise)

  其做法是在任意两类样本之间设计一个SVM,因此k个类别的样本就需要设计k(k-1)/2个SVM。

  当对一个未知样本进行分类时,最后得票最多的类别即为该未知样本的类别。

  Libsvm中的多类分类就是根据这个方法实现的。

  假设有四类A,B,C,D四类。在训练的时候我选择A,B; A,C; A,D; B,C; B,D;C,D所对应的向量作为训练集,然后得到六个训练结果,在测试的时候,把对应的向量分别对六个结果进行测试,然后采取投票形式,最后得到一组结果。

  投票是这样的:
  A=B=C=D=0;
  (A,B)-classifier 如果是A win,则A=A+1;otherwise,B=B+1;
  (A,C)-classifier 如果是A win,则A=A+1;otherwise, C=C+1;
  ...
  (C,D)-classifier 如果是A win,则C=C+1;otherwise,D=D+1;
  The decision is the Max(A,B,C,D)

评价:这种方法虽然好,但是当类别很多的时候,model的个数是n*(n-1)/2,代价还是相当大的。

层次支持向量机

层次分类法首先将所有类别分成两个子类,再将子类进一步划分成两个次级子类,如此循环,直到得到一个单独的类别为止。对层次支持向量机的详细说明可以参考论文《支持向量机在多类分类问题中的推广》(刘志刚,计算机工程与应用,2004)