5.2. 좌표와 영역

이미지 처리는 픽셀에 대해 동작하며, 어떤 픽셀에 대해 동작하려면 알고리즘이 그 픽셀을 좌표로 지정할 수 있어야 합니다. 픽셀로 이루어진 사각형에 대해 동작하는 경우도 마찬가지입니다 – 그 사각형은 알고리즘과 애플리케이션 코드가 서로 합의한 방식으로 기술되어야 합니다. image 모듈이 좌표와 사각형에 사용하는 규칙은 간단하지만, 수학적 관례에 익숙한 독자들이 컴퓨터 그래픽스 관례 대신 혼동하기 쉬운 한 가지 세부 사항이 있으며, 이는 처음부터 명확히 짚고 넘어갈 가치가 있습니다.

5.2.1. 픽셀 격자

픽셀 (0, 0) 은 이미지의 왼쪽 위 모서리입니다. x축은 오른쪽으로 진행하므로 x가 클수록 더 오른쪽을 의미합니다. y축은 아래쪽으로 진행하므로 y가 클수록 이미지에서 더 아래쪽을 의미합니다. 너비 곱하기 높이 크기의 이미지는 (0, 0) 부터 (width - 1, height - 1) 까지의 정수 좌표에 픽셀을 담습니다. (width, 0) 이나 (0, height) 위치에는 픽셀이 없습니다 – 이 위치들은 오른쪽과 아래쪽 에지로, 각 방향에서 마지막 실제 픽셀을 한 칸 지난 지점입니다.

아래쪽으로 향하는 y축이 위에서 언급한 세부 사항입니다. 모눈종이 기하학에 익숙한 독자는 y가 클수록 더 위쪽을 의미할 것이라고 예상하지만, 여기서는 그 직관이 정확히 반대입니다. 이렇게 반전된 이유는 디지털 센서와 디지털 디스플레이가 모두 왼쪽 위에서 시작하여 각 행을 오른쪽으로 훑으며 위에서 아래로 진행하기 때문입니다. 그리고 픽셀을 메모리에 동일한 순서로 배치하면 “버퍼의 위치 i “와 “이미지의 행 r , 열 c “ 사이의 관계를 가능한 한 단순한 산술로 만들 수 있습니다 – 픽셀 (x, y) 의 위치 i 는 그저 y * width + x 입니다. 모든 이미징 라이브러리가 수십 년 전에 같은 이유로 이 배치 방식에 합의했으며, 그 대가는 이미지를 처음 다룰 때 약간의 사고 조정 하나뿐입니다.

이미지를 나타내는 사각형. 왼쪽 위 모서리의 표식에는 (0, 0) 이라고 표시되어 있습니다. 위쪽 에지를 따라 오른쪽을 가리키는 화살표에는 x, 왼쪽 에지를 따라 아래쪽을 가리키는 화살표에는 y라고 표시되어 있습니다. 안쪽에 그려진 더 작은 사각형에는 ROI라고 표시되어 있으며, 그 왼쪽 위 모서리는 (x, y) 에 있고 가로세로 크기는 에지를 따라 w와 h로 표시되어 있습니다.

이미지 좌표계: 원점은 왼쪽 위, x는 오른쪽으로, y는 아래쪽으로 진행합니다. 이미지 내부의 사각형 영역은 왼쪽 위 모서리 (x, y) 와 그 크기 (w, h) 로 지정됩니다.

5.2.2. 사각형

이미지에 대한 대부분의 연산은 단일 픽셀보다 픽셀로 이루어진 사각형에 관심을 둡니다 – 살펴볼 영역, 복사해 낼 영역, 통계를 계산할 프레임 안의 프레임 등입니다. 사각형을 지정하는 형식은 단일 픽셀 규칙을 가능한 한 단순하게 확장한 것을 택합니다: 왼쪽 위 모서리의 좌표를 주고, 그 뒤에 사각형의 크기를 주어 네 개짜리 튜플 (x, y, w, h) 로 묶습니다. 사각형 내부의 픽셀들은 열 x 부터 x + w - 1 까지, 행 y 부터 y + h - 1 까지에 있습니다.

