如何使用面向对象梯度直方图的对象分类

314 阅读8分钟

使用面向对象梯度的直方图进行对象分类

定向梯度直方图(HOG)是计算机视觉和图像处理中用来描述某个数据特征的一种方法。它考虑的是图像局部的梯度方向出现的次数。

支持向量机(SVM)也被称为判别法。超平面定义了这种方法。超平面根据定义的区分特征将给定的数据分离成若干部分。

SVM模型使用超平面将一个给定的数据分成两个部分。超平面是所提供数据的分离点。需要注意的一点是,SVM并没有创建一个超平面。相反,它还创建了两个相互平行的超平面。

这两个超平面是最接近每个部分的点。超平面给人的警觉是准确有效地对你的数据进行分类。

在本教程中,我们将研究在HOG特征的帮助下进行多类物体分类。对于分类,我们使用基于ECOC的多类SVM。

前提条件

要学习本教程,你需要:

  • 安装[MATLAB]。
  • 对[MATLAB]基础知识的正确理解。

整体方案

Image of the scheme

在训练图像数据库中,我们在训练数据库的文件夹里有所有的训练图像。首先,所有这些图像被转换为其相应的HOG特征。然后,这些HOG特征被存储在特征数据库中,用于训练基于ECOC的多类SVM分类器。因此,一旦训练完成,我们就会得到一个训练好的分类器。训练好的分类器可以对输入的图像进行分类。

为了测试它的性能,我们给出一个测试图像。因此,所有存储在测试图像数据库中的测试图像首先被转换为其相应的HOG特征,然后交给训练好的分类器。然后,训练好的分类器对所有的输入图像进行分类,我们得到测试结果。基于这些结果,我们可以计算出准确率和混淆矩阵,等等。

图像数据集

我们将在[这里]使用的图像数据集总共有16000张灰度图像,大小为200 x 200 。我们将这些图像分为四类,即圆形、方形、三角形和星形。

在这16000张图片中,我们只使用4800张图片进行训练和测试。我们从每个类别中抽取1000张图像用于训练。总共有4000张图像。然后,我们从每个类别中使用200张图像进行测试。总共有800张图片用于测试。文件夹结构应如下图所示。

The folder structure

基于错误纠正输出代码(ECOC)的多类SVM

在机器学习中,许多算法,如线性回归、SVM等,可以处理二元分类问题。二元分类问题是指只有两个目标类别的问题,例如,是或不是,黑或白等,这意味着你只能将两个输入对象归入这两个类别。

在实践中,许多分类问题都属于多类分类问题;因此,二元SVM不能处理我们对四种不同形状进行分类的目标。然而,有一些修改过的SVM也适用于多类问题,如one vs restone vs one 。这些方法通过将一个给定的多类问题划分为固定数量的二进制问题来进行分类。

one vs restone vs one 不同,ECOC技术允许每个类在任意数量的分类问题中进行编码。此外,使用超决定性的表述,允许额外的模型作为error correction 预测,从而获得更好的预测性能。

在Matlab中实现多类SVM的ECOC分类器

Matlab有内置的函数fitcecoc ,其语法为。

fitcecoc(x, y, name, value)

其中。

  • x代表预测器(所有图像的特征向量的集合)。
  • y代表类标签。
  • name, value 代表名称值对参数。它有很多选项,但这里我们使用两个,即 和 。编码的默认选项是 ,而 是 。coding learners onevsone learners SVM

使用HOG特征进行物体分类的Matlab代码

现在,我们准备图像数据库。我们通过给出我们之前准备的训练和测试文件夹的目录来准备它。

path1 = 'trainimg';     %input all the training images
path2 = 'testimg';      %input all the test images 

然后我们读取所有这些训练和测试图像。

traindb = imageDatastore(path1,'IncludeSubfolders', true, 'LabelSource', 'foldernames'); 
testdb = imageDatastore(path2,'IncludeSubfolders', true, 'LabelSource', 'foldernames'); 

imageDatastore ,我们必须包括所有的子文件夹和文件夹名称。文件夹名称是LabelSource 。因此,所有的训练图像将进入traindb ,而测试图像将进入testdb 变量。

训练

首先,我们从训练数据库中读取一张图片并定义单元大小。我们在这里使用的单元格大小是16x16 ,用于HOG特征。注意,你可以把这个单元格大小改为8x8 ,甚至32x32

img = readimage(traindb, 1);
CS = [16, 16];

现在,找到第一幅图像的HOG特征。

[hogfv, hogvis] = extractHOGFeatures(img, 'CellSize', CS);

所有的HOG特征都存储在hogfv 这个变量中。然后,我们找到我们的hogfv 变量的长度,这就是HOG特征变量。然后,读取traindb 文件夹中的图像总数。

