문제

나는 적응을 구현했다 Viola-Jones의 얼굴 감지 알고리즘. 이 기술은 이미지 내에 24x24 픽셀의 서브 프레임을 배치 한 다음 모든 크기가 가능한 모든 위치에 직사각형 기능을 배치 할 때 의존합니다.

이 기능은 2, 3 또는 4 개의 직사각형으로 구성 될 수 있습니다. 다음 예제가 제시됩니다.

Rectangle features

그들은 철저한 세트가 180k 이상이라고 주장합니다 (섹션 2).

검출기의 기본 해상도가 24x24라는 점을 감안할 때, 전적으로 사각형 특징의 철저한 세트는 180,000을 초과합니다. HAAR 기준과 달리 직사각형 기능 세트는 지나치게 다릅니다.

다음 진술은 논문에 명시 적으로 언급되어 있지 않으므로 내 입장에 대한 가정입니다.

  1. 2 개의 2 개의 rectangle 기능, 2 개의 3 개 조정 기능 및 1 개의 4 개의 고정 기능 만 있습니다. 이것의 논리는 우리가 관찰하고 있다는 것입니다. 차이점 강조 표시된 직사각형 사이에, 색상이나 휘도 또는 그런 종류의 어떤 것도 명시 적으로.
  2. 피처 타입 A를 1x1 픽셀 블록으로 정의 할 수 없습니다. 적어도 1x2 픽셀이어야합니다. 또한 D 형은 최소 2x2 픽셀이어야 하며이 규칙은 다른 기능에 따라 유지됩니다.
  3. 중간 픽셀을 분할 할 수 없으므로 피처 타입 A를 1x3 픽셀 블록으로 정의 할 수 없으며, 그 자체에서 빼면 1x2 픽셀 블록과 동일합니다. 이 기능 유형은 너비에 대해서만 정의됩니다. 또한 기능 유형 C의 너비는 3으로 나눌 수 있어야 하며이 규칙은 다른 기능에 따라 유지됩니다.
  4. 너비 및/또는 높이가 0 인 기능을 정의 할 수 없습니다. 엑스 그리고 와이 기능 크기의 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.

내가 "180,000 명 이상"비올라와 존스가 말하는 유일한 방법은 가정 #4를 삭제하고 코드에 버그를 도입하는 것입니다. 여기에는 각각 4 줄을 변경하는 것이 포함됩니다.

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

결과는 그렇습니다 180,625. (이것은 기능이 서브 프레임의 오른쪽 및/또는 하단에 영향을 미치는 것을 효과적으로 방지합니다.)

물론 질문 : 그들은 구현에서 실수를 했습니까? 표면이 0 인 기능을 고려하는 것이 합리적입니까? 아니면 내가 잘못된 길을보고 있습니까?

도움이 되었습니까?

해결책

면밀히 살펴보면 코드가 올바르게 보입니다. 원래 저자가 나오지 않은 버그를 가지고 있는지 궁금해합니다. 나는 누군가가 OpenCV가 그것을 어떻게 구현하는지 봐야한다고 생각합니다!

그럼에도 불구하고 이해하기 쉽게하는 한 가지 제안은 ~을 위한 먼저 모든 크기를 넘어서 고리 한 다음 크기가 주어진 가능한 위치를 반복합니다.

#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

다른 팁

모두. 비올라와 존스의 논문에는 여전히 약간의 혼란이 있습니다.

그들의 CVPR'01 논문에서 그것은 분명히 언급되어 있습니다

"보다 구체적으로, 우리는 사용합니다 종류의 기능. a의 가치 2 개의 교정 기능 두 직사각형 영역 내에서 픽셀의 합 사이의 차이입니다. 영역은 크기와 모양이 동일하며 수평 또는 수직으로 인접합니다 (그림 1 참조). 3 개의 rectangle 기능 중앙 사각형의 합계에서 빼낸 두 개의 외부 사각형 내에서 합계를 계산합니다. 드디어 4 개의 rectangle 기능".

IJCV'04 종이에서 정확히 같은 말이 있습니다. 4 가지 기능이 있습니다. 그러나 이상하게도, 그들은 이번에는 철저한 기능 세트가 45396이라고 말했습니다! 이는 최종 버전이 아닌 것 같습니다. Min_Width, Min_Height, 너비/높이 비율 및 위치와 같은 일부 추가 제약 조건이 도입되었다고 생각합니다.

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

종이 전체를 읽지 않았다.

검출기의 기본 해상도가 24x24라는 점을 감안할 때, 전적으로 사각형 특징의 철저한 세트는 180,000을 초과합니다. HAAR 기준과 달리 직사각형 기능 세트는 지나치게 다릅니다.

"직사각형 기능 세트는 지나치게 다가옵니다" "철저한 세트"

예를 들어, 제지기 작가가 예를 들어, 제로가있는 사각형과 같은 사소한 사례를 제거함으로써 검색 공간을보다 효과적인 세트로 끌어 올리는 방법에 대한 설명을 추적 할 것으로 기대하는 세트 업처럼 들립니다. 표면적.

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

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

아주 좋은 관찰이지만, 24x24 프레임 또는 "오버플로"를 암시 적으로 제로 패드 할 수 있으며, 회전 교대 또는 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)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top