我一直在实施Viola-Jones 的人脸检测算法的改编版。该技术依赖于在图像中放置一个 24x24 像素的子帧,然后将矩形特征放置在图像中的每个位置,并具有各种可能的大小。
这些特征可以由两个、三个或四个矩形组成。给出了以下示例。
他们声称详尽的集合超过 180k(第 2 节):
鉴于检测器的基本分辨率为 24x24,详尽的矩形特征集相当大,超过 180,000 个。请注意,与 Haar 基不同,矩形特征集是过完备的。
以下陈述未在论文中明确说明,因此它们是我的假设:
- 只有 2 个二矩形特征、2 个三矩形特征和 1 个四矩形特征。这背后的逻辑是我们正在观察突出显示的矩形之间的差异,而不是明确地观察颜色或亮度或任何类似的东西。
- 我们不能将特征类型 A 定义为 1x1 像素块;它必须至少为 1x2 像素。此外,类型 D 必须至少为 2x2 像素,并且此规则适用于其他特征。
- 我们不能将特征类型 A 定义为 1x3 像素块,因为中间像素无法分割,从自身中减去它与 1x2 像素块相同;此特征类型仅针对偶数宽度定义。此外,特征类型 C 的宽度必须能被 3 整除,此规则也适用于其他特征。
- 我们无法定义宽度和/或高度为 0 的特征。因此,我们将x和y迭代为 24 减去特征的大小。
基于这些假设,我计算了详尽的集合:
const int frameSize = 24;
const int features = 5;
// All five feature types:
const int feature[features][2] = {{2,1}, {1,2}, {3,1}, {1,3}, {2,2}};
int count = 0;
// Each feature:
for (int i = 0; i < features; i++) {
int sizeX = feature[i][0];
int sizeY = feature[i][1];
// Each position:
for (int x = 0; x <= frameSize-sizeX; x++) {
for (int y = 0; y <= frameSize-sizeY; y++) {
// Each size fitting within the frameSize:
for (int width = sizeX; width <= frameSize-x; width+=sizeX) {
for (int height = sizeY; height <= frameSize-y; height+=sizeY) {
count++;
}
}
}
}
}
结果是162,336。
我发现近似 Viola & Jones 所说的“超过 180,000 个”的唯一方法是放弃假设 #4 并在代码中引入错误。这涉及将四行分别更改为:
for (int width = 0; width < frameSize-x; width+=sizeX)
for (int height = 0; height < frameSize-y; height+=sizeY)
结果是180,625。(请注意,这将有效地防止特征接触子框架的右侧和/或底部。)
现在当然是问题:他们在实施过程中犯了错误吗?考虑表面为零的特征是否有意义?还是我看错了?