Viola-Jones의 얼굴 감지 기능으로 180k 기능 주장


84

저는 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를 삭제하고 코드에 버그를 도입하는 것입니다. 여기에는 네 줄을 각각 다음과 같이 변경하는 작업이 포함됩니다.

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

결과는 180,625 입니다. (이렇게하면 기능이 서브 프레임의 오른쪽 및 / 또는 하단에 닿지 않도록 효과적으로 방지 할 수 있습니다.)

당연히 질문 : 구현에서 실수를 했습니까? 표면이 0 인 피쳐를 고려하는 것이 합리적입니까? 아니면 잘못된 방향으로보고 있습니까?


코드를 실행할 때 count = 114829가 표시되는 이유는 무엇입니까?
Niki

x / y 루프가 1에서 시작하는 이유는 무엇입니까? x / y가 기능 직사각형의 왼쪽 상단 좌표라고 가정합니다. x / y가 0/0에서 시작하면 안되나요?
Niki

0에서 시작하든 1에서 시작하든에서 끝나는 x < size것은 가정 # 4와 관련이 있습니다. 기능이 서브 프레임 내에 유지 되길 원하지만 크기가 1x1 이상이어야합니다. 기능의 차원이 서브 프레임 외부로 확장되어서는 안되는지 여부에 대해서는 아마도 가정 일 수도 있습니다.
Paul Lammertsma

마찬가지로 x를 0에서 시작하면로 실행해야 x < size - 1하므로 이득이 없습니다.
Paul Lammertsma

나는 수많은 for 루프를 수행했습니다. 이것은 나에게 잘못된 것 같습니다. <size는 x가 24가되는 것을 막아줍니다. 0에서 시작하면 0 ... 23이됩니다. 너비가 1 픽셀이면 사각형이 프레임을 벗어나지 않습니다.
Breton

답변:


40

자세히 살펴보면 귀하의 코드가 저에게 맞는 것처럼 보입니다. 이것은 원저자가 하나의 버그를 가지고 있는지 궁금하게 만듭니다. 누군가 OpenCV가 그것을 구현하는 방법을보아야한다고 생각합니다!

그럼에도 불구하고 이해하기 쉽도록하기위한 한 가지 제안은 먼저 모든 크기를 검토 한 다음 주어진 크기에 대해 가능한 위치를 반복 하여 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

설득력 있는. 그래서 저는 우리가 옳다고 확신합니다. 나는 내 추론에서 근본적인 실수를했는지 확인하기 위해 저자에게 이메일을 보냈다. 바쁜 남자가 대답 할 시간이 있는지 살펴 보겠습니다.
Paul Lammertsma

이 제품은 2 년 동안
출시

25
180k가 언급 된 원본 논문은 2001 년 컴퓨터 비전 및 패턴 인식 컨퍼런스에서 나온 것입니다. 2003 년에 채택되어 2004 년에 International Journal of Computer Vision에 발표 된 개정 된 논문은 p. 139 (섹션 2의 끝) : "전체 직사각형 집합은 160,000으로 상당히 큽니다." 우리가 옳은 것 같습니다!
Paul Lammertsma

3
좋습니다. 업데이트 해 주셔서 감사합니다. 관심있는 사람들을 위해 IJCV'04 논문에 대한 링크를 찾았습니다. lear.inrialpes.fr/people/triggs/student/vj/viola-ijcv04.pdf
Amro

그래 그거야. 180k가 아니라 160k입니다.
Paul Lammertsma

9

모두. Viola와 Jones의 논문에는 여전히 약간의 혼란이 있습니다.

그들의 CVPR'01 논문에는

"좀 더 구체적으로 말하자면, 우리는 종류의 특징을 사용 합니다. 두 개의 직사각형 특징 의 값은 두 직사각형 영역 내의 픽셀 합계의 차이입니다. 영역은 크기와 모양이 같고 수평 또는 수직으로 인접합니다 (그림 참조). 1) 세 개의 직사각형 특성 은 중앙 직사각형의 합계에서 뺀 두 외부 직사각형 내의 합계를 계산합니다. 마지막 으로 네 직사각형 특성 ".

IJCV'04 논문에서도 똑같은 말이 있습니다. 총 4 개의 기능이 있습니다 . 그러나 이상하게도 이번에는 완전한 기능 세트가 45396이라고 말했습니다! 이것이 최종 버전이 아닌 것 같고 여기에 min_width, min_height, width / height ratio, even position과 같은 몇 가지 추가 제약이 도입 된 것 같습니다.

두 문서 모두 그의 웹 페이지에서 다운로드 할 수 있습니다 .


3

논문 전체를 읽지 못한 채 당신의 말이 튀어 나와

감지기의 기본 해상도가 24x24라는 점을 감안할 때 전체 직사각형 기능 집합은 180,000 이상으로 상당히 큽니다. Haar 기반과 달리 직사각형 기능 세트가 과도하게 완성되었습니다.

"사각형 기능 세트가 과도합니다" "완전 세트"

마치 설정처럼 들리는데, 종이 작성자가 검색 공간을 더 효과적인 세트로 뽑아내는 방법에 대한 설명을 추가 할 것으로 예상됩니다. 예를 들어 0이있는 직사각형과 같은 사소한 경우를 제거하는 방법 표면적.

