当谈到级联分类器(使用类似 haar 的特征)时,我总是读到像 AdaBoosting 这样的方法用于选择“最佳”特征进行检测。但是,这仅在有一些初始功能集开始增强时才有效。
给定一个 24x24 像素的图像,有 162,336 个可能的 haar 特征。我在这里可能错了,但我不认为像 openCV 这样的库最初会针对所有这些特性进行测试。
所以我的问题是如何选择初始特征或它们是如何生成的?有没有关于初始特征数量的指导方针?
如果最初使用所有 162,336 个特征。它们是如何产生的?
当谈到级联分类器(使用类似 haar 的特征)时,我总是读到像 AdaBoosting 这样的方法用于选择“最佳”特征进行检测。但是,这仅在有一些初始功能集开始增强时才有效。
给定一个 24x24 像素的图像,有 162,336 个可能的 haar 特征。我在这里可能错了,但我不认为像 openCV 这样的库最初会针对所有这些特性进行测试。
所以我的问题是如何选择初始特征或它们是如何生成的?有没有关于初始特征数量的指导方针?
如果最初使用所有 162,336 个特征。它们是如何产生的?
从您的问题中,我可以理解您想知道什么是 1,62,336 个功能。
来自 4 个原始 viola jones 功能(http://en.wikipedia.org/wiki/Viola%E2%80%93Jones_object_detection_framework)
我们可以通过改变 4 个原始特征的大小及其在 24*24 输入图像上的位置来生成 1,62,336 个特征。
例如,考虑具有两个彼此相邻的矩形的原始特征之一。让我们考虑每个矩形的大小是 1 个像素。最初,如果在 24*24 图像的 (0,0) 上存在一个矩形,则将其视为一个特征,现在如果将其水平移动一个像素(到 (1,0) ),则将其视为第二个特征它的位置更改为 (1,0)。通过这种方式,您可以将其水平移动到 (22,0),生成 23 个特征。同样,如果您沿着垂直轴从 (0,0) 向上移动到 (0,23),那么您可以生成 24 个特征。现在,如果您移动覆盖每个位置的图像(例如 (1,1),(1,2).....(22,23) ),那么您可以生成 24*23=552 个特征。
现在如果我们考虑每个矩形的宽度是 2 像素,高度是 1 像素。最初,如果一个矩形出现在 (0,0) 上,并且如上所述沿水平轴移动到 (20,0),那么我们可以有 21 个特征,因为如果我们从 (0, 0) 到 (0,23) 我们可以有 24 个特征。因此,如果我们移动以覆盖图像上的每个位置,那么我们可以拥有 24*21=504 个特征。
这样,如果我们将每个矩形的宽度增加一个像素,保持每个矩形的高度为 1 像素,每次我们覆盖完整的图像时,它的宽度从 1 像素变为 24 像素,我们得到否。特征数 = 24*(23+21+19.....3+1)
现在,如果我们考虑每个矩形的宽度为 1 像素,高度为 2 像素。最初,如果在 (0,0) 上存在一个矩形并沿水平轴移动到 (23,0),那么我们可以有 23 个特征,因为它的宽度为 1 像素,如果我们沿垂直轴移动,它的高度为 2 像素从 (0,0) 到 (0,22) 那么我们可以有 23 个特征。因此,如果我们移动以覆盖图像上的每个位置,那么我们可以拥有 23*23=529 个特征。
类似地,如果我们将每个矩形的宽度增加一个像素,并且每次覆盖完整图像时每个矩形的高度为 2 个像素,那么它的宽度从 1 个像素变为 24 个像素,我们得到否。特征数 = 23*(23+21+19.....3+1)
现在,如果我们在将每个矩形的宽度从 1 像素更改为 24 像素之后将每个矩形的高度增加 1 像素,直到每个矩形的高度变为 24 像素,那么
不。特征数 = 24*(23+21+19.....3+1) + 23*(23+21+19.....3+1) + 22*(23+21+19... ..3+1) +..................+ 2*(23+21+19.....3+1) + 1*(23+21+ 19.....3+1)
= 43,200 features
现在,如果我们考虑 2nd viola jones 原始特征,它有两个矩形,一个矩形在另一个矩形之上(即矩形垂直排列),因为这类似于 1st viola jones 原始特征,它也将具有
不。特征数 = 43,200
类似地,如果我们按照上述过程,从第 3 个原始 viola jones 特征中,有 3 个沿水平方向排列的矩形,我们得到
不。特征数 = 24*(22+19+16+....+4+1) + 23*(22+19+16+....+4+1) + 22*(22+19+16+ ....+4+1) +................+ 2*(22+19+16+....+4+1) + 1*(22 +19+16+....+4+1)
=27,600
现在,如果我们考虑另一个具有 3 个垂直排列的矩形的特征(即一个矩形叠加在另一个矩形上),那么我们得到
不。特征数 = 27,600(因为它类似于第 3 个原始中提琴琼斯特征)
最后,如果我们考虑具有 4 个矩形的第 4 个原始 viola jones 特征,我们得到
特征数 = 23*(23+21+19+......3+1) + 21*(23+21+19+......3+1) + 19*(23+ 21+19+......3+1) ......................+ 3*(23+21+19+......3+ 1) + 1*(23+21+19+......3+1)
= 20,736
现在总结所有这些特征,我们得到 = 43,200 + 43,200 + 27,600 + 27,600 + 20,736
= 1,62,336 features
因此,Adaboost 从上面的 1,62,336 个特征中选择其中的一些来形成强分类器。
我想,你应该熟悉 Viola/Jones关于这个主题的原创作品。
您首先手动选择特征类型(例如矩形 A)。这为您提供了一个掩码,您可以使用它来训练您的弱分类器。为了避免逐个像素地移动掩码和重新训练(这将花费大量时间并且没有更好的准确性),您可以指定每个训练的弱分类器在 x 和 y 方向上移动多少。跳跃的大小取决于您的数据大小。目标是让面罩能够移入和移出检测到的对象。特征的大小也可以是可变的。
在您训练了具有各自特征(即掩码位置)的多个分类器之后,您可以像往常一样继续进行 AdaBoost 和 Cascade 训练。
特征/弱分类器的数量很大程度上取决于您的数据和实验设置(即也是您使用的分类器类型)。您需要对参数进行扩展测试,以了解哪种类型的功能效果最好(矩形/圆形/类似俄罗斯方块的对象等)。我在 2 年前从事这项工作,我们花了很长时间来评估哪些特征和特征生成启发式产生了最好的结果。
如果你想从某个地方开始,只需选取 4 个原始 Viola/Jones 特征中的 1 个,然后训练一个分类器,将其应用到 (0,0)。用 (x,0) 训练下一个分类器。下一个是 (2x,0)....(0,y), (0,2y), (0,4y),.. (x,y), (x, 2y) 等等...看看什么发生。很可能您会发现使用较少的弱分类器是可以的,即您可以继续增加决定掩码如何滑动的 x/y 步长值。你也可以让面具长大或做其他事情来节省时间。这种“惰性”特征生成起作用的原因是 AdaBoost:只要这些特征使分类器比随机分类器稍微好一点,AdaBoost 就会将这些分类器组合成一个有意义的分类器。
在我看来,这里有点混乱。
即使是接受的答案对我来说似乎也不正确(也许我没有很好地理解它)。最初的 Viola-Jones 算法,后来的主要改进为 Lienhart-Maydt 算法,以及 Opencv 实现,它们都依次评估特征集的每一个特征。
您可以查看 Opencv 的源代码(以及您喜欢的任何实现)。
在函数 void CvHaarEvaluator::generateFeatures() 结束时,您有 numFeatures,对于 BASIC 模式和大小为 24x24,它只有 162,336。
当所有的特征集都以 featureEvaluator ( source ) 的形式提供时,所有这些都被依次检查:
bool isStageTrained = tempStage->train( (CvFeatureEvaluator*)featureEvaluator, curNumSamples,
_precalcValBufSize, _precalcIdxBufSize, *((CvCascadeBoostParams*)stageParams) );
每个弱分类器都是通过检查每个特征并选择在该点产生最佳结果的特征来构建的(在决策树的情况下,过程类似)。
在这个选择之后,样本的权重会相应地改变,以便在下一轮从所有特征集中再次选择一个不同的特征。单个特征评估的计算成本很低,但乘以 numFeatures 可能要求很高。
一个级联的整个训练可能需要数周时间,但瓶颈不是特征评估过程,而是最近阶段的负样本收集。
从您提供的维基百科链接中,我读到:
在一个标准的 24x24 像素子窗口中,总共有 M=162,336 个可能的特征,并且在测试图像时对它们进行评估会非常昂贵。
不要被这一点误导,这意味着在长时间的训练过程之后,您的检测算法应该非常快,并且只需要检查很少的特征(只是在训练期间选择的特征)。