88

私はViola-Jonesの顔検出アルゴリズムの適応を実装してきました。この手法は、画像内に24x24ピクセルのサブフレームを配置し、その後、可能な限りすべてのサイズですべての位置に長方形のフィーチャを配置することに依存しています。

これらの機能は、2つ、3つ、または4つの長方形で構成できます。次の例を示します。

長方形の機能

彼らは、網羅的なセットが180k以上であると主張しています(セクション2):

検出器の基本解像度が24x24であることを考えると、長方形の特徴の網羅的なセットは非常に大きく、180,000を超えます。Haarの基礎とは異なり、長方形の特徴のセットは不完全であることに注意してください。

以下の記述は、この論文では明示的に述べられていないため、私の側の仮定です。

  1. 2つの長方形の機能が2つ、3つの長方形の機能が2つ、4つの長方形の機能が1つだけです。この背後にある論理は、強調表示された長方形の違いを観察していることであり、色や輝度などを明示的に観察しているわけではありません。
  2. フィーチャタイプAを1x1ピクセルブロックとして定義することはできません。少なくとも1x2ピクセルである必要があります。また、タイプDは少なくとも2x2ピクセルである必要があり、このルールは他の機能にも適用されます。
  3. 中央のピクセルは分割できないため、フィーチャタイプAを1x3ピクセルのブロックとして定義することはできません。また、それ自体からそれを差し引くことは1x2ピクセルのブロックと同じです。このフィーチャタイプは、偶数の幅に対してのみ定義されます。また、フィーチャタイプCの幅は3で割り切れる必要があり、このルールは他のフィーチャにも適用されます。
  4. 幅や高さが0のフィーチャを定義することはできません。したがって、xyを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を削除し、コードにバグを導入することです。これには、4行をそれぞれ次のように変更することが含まれます。

for (int width = 0; width < frameSize-x; width+=sizeX)
for (int height = 0; height < frameSize-y; height+=sizeY)

その結果、180,625になります。(これにより、機能がサブフレームの右または下、あるいはその両方に接触するのを効果的に防ぐことができます。)

もちろん、質問です。彼らは実装に誤りを犯しましたか?サーフェスがゼロのフィーチャを検討することは意味がありますか?それとも私はそれを間違った方法で見ていますか?

4

6 に答える 6

41

よく見ると、あなたのコードは私には正しいように見えます。これは、元の作者が1つずつバグを持っていたかどうか疑問に思います。誰かがOpenCVがそれをどのように実装するかを見るべきだと思います!

それでも、理解しやすくするための1つの提案は、最初にすべてのサイズを調べてから、サイズを指定して可能な場所をループすることにより、 forループの順序を反転することです。

#include <stdio.h>
int main()
{
    int i, x, y, sizeX, sizeY, width, height, count, c;

    /* All five shape types */
    const int features = 5;
    const int feature[][2] = {{2,1}, {1,2}, {3,1}, {1,3}, {2,2}};
    const int frameSize = 24;

    count = 0;
    /* Each shape */
    for (i = 0; i < features; i++) {
        sizeX = feature[i][0];
        sizeY = feature[i][1];
        printf("%dx%d shapes:\n", sizeX, sizeY);

        /* each size (multiples of basic shapes) */
        for (width = sizeX; width <= frameSize; width+=sizeX) {
            for (height = sizeY; height <= frameSize; height+=sizeY) {
                printf("\tsize: %dx%d => ", width, height);
                c=count;

                /* each possible position given size */
                for (x = 0; x <= frameSize-width; x++) {
                    for (y = 0; y <= frameSize-height; y++) {
                        count++;
                    }
                }
                printf("count: %d\n", count-c);
            }
        }
    }
    printf("%d\n", count);

    return 0;
}

前と同じ結果になります162336


それを確認するために、4x4ウィンドウのケースをテストし、すべてのケースを手動でチェックしました(1x2/2x1と1x3/3x1の形状は同じで、90度回転するだけなので簡単に数えられます)。

2x1 shapes:
        size: 2x1 => count: 12
        size: 2x2 => count: 9
        size: 2x3 => count: 6
        size: 2x4 => count: 3
        size: 4x1 => count: 4
        size: 4x2 => count: 3
        size: 4x3 => count: 2
        size: 4x4 => count: 1
1x2 shapes:
        size: 1x2 => count: 12             +-----------------------+
        size: 1x4 => count: 4              |     |     |     |     |
        size: 2x2 => count: 9              |     |     |     |     |
        size: 2x4 => count: 3              +-----+-----+-----+-----+
        size: 3x2 => count: 6              |     |     |     |     |
        size: 3x4 => count: 2              |     |     |     |     |
        size: 4x2 => count: 3              +-----+-----+-----+-----+
        size: 4x4 => count: 1              |     |     |     |     |
3x1 shapes:                                |     |     |     |     |
        size: 3x1 => count: 8              +-----+-----+-----+-----+
        size: 3x2 => count: 6              |     |     |     |     |
        size: 3x3 => count: 4              |     |     |     |     |
        size: 3x4 => count: 2              +-----------------------+
1x3 shapes:
        size: 1x3 => count: 8                  Total Count = 136
        size: 2x3 => count: 6
        size: 3x3 => count: 4
        size: 4x3 => count: 2