여기서 명확히 짚어 둘 만한 세부 사항은 wh 가 오른쪽 아래 좌표가 아니라 크기라는 점입니다. 사각형 (10, 20, 4, 3) 은 열 10, 11, 12, 13 과 행 20, 21, 22 – 총 열두 개의 픽셀 – 을 덮으며, (10, 20) 에서 (4, 3) 까지 이어지는 영역이 아닙니다. 이 규칙은 모듈 전체에서 일관되므로 한 번 체득하고 나면 실수가 사라지지만, 처음에는 사람들이 혼동하곤 합니다.

(x, y, w, h) 형식은 서로 달라 보이지만 같은 규칙을 공유하는 세 곳에서 등장합니다. 첫 번째는 이미지가 자기 자신의 영역을 기술할 때입니다: 이미지 전체를 덮는 사각형은 (0, 0, width, height) 입니다. 두 번째는 검출 메서드가 경계 상자를 가진 결과 – blob , rect , apriltag – 를 반환할 때이며, 이 상자는 (x, y, w, h) 로 보고됩니다. 세 번째는 메서드에게 프레임 전체가 아니라 이미지의 하위 영역에 대해 동작하도록 지시해야 할 때입니다. 연산의 범위를 한정하는 roi 키워드 인수도 같은 네 개짜리 튜플을 받습니다.

한 메서드에서 경계 상자를 받아 다음 메서드의 roi 에 넣는 것은 이미지 처리에서 가장 흔한 패턴 중 하나입니다. 거친 1차 검출의 경계 상자는 더 정밀한 2차 검출의 탐색 영역을 좁혀 주며, 검출 결과와 메서드 인수 전반에 걸친 통일된 어휘 덕분에 그 패턴이 이토록 간단해집니다 – 하나의 튜플 형식이 인계의 양쪽에서 동일하게 사용됩니다.

5.2.3. 정수 주소, 소수 무게중심

픽셀 주소 자체는 정수입니다. 주어진 정수 열과 행에 픽셀이 있거나 없거나 둘 중 하나이며, 좌표 (40.5, 30.7) 에 무엇이 있는지 묻는 것은 올바르게 정의된 질문이 아닙니다 – 정확히 그 위치에 자리한 픽셀은 없습니다. 하지만 image 모듈이 픽셀 위치로부터 유도하는 몇몇 값은 소수이며, 이 구분이 나중에 애플리케이션을 곤란하게 하지 않도록 그 이유를 이해해 둘 가치가 있습니다.

가장 흔한 경우는 무게중심 – 영역의 질량 중심입니다. 픽셀로 연결된 영역의 경우, 부동소수점 형태의 무게중심은 구성 픽셀들의 위치를 그 밀도로 가중 평균한 값입니다. 픽셀이 두 열에 걸쳐 있는 영역은 예를 들어 무게중심 x가 41.6 이 될 수 있습니다 – 정확히 그 x에 실제 픽셀이 없더라도 눈으로 보면 “그 영역의 한가운데”라고 표현할 만한 실제 위치입니다. 검출 결과 객체는 두 형태를 모두 읽기 전용 속성으로 가집니다: 정수 쌍( cx / cy , 위치를 정수 픽셀 좌표를 원하는 곳에 다시 넣을 때 유용)과 부동소수점 쌍( cxf / cyf , 위치가 서브픽셀 해상도의 이점을 누리는 제어 루프로 들어갈 때 유용)입니다.

또 다른 경우는 주파수 영역에서 측정한 두 프레임 사이의 변위입니다. 이미지의 픽셀을 직접 다루는 대신 스펙트럼 내용을 분석하는 기법은 1픽셀보다 미세한 이동을 분해할 수 있으며, 그러한 이동을 부동소수점 (dx, dy) 값으로 보고합니다.

경험칙: 픽셀 주소는 정수이고, 알고리즘에서 나오는 위치와 이동은 부동소수점일 수 있습니다. 그리기 메서드는 두 형태를 모두 받아들이며, 결과가 격자 위에 놓여야 할 때는 부동소수점을 가장 가까운 정수 픽셀로 내림합니다.

5.2.4. 직교좌표와 극좌표

