더북(TheBook)
소스 11-11 해리스 코너 검출 구현 함수(IppFeature.cpp)
void IppHarrisCorner(IppByteImage& img, std::vector<IppPoint>& corners, double th)
{
    register int i, j, x, y;

    int w = img.GetWidth();
    int h = img.GetHeight();

    BYTE** ptr = img.GetPixels2D();

    //-------------------------------------------------------------------------
    // 1. (fx)*(fx), (fx)*(fy), (fy)*(fy) 계산
    //-------------------------------------------------------------------------

    IppFloatImage imgDx2(w, h);
    IppFloatImage imgDy2(w, h);
    IppFloatImage imgDxy(w, h);

    float** dx2 = imgDx2.GetPixels2D();
    float** dy2 = imgDy2.GetPixels2D();
    float** dxy = imgDxy.GetPixels2D();

    float tx, ty;
    for (j = 1; j < h - 1; j++)
    for (i = 1; i < w - 1; i++)
    {
        tx = (ptr[j - 1][i + 1] + ptr[j][i + 1] + ptr[j + 1][i + 1]
            - ptr[j - 1][i - 1] - ptr[j][i - 1] - ptr[j + 1][i - 1]) / 6.f;
        ty = (ptr[j + 1][i - 1] + ptr[j + 1][i] + ptr[j + 1][i + 1]
            - ptr[j - 1][i - 1] - ptr[j - 1][i] - ptr[j - 1][i + 1]) / 6.f;

        dx2[j][i] = tx * tx;
        dy2[j][i] = ty * ty;
        dxy[j][i] = tx * ty;
    }

    //-------------------------------------------------------------------------
    // 2. 가우시안 필터링
    //-------------------------------------------------------------------------

    IppFloatImage imgGdx2(w, h);
    IppFloatImage imgGdy2(w, h);
    IppFloatImage imgGdxy(w, h);

    float** gdx2 = imgGdx2.GetPixels2D();
    float** gdy2 = imgGdy2.GetPixels2D();
    float** gdxy = imgGdxy.GetPixels2D();

    float g[5][5] = { { 1, 4, 6, 4, 1 },{ 4, 16, 24, 16, 4 },
    { 6, 24, 36, 24, 6 },{ 4, 16, 24, 16, 4 },{ 1, 4, 6, 4, 1 } };

    for (y = 0; y < 5; y++)
    for (x = 0; x < 5; x++)
    {
        g[y][x] /= 256.f;
    }

    float tx2, ty2, txy;
    for (j = 2; j < h - 2; j++)
    for (i = 2; i < w - 2; i++)
    {
        tx2 = ty2 = txy = 0;
        for (y = 0; y < 5; y++)
        for (x = 0; x < 5; x++)
        {
            tx2 += (dx2[j + y - 2][i + x - 2] * g[y][x]);
            ty2 += (dy2[j + y - 2][i + x - 2] * g[y][x]);
            txy += (dxy[j + y - 2][i + x - 2] * g[y][x]);
        }

        gdx2[j][i] = tx2;
        gdy2[j][i] = ty2;
        gdxy[j][i] = txy;
    }

    //-------------------------------------------------------------------------
    // 3. 코너 응답 함수 생성
    //-------------------------------------------------------------------------

    IppFloatImage imgCrf(w, h);
    float** crf = imgCrf.GetPixels2D();

    float k = 0.04f;
    for (j = 2; j < h - 2; j++)
    for (i = 2; i < w - 2; i++)
    {
        crf[j][i] = (gdx2[j][i] * gdy2[j][i] - gdxy[j][i] * gdxy[j][i])
            - k*(gdx2[j][i] + gdy2[j][i])*(gdx2[j][i] + gdy2[j][i]);
    }

    //-------------------------------------------------------------------------
    // 4. 임계값보다 큰 국지적 최댓값을 찾아 코너 포인트로 결정
    //-------------------------------------------------------------------------

    corners.clear();
    float cvf_value;

    for (j = 2; j < h - 2; j++)
    for (i = 2; i < w - 2; i++)
    {
        cvf_value = crf[j][i];
        if (cvf_value > th)
        {
            if (cvf_value > crf[j - 1][i] && cvf_value > crf[j - 1][i + 1] &&
                cvf_value > crf[j][i + 1] && cvf_value > crf[j + 1][i + 1] &&
                cvf_value > crf[j + 1][i] && cvf_value > crf[j + 1][i - 1] &&
                cvf_value > crf[j][i - 1] && cvf_value > crf[j - 1][i - 1])
            {
                corners.push_back(IppPoint(i, j));
            }
        }
    }
}
신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.