문제

나는 이것에 오랫동안 머리를 두드리고있다

나는 이미징을하고있다. 지금까지 나는 내 이미지를 이진화 시켰습니다. 즉, 회색조 이미지에서 특정 값의 모든 픽셀이 삭제됩니다. 이것은 나에게 해당 지역 주변의 많은 "제로 픽셀"이있는 원본 이미지에서 일부 지역 만 제공합니다.

다음으로 길이가 내 영역을 "블로브"로 인코딩했습니다. 실행은 데이터에 대한 압축 방법입니다. 예를 들어, 정사각형을 이진화했다고 가정하면 전체 이미지를 설명하는 몇 가지만 실행할 수 있습니다. 런은 x, y 좌표 및 길이로 정의됩니다.

이미지를 재현 할 때 각 실행마다 X, Y 좌표로 이동하여 X 축에 픽셀을 추가하여 달리기 길이를 추가하십시오.

이제 나는 달리기를하고 지역의 윤곽을 설명 할 체인을 만들어야합니다. 어떻게 해야할지 모르겠습니다.

나는 x, y, 길이가 달리는 덩어리가 있고 가장자리 주위에 "탐색"해야합니다. 체인. 일반적으로 이미징 에서이 프로세스는 원본 이미지로 수행되지만 더 이상 원본 이미지를 여기서 사용할 수 없으므로 실행 중에 계산해야합니다.

나는 이것이 큰 텍스트 벽처럼 보이지만이 질문을 더 잘 물어야 할 방법을 모르겠습니다.

동일한 구현에 대한 힌트 나 포인터는 굉장합니다.

편집하다

풀기 덕분에 몇 가지 이미지를 링크 할 수 있습니다.

alt text
(원천: tudelft.nl)

이 예에서는 이미지 B를 윤곽 C (체인이라고 부르는)로 처리합니다. 그러나 D, 실행 길이에서 윤곽을 생성하고 싶습니다.

도움이 되었습니까?

해결책 3

글쎄, 나는 그 계약을 잃었지만 그 대답은 프리먼 체인 코딩 기술

그것이 실행 길이 인코딩이라는 사실은 이전에 생각한 것과는 달리 알고리즘과 관련이 없습니다.

다른 팁

언뜻보기에는 실용적인 알고리즘이 보이지 않습니다. 가난한 사람의 해결책이 될 것입니다 확장하다 길이의 원본 이미지는 인코딩 된 이미지입니다. 따라서 라인이 다음과 같이 보이는 경우 :

A 3B 10A C 8D
C 4D 3A 6C 9A

여기서 문자는 실제 픽셀 값을 반환합니다 (예 : a = 0, b = 127, ...). 픽셀 값을 2 차원 배열 (또는 선택한 다른 데이터)에 쓸 수 있습니다.

ABBBAAAAAAAAAACDDDDDDDD
CDDDDAAACCCCCCAAAAAAAAA

그 후 체인을 생성하고 배열을 삭제하고 체인 정보를 유지하십시오. 물론 이것은 비싸다 아마도 원본 그림을 길이로 인코딩하기 전에이 작업을 수행 할 수 있습니다.

다음은 완벽하게 간단하고 실용적인 솔루션 (C ++)입니다.

#include <iostream>
#include <vector>

struct Run { int x, w; };
enum { EAST, NORTHEAST, NORTH, NORTHWEST, WEST, SOUTHWEST, SOUTH, SOUTHEAST };

int main() {

    const Run data[] = {
        { 7, 2 },
        { 5, 6 },
        { 5, 7 },
        { 5, 7 },
        { 6, 6 },
        { 0, 12 },
        { 0, 12 },
        { 0, 11 },
        { 1, 7 },
        { 3, 4 },
        { 3, 4 },
        { 3, 5 },
        { 3, 7 },
        { 3, 7 },
        { 5, 5 }
    };

    std::vector<Run> runs(data, data + 15);
    std::vector<int> before;
    std::vector<int> after;
    unsigned int i;
    int j;

    for (i = 0; i < runs.size() - 1; ++i) {

        if (runs[i].x < runs[i + 1].x) {

            for (j = 0; j < runs[i + 1].x - runs[i].x - 1; ++j)
                before.push_back(WEST);
            before.push_back(NORTHWEST);

        } else if (runs[i].x > runs[i + 1].x) {

            before.push_back(NORTHEAST);
            for (j = 0; j < runs[i].x - runs[i + 1].x - 1; ++j)
                before.push_back(EAST);

        } else {

            before.push_back(NORTH);

        }

        int first_right(runs[i].x + runs[i].w);
        int second_right(runs[i + 1].x + runs[i + 1].w);

        if (first_right < second_right) {

            after.push_back(SOUTHEAST);
            for (j = 0; j < second_right - first_right - 1; ++j)
                after.push_back(EAST);

        } else if (first_right > second_right) {

            for (j = 0; j < first_right - second_right - 1; ++j)
                after.push_back(WEST);
            after.push_back(SOUTHWEST);

        } else {

            after.push_back(SOUTH);

        }

    }

    for (j = 0; j < runs.back().w - 1; ++j)
        after.push_back(WEST);

    std::reverse(before.begin(), before.end());
    after.insert(after.end(), before.begin(), before.end());

    for (j = 0; j < int(after.size()); ++j) {
        switch (after[j]) {
        case EAST:      std::cout << "EAST\n";      break;
        case NORTHEAST: std::cout << "NORTHEAST\n"; break;
        case NORTH:     std::cout << "NORTH\n";     break;
        case NORTHWEST: std::cout << "NORTHWEST\n"; break;
        case WEST:      std::cout << "WEST\n";      break;
        case SOUTHWEST: std::cout << "SOUTHWEST\n"; break;
        case SOUTH:     std::cout << "SOUTH\n";     break;
        case SOUTHEAST: std::cout << "SOUTHEAST\n"; break;
        }
    }

}

이것은 달리기를 반복하고, 왼쪽 및 오른쪽 끝점을 점프하는 방향으로 테스트하고, 적절한 수의 체인 요소를 두 개의 벡터에 추가하여, 하나는 순서대로, 오른쪽, 반전 순서를 추가함으로써 작동합니다. , 왼쪽. 그런 다음 마지막 스캔 라인에 적절한 수의 링크를 추가하여 두 체인을 연결 한 다음 왼쪽 체인을 뒤집어 오른쪽 체인에 추가하여 최종 체인을 생성합니다.

이것이 당신이 찾고있는 것이기를 바랍니다!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top