런 길이 인코딩의 픽셀 체인
-
20-09-2019 - |
문제
나는 이것에 오랫동안 머리를 두드리고있다
나는 이미징을하고있다. 지금까지 나는 내 이미지를 이진화 시켰습니다. 즉, 회색조 이미지에서 특정 값의 모든 픽셀이 삭제됩니다. 이것은 나에게 해당 지역 주변의 많은 "제로 픽셀"이있는 원본 이미지에서 일부 지역 만 제공합니다.
다음으로 길이가 내 영역을 "블로브"로 인코딩했습니다. 실행은 데이터에 대한 압축 방법입니다. 예를 들어, 정사각형을 이진화했다고 가정하면 전체 이미지를 설명하는 몇 가지만 실행할 수 있습니다. 런은 x, y 좌표 및 길이로 정의됩니다.
이미지를 재현 할 때 각 실행마다 X, Y 좌표로 이동하여 X 축에 픽셀을 추가하여 달리기 길이를 추가하십시오.
이제 나는 달리기를하고 지역의 윤곽을 설명 할 체인을 만들어야합니다. 어떻게 해야할지 모르겠습니다.
나는 x, y, 길이가 달리는 덩어리가 있고 가장자리 주위에 "탐색"해야합니다. 체인. 일반적으로 이미징 에서이 프로세스는 원본 이미지로 수행되지만 더 이상 원본 이미지를 여기서 사용할 수 없으므로 실행 중에 계산해야합니다.
나는 이것이 큰 텍스트 벽처럼 보이지만이 질문을 더 잘 물어야 할 방법을 모르겠습니다.
동일한 구현에 대한 힌트 나 포인터는 굉장합니다.
편집하다
풀기 덕분에 몇 가지 이미지를 링크 할 수 있습니다.
(원천: 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;
}
}
}
이것은 달리기를 반복하고, 왼쪽 및 오른쪽 끝점을 점프하는 방향으로 테스트하고, 적절한 수의 체인 요소를 두 개의 벡터에 추가하여, 하나는 순서대로, 오른쪽, 반전 순서를 추가함으로써 작동합니다. , 왼쪽. 그런 다음 마지막 스캔 라인에 적절한 수의 링크를 추가하여 두 체인을 연결 한 다음 왼쪽 체인을 뒤집어 오른쪽 체인에 추가하여 최종 체인을 생성합니다.
이것이 당신이 찾고있는 것이기를 바랍니다!