2x2 shapes:
        size: 2x2 => count: 9
        size: 2x4 => count: 3
        size: 4x2 => count: 3
        size: 4x4 => count: 1
于 2009-11-10T21:02:39.690 に答える
9

すべて。ViolaとJonesの論文にはまだ混乱があります。

彼らのCVPR'01論文では、次のように明確に述べられています。

「より具体的には、3 種類のフィーチャ を使用します。2つの長方形のフィーチャの値は、2つの長方形の領域内のピクセルの合計の差です。領域は同じサイズと形状であり、水平または垂直に隣接しています(図を参照)。 1) 。3つの長方形の特徴は、中央の長方形の合計から差し引かれた2つの外側の長方形内の合計を計算します。最後に4つの長方形の特徴"。

IJCV'04の論文でも、まったく同じことが言えます。つまり、全部で4つの機能です。しかし不思議なことに、彼らは今回、網羅的な機能セットは45396であると述べました!これは最終バージョンではないようです。ここでは、min_width、min_height、width / height比、さらには位置など、いくつかの追加の制約が導入されたと思います。

両方の論文が彼のウェブページからダウンロード可能であることに注意してください。

于 2010-07-21T12:42:54.307 に答える
3

論文全体を読んでいないので、あなたの引用の言葉遣いは私に突き出ています

検出器の基本解像度が24x24であることを考えると、長方形の特徴の網羅的なセットは非常に大きく、180,000を超えます。Haarの基礎とは異なり、長方形の特徴のセットは不完全であることに注意してください。

「長方形の特徴のセットが過剰です」「網羅的なセット」

セットアップのように聞こえます。たとえば、ゼロの長方形などの些細なケースを取り除くことで、ペーパーライターが検索スペースをより効果的なセットに絞り込む方法についての説明をフォローアップすることを期待しています。表面積。

編集:または、抽象的なヒントとして、ある種の機械学習アルゴリズムを使用します。網羅的なセットは、「合理的な」ものだけでなく、すべての可能性を意味します。

于 2009-11-10T12:50:09.653 に答える
2

論文の著者がすべての仮定と発見において正しいという保証はありません。仮定#4が有効であると思われる場合は、その仮定を維持し、理論を試してください。あなたは元の作者よりも成功するかもしれません。

于 2009-11-10T13:00:39.170 に答える
1

かなり良い観察ですが、24x24フレームを暗黙的にゼロパッドするか、「オーバーフロー」して、回転シフトのように、またはBretonが言ったように、範囲外になると最初のピクセルの使用を開始する可能性があります。その後、AdaBoostでそれらを破棄します。

さらに、PythonとMatlabのバージョンのコードを作成して、自分でコードをテストできるようにしました(デバッグとフォローが簡単です)。そのため、誰かがいつか役立つと思ったら、ここに投稿します。

Python:

frameSize = 24;
features = 5;
# All five feature types:
feature = [[2,1], [1,2], [3,1], [1,3], [2,2]]

count = 0;
# Each feature:
for i in range(features):
    sizeX = feature[i][0]
    sizeY = feature[i][1]
    # Each position:
    for x in range(frameSize-sizeX+1):
        for y in range(frameSize-sizeY+1):
            # Each size fitting within the frameSize:
            for width in range(sizeX,frameSize-x+1,sizeX):
                for height in range(sizeY,frameSize-y+1,sizeY):
                    count=count+1
print (count)

Matlab:

frameSize = 24;
features = 5;
% All five feature types:
feature = [[2,1]; [1,2]; [3,1]; [1,3]; [2,2]];

count = 0;
% Each feature:
for ii = 1:features
    sizeX = feature(ii,1);
    sizeY = feature(ii,2);
    % Each position:
    for x = 0:frameSize-sizeX
        for y = 0:frameSize-sizeY
            % Each size fitting within the frameSize:
            for width = sizeX:sizeX:frameSize-x
                for height = sizeY:sizeY:frameSize-y
                    count=count+1;
                end
            end
        end
    end
end

display(count)
于 2017-04-12T18:06:29.287 に答える
1

彼らの元の2001年の論文では、彼らは3種類の機能を使用したと述べているだけです。

3種類の機能を使用しています

それぞれ2つ、3つ、4つの長方形があります。

それぞれの種類には2つの方向(90度異なる)があるため、おそらく2 * 3種類の特徴を使用した特徴の総数を計算するために、2つの2つの長方形の特徴、2つの3つの長方形の特徴、2つの4つの長方形の特徴を使用しました。 。この仮定では、実際に180,000を超える機能があります。

feature_types = [(1,2), (2,1), (1,3), (3,1), (2,2), (2,2)]
window_size = (24,24)

total_features = 0
for f_type in feature_types:
    for f_height in range(f_type[0], window_size[0] + 1, f_type[0]):
        for f_width in range(f_type[1], window_size[1] + 1, f_type[1]):
            total_features += (window_size[0] - f_height + 1) * (window_size[1] - f_width + 1)
            
print(total_features)
# 183072

2番目の4つの長方形の機能は、最初の機能とは記号だけが異なるため、保持する必要はありません。削除すると、機能の総数は162,336に減少します。

于 2020-06-23T08:55:50.827 に答える