편집 : 또는 추상적 인 힌트처럼 어떤 종류의 기계 학습 알고리즘을 사용합니다. 철저한 세트는 "합리적인"가능성뿐만 아니라 모든 가능성을 의미합니다.


"overcomplete"뒤에 각주를 포함해야합니다. "완전한 기저는 기저 요소간에 선형 종속성이 없으며 이미지 공간과 동일한 수의 요소 (이 경우 576)를 갖습니다. 완전한." 그들은 표면이없는 분류기를 명시 적으로 제거하지 않고 AdaBoost를 사용하여 "매우 적은 수의 이러한 기능을 결합하여 효과적인 분류기를 형성 할 수있다"고 결정합니다. 좋습니다. 표면이없는 피처는 즉시 삭제됩니다. 그런데 왜 처음부터 고려할까요?
Paul Lammertsma

글쎄, 그것은 누군가가 실제로 집합 이론으로 추론하는 것처럼 들립니다.
Breton

나는 전체 세트가 모든 가능성을 암시한다는 데 동의합니다. 그러나 x 및 너비 <= x에 대해 1 ~ 24를 취 하면 기능이 서브 프레임 외부로 1 픽셀 확장된다는 점을 고려하십시오!
Paul Lammertsma

코드가 "하나씩"버그로 가득 차 있지 않습니까? 방금 자세히 살펴 보았고 for 루프를 작성하는 재미있는 방법이 있습니다.
Breton

나는 그것을 자격을 갖추어야합니다. 저는 그것을 조금 생각했습니다. 그리고 만약 당신이 1 픽셀 높이, 2 픽셀 높이, 3 픽셀, 높이 24 픽셀까지의 직사각형을 가지고 있다면 당신은 24 종류의 직사각형을 가지고 있습니다. 24 픽셀 높이의 서브 프레임에 맞습니다. 오버행은 무엇입니까?
Breton

2

논문의 저자가 모든 가정과 결과가 정확하다는 보장은 없습니다. 가정 # 4가 타당하다고 생각되면 그 가정을 유지하고 이론을 시도하십시오. 당신은 원저자보다 더 성공할 수 있습니다.


실험 결과 겉보기에는 똑같은 성능을 보입니다. AdaBoost는 첫 번째주기에서 추가 제로 표면 기능을 단순히 삭제한다고 생각하지만 실제로는 이것을 조사하지 않았습니다.
Paul Lammertsma

비올라와 존스는 컴퓨터 비전 분야에서 매우 유명합니다. 사실,이 특정 논문은 중요한 것으로 간주됩니다. 모두가 실수를하지만이 특정 알고리즘은 매우 잘 작동하는 것으로 입증되었습니다.
Dima

1
확실히, 그리고 나는 그들의 방법을 전혀 의심하지 않습니다. 효율적이고 잘 작동합니다! 이론은 건전하지만 감지기가 1 픽셀 짧게 잘못 자르고 불필요한 제로 표면 기능을 포함했을 수 있다고 생각합니다. 그렇지 않다면 180k 기능을 시연하도록 도전합니다!
Paul Lammertsma

사실은 모두가 인간이라는 것입니다. 누구나 실수를합니다. 큰 이름이 실수를 할 때, 사람들은받은 지혜에 의문을 제기하는 것을 두려워하기 때문에 종종 대대로 숨겨져 있습니다. 그러나 진정한 과학은 과학적 방법을 따르며 이름이 아무리 커도 누구에게도 숭배하지 않습니다. 그것이 과학이라면 단순한 필사자가 노력을 기울이고 그것이 어떻게 작동하는지 이해하며 상황에 적응할 수 있습니다.
Michael Dillon

우리는 볼 것입니다; 저자에게 이메일을 보냈습니다.
Paul Lammertsma

1

꽤 좋은 관찰이지만, 24x24 프레임 또는 "오버플로"를 암시 적으로 0으로 채우고 회전 이동에서와 같이 경계를 벗어날 때 첫 번째 픽셀을 사용하기 시작하거나 Breton이 말한대로 일부 기능을 "사소한 기능"으로 간주 할 수 있습니다. AdaBoost로 폐기하십시오.

또한 Python 및 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 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)

5 가지 기능을 사용하는 이유는 주요 질문에 4 개만 게시됩니다. 그러나 어쨌든 파이썬 버전에 감사드립니다.
Kasparov92

0

2001 년 원본 논문에서는 다음과 같은 세 가지 기능 만 사용한다고 언급합니다.

세 가지 기능을 사용합니다.

또한

영역의 크기와 모양이 동일합니다.

각 종류에는 두 가지 방향이 있기 때문에 총 6 개의 기능 (적어도 총 기능 수 계산을 위해)을 사용한다고 가정하는 것이 합리적입니다 : 2 개의 직사각형 기능 2 개, 3 개의 직사각형 기능 2 개 및 4 개의 직사각형 기능 2 개. 이 가정에는 실제로 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

네 개의 직사각형 유형의 특성 (나중에 발표 된 것처럼 보임) 하나를 드롭하면 총 특성 수는 162,336 개입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.