hogfeaturesize = length(hogfv);
totaltrainimages = numel(traindb.Files);

有了这两个信息,即图像的数量和HOG特征的大小,我们就定义了一个特征数据库。这个特征数据库是一个矩阵。行数等于训练文件夹中的图像数,而列数等于特征的长度。

trainfeatures = zeros(totaltrainimages, hogfeatures, 'single');    %feature database

上面的代码显示,trainfeature ,这个数据库存储了所有图像中的HOG特征。

之后,我们从traindb ,逐一读取所有这些图像,找到它们的HOG特征。这些HOG特征被存储在trainfeatures 矩阵中。

for i = 1:totaltrainimages
    img = readimage(traindb, i);
    %img = rgb2gray(img);
    trainingfeatures(i,:) = extractHOGFeatures(img, 'CellSize', CS);
end

我们还将使用下面的命令读取四个不同形状的标签。

traininglabels = traindb.Labels;

然后,我们将使用fitcecoc 函数来实现多类SVM的ECOC特征分类器。

%fitcecoc uses SVM learner and a 'one-vs-one' encoding scheme
classifiers = fitcecoc(trainingfeatures, traininglabels);

训练特征是X值,而traininglabels 是Y值。我们不定义任何其他参数,这意味着所有的参数都处于默认值。一旦完成,分类器参数将进入classifier 变量。

测试所有的图像

在这里,我们读取测试文件夹中的总图像数量和testfeatures 。它也是一个矩阵,行是测试图像的总数量,列是HOG特征的大小。

totaltestimages = numel(testdb.Files);
testfeatures = zeros(totaltestimages, hogfeatures, 'single');

然后,我们像以前一样,逐一读取测试图像。

for i = 1:totaltestimages
    imgt = readimage(testdb, i);
    testfeatures(i,:) = extractHOGFeatures(imgt, 'CellSize', CS);
end

然后是标签。

testlabels = testdb.Labels;      %getting labels

现在我们在testfeatures 矩阵中得到了所有的测试图像,并训练了我们的分类器,我们用predict 函数测试分类器。

predictedlabels = predicted(classifiers, testfeatures);

所以在这里,我们把训练好的分类器和所有测试图像的特征都储存在测试特征变量中。接下来,预测的标签被存储在predictedlabels 变量中。

之后,我们找出我们的分类器的准确性。这个准确性是预测的标签和预先定义的标签的比较。此外,你可以绘制混淆矩阵,这有助于解释结果。

accuracy = (sum(predictedlabels == testlabels)/numel(testlabels))*100;
plotconfusion(testlabels, predictedlabels)

如果我们运行这个程序,我们会得到如下图所示的混淆矩阵。它表明我们的分类器已经分类了。

confusion matrix

另外,在命令窗口中,我们可以看到准确性显示为100%。这是因为该数据库相当简单。如果你使用一个更具挑战性的数据库,它将低于100%。

离散测试

离散测试的代码应该在另一个脚本中。在这一点上,我们一次给出一张图片,并显示我们的分类器给出的输出。它首先读取一张图片,由用户输入。

%program to test HOG based object detection
[filename, filepath] = uigetfile('*.*', 'Select input image');
filewithpath = strcat(pathname, filename);
imgt = imread(filewithpath);

然后我们定义单元格的大小并提取其HOG特征。

CS = [16, 16];    %cell size
[hogfvt, hogvist] = extractHOGFeatures(imgt, 'CellSize', CS); %getting HOG features

然后,它将HOG特征交给分类器进行预测。

predictedLabel = predict(classifier, hogfvt);

我们在图像上打印预测的标签作为标题。

figure
imshow(imgt)
title(['Shape recognized is' char(predictedLabels)])

现在让我们运行这个程序进行离散测试。当你运行它时,Matlab要求用户输入形状,一旦完成,形状就会被识别,如下图所示。

image recognition

为了看看我们的分类器的鲁棒性,我们要使用一个扭曲的图像,看看分类器是否还能识别它。对于图像的扭曲,你可以使用你喜欢的软件。因此,你扭曲了图像,并将其作为输入。让我们看看这个方案是如何运作的。

distorted image

正如我们所看到的,该方案运行良好。这意味着,它是准确和稳健的。

总结

使用HOG特征和ECOC多类SVM进行物体分类是一个程序性过程。你需要了解这个方案,这样你就可以知道你的程序中发生了什么。这对错误识别很重要。

另外,该方案是准确和稳健的。这意味着它对更复杂的数据集更可靠。即使对于复杂的数据集,准确率不会是100%,但准确率会尽可能高。这使得它成为一个很好的物体识别方法。