지금까지 설명한 체계는 직교좌표입니다: 모든 픽셀은 원점으로부터의 수평 오프셋과 수직 오프셋으로 지정됩니다. 이것이 바이트가 저장되는 체계이며 – 버퍼의 픽셀 i 는 열 i % width , 행 i // width 의 픽셀에 대응하고, 행을 위에서부터 훑습니다 – 모든 메서드가 기본적으로 동작하는 체계이기도 합니다.

두 번째 표현 방식도 알아 둘 가치가 있는데, 일부 알고리즘이 그 안에서 훨씬 잘 동작하기 때문입니다. 극좌표는 각 픽셀을 선택한 중심점으로부터의 거리와 그 픽셀과 기준 방향 사이의 각도로 지정합니다. 이미지의 픽셀들이 움직인 것은 아닙니다 – 바이트는 여전히 같은 행 우선 버퍼에 그대로 있습니다 – 다만 주소 지정 방식이 “얼마나 오른쪽이고 얼마나 아래쪽인가”에서 “중심에서 얼마나 멀고 그 주위로 어떤 각도인가”로 바뀌었을 뿐입니다.

두 개의 사각형이 나란히 있고, 각각 같은 이미지를 나타냅니다. 왼쪽 것은 직교좌표를 보여줍니다 -- 왼쪽 위 원점, x축과 y축, 좌표 (x, y) 에 있는 샘플 점 P. 오른쪽 것은 극좌표를 보여줍니다 -- 사각형 안의 중심 표식 C, C에서 같은 점 P로 이어지며 r(거리)로 표시된 선, 그리고 theta(각도)로 표시된 호.

같은 점 P를 두 가지 방식으로 지정: 왼쪽 위 원점에서의 직교좌표 (x, y) , 선택한 중심에서의 극좌표 (r, theta) .

왜 굳이 바꿔야 할까요? 어려운 탐색을 쉬운 탐색으로 바꿔 주는 두 가지 항등식 때문입니다.

극좌표에서는 선택한 중심을 기준으로 이미지를 회전시키는 것이 픽셀을 각도 축 – 재투영된 이미지에서의 x 방향 – 을 따라 평행이동시키는 것과 동일한 연산입니다. 회전된 사본은 원본을 극좌표 형태에서 왼쪽 또는 오른쪽으로 이동시킨 것입니다.

로그-극좌표 변형 – 거리 축은 로그 스케일을 사용하고 각도 축은 선형을 유지 – 에서는 선택한 중심을 기준으로 이미지를 확대/축소하는 것이 픽셀을 거리 축 – y 방향 – 을 따라 평행이동시키는 것과 동일한 연산입니다. 확대/축소된 사본은 원본을 로그-극좌표 형태에서 위 또는 아래로 이동시킨 것입니다.

따라서 회전이나 확대/축소 하에서 알려진 패턴을 인식해야 하는 알고리즘은 극좌표 공간에서 탐색을 수행할 수 있으며, 그곳에서는 두 변환이 모두 평범한 평행이동으로 바뀝니다. 평행이동은 회전이나 확대/축소보다 탐색 비용이 훨씬 적게 들며, 극좌표 재투영이 바로 이 대체를 가능하게 합니다.

극좌표는 픽셀을 저장할 때 직교좌표를 대체하지 않습니다. 바이트는 항상 직교좌표 격자 위에 존재합니다. 모듈은 필요할 때 이미지를 직교좌표에서 극좌표 형태로 재투영하는 한 쌍의 메서드를 제공하며, 극좌표가 필요한 알고리즘이 작업을 수행한 뒤, 그 결과를 다시 투영해 내보내거나 극좌표 공간의 측정값을 직접 사용합니다. 이 메커니즘이 모듈 표면 어디에서든 극좌표가 등장하는 유일한 이유입니다.

개별 픽셀을 지정하는 직교좌표, 그 픽셀들의 사각형을 지정하는 (x, y, w, h) 네 개짜리 튜플, 그리고 알고리즘이 이점을 누릴 때 사용할 수 있는 극좌표를 통해, 애플리케이션은 이미지에서 무언가가 어디에 있는지를 지정하는 완전한 어휘를 갖추게 됩니다. 그 위치들 중 어느 곳에 실제로 무엇이 저장되는지가 이 토대의 다음 계층입니다.