Viola Jones AdaBoost在开始之前就耗尽了内存

时间:2012-12-07 01:16:19

标签: computer-vision face-detection adaboost viola-jones

我正在实施Viola Jones算法进行人脸检测。我在算法的AdaBoost学习部分的第一部分遇到了问题。

原始论文陈述

  

弱分类器选择算法如下进行。对于每个要素,示例都根据要素值进行排序。

我目前正在使用相对较小的2000张正面图像和1000张负面图像。该论文描述了数据集大到10,000。

AdaBoost的主要目的是减少24x24窗口中的功能数量,总计160,000+。该算法适用于这些功能并选择最佳功能。

本文描述了对于每个特征,它计算每个图像的值,然后根据值对它们进行排序。这意味着我需要为每个特征制作一个容器并存储所有样本的值。

我的问题是我的程序在仅评估了10,000个功能(仅占其中的6%)后内存不足。所有容器的总体尺寸最终将达到160,000 * 3000,达到数十亿。如何在不耗尽内存的情况下实现此算法?我已经增加了堆大小,它让我从3%增加到6%,我认为增加它不会更有效。

本文暗示整个算法需要这些排序值,因此我不能在每个特征后丢弃它们。

到目前为止,这是我的代码

public static List<WeakClassifier> train(List<Image> positiveSamples, List<Image> negativeSamples, List<Feature> allFeatures, int T) {
    List<WeakClassifier> solution = new LinkedList<WeakClassifier>();

    // Initialize Weights for each sample, whether positive or negative
    float[] positiveWeights = new float[positiveSamples.size()];
    float[] negativeWeights = new float[negativeSamples.size()];

    float initialPositiveWeight = 0.5f / positiveWeights.length;
    float initialNegativeWeight = 0.5f / negativeWeights.length;

    for (int i = 0; i < positiveWeights.length; ++i) {
        positiveWeights[i] = initialPositiveWeight;
    }
    for (int i = 0; i < negativeWeights.length; ++i) {
        negativeWeights[i] = initialNegativeWeight;
    }

    // Each feature's value for each image
    List<List<FeatureValue>> featureValues = new LinkedList<List<FeatureValue>>();

    // For each feature get the values for each image, and sort them based off the value
    for (Feature feature : allFeatures) {
        List<FeatureValue> thisFeaturesValues = new LinkedList<FeatureValue>();

        int index = 0;
        for (Image positive : positiveSamples) {
            int value = positive.applyFeature(feature);
            thisFeaturesValues.add(new FeatureValue(index, value, true));
            ++index;
        }
        index = 0;
        for (Image negative : negativeSamples) {
            int value = negative.applyFeature(feature);
            thisFeaturesValues.add(new FeatureValue(index, value, false));
            ++index;
        }

        Collections.sort(thisFeaturesValues);

        // Add this feature to the list
        featureValues.add(thisFeaturesValues);
        ++currentFeature;
    }

    ... rest of code

1 个答案:

答案 0 :(得分:1)

这应该是选择其中一个弱分类器的伪代码:

normalize the per-example weights  // one float per example

for feature j from 1 to 45,396:
  // Training a weak classifier based on feature j.
  - Extract the feature's response from each training image (1 float per example)
  // This threshold selection and error computation is where sorting the examples
  // by feature response comes in.
  - Choose a threshold to best separate the positive from negative examples
  - Record the threshold and weighted error for this weak classifier

choose the best feature j and threshold (lowest error)

update the per-example weights

您无需存储数十亿个功能。只需在每次迭代时即时提取特征响应。您使用的是积分图像,因此提取速度很快。这是主要的内存瓶颈,并不是那么多,每个图像中每个像素只有一个整数...基本上与您所需图像的存储量相同。

即使您只计算了所有图像的所有特征响应并将它们全部保存,因此您不必每次迭代都这样做,但仍然只有:

  • 45396 * 3000 * 4字节= ~520 MB,或者如果您确信有160000种可能的功能,
  • 160000 * 3000 * 4字节= ~1.78 GB,或者如果您使用10000个训练图像,
  • 160000 * 10000 * 4字节= ~5.96 GB

基本上,即使您 存储所有功能值,也不应该耗尽内存。