5.23. 원근 보정¶
경고
임의의 3x3 transform 행렬은 OpenMV Cam N6 에서만 지원됩니다 – 다른 모든 보드에서는 이 키워드가 조용히 무시됩니다. 그 외의 곳에서 실행해야 하는 애플리케이션은 정형화된 rotation_corr() 메서드(그리고 그 corners= 형태)를 사용하거나 보정된 이미지를 보드 밖에서 미리 계산해야 합니다.
정형화된 rotation_corr() 메서드는 특정 계열의 원근 워핑을 작은 매개변수 집합 뒤에 묶어 패키징하며, 지원되는 모든 보드에서 실행됩니다. 일부 애플리케이션은 그 형태에 맞지 않는 워핑을 필요로 합니다. 한 사각형에서 다른 사각형으로의 임의의 사영 재매핑, 오프라인에서 이미 산출된 알려진 마운팅에 대한 보정, 또는 어떤 상류 알고리즘이 이미 만들어 넘겨준 워핑 행렬 등이 그렇습니다. 이러한 경우를 위해 draw_image() 은 – copy(), crop(), scale() 과 함께 – 워핑을 직접 기술하는 직접 만든 3x3 행렬을 받는 transform 키워드를 받습니다.
5.23.1. 어파인 및 사영 변환¶
기하 워핑은 동차 좌표(homogeneous coordinates) 로 표현됩니다. 즉 픽셀 위치 (x, y) 에 1 을 덧붙인 것에 3x3 행렬을 곱합니다.
어파인(affine) 형태가 출발점입니다. 그 맨 아랫줄은 \((0, 0, 1)\) 로 고정됩니다:
풀어서 쓰면, 각 출력 좌표는 입력 좌표들의 선형 결합에 상수를 더한 것입니다:
이는 스케일링, 회전, 전단(shearing), 평행이동을 임의로 조합한 것을 모두 포괄하며, 이 모든 변환 하에서 평행선은 평행하게 유지됩니다.
사영(projective) (원근) 형태는 맨 아랫줄을 자유롭게 풉니다:
풀어서 쓰면:
\(w' = g x + h y + 1\) 로 나누는 것이 바로 이 변환을 단순한 어파인이 아니라 사영으로 만드는 요소입니다. \(g\) 와 \(h\) 가 모두 0일 때, \(w'\) 는 1로 유지되고 나눗셈은 아무 작용도 하지 않습니다 – 다시 어파인 형태가 됩니다. 둘 중 하나라도 0이 아니면 \(w'\) 가 입력 위치에 따라 달라지고 서로 다른 위치의 픽셀이 서로 다른 양만큼 단축(foreshorten)되어, 더 이상 평행선이 평행하게 유지되지 않습니다 – 이는 정확히 평평한 평면을 비스듬한 각도에서 바라볼 때의 키스톤 효과입니다. 사영 변환은 직선을 직선으로 보내는 가장 일반적인 기하 워핑입니다. 스케일링, 뒤집기, 전치, 회전, 그리고 네 모서리 회전 보정은 모두 그 특수한 경우입니다.
이름 붙은 변환들은 어파인 형태에서 직접 도출됩니다. 항등 변환은 항등 행렬이며, 또한:
대부분의 직접 만든 변환에서 애플리케이션은 이들 중 하나를 기반으로 시작하여 추가 연산마다 행렬을 더 곱해 나가고, 결국 합성 워핑을 기술하는 단일 3x3 행렬로 끝맺습니다. 행렬은 오른쪽에서 왼쪽으로 적용됩니다. \(M = T R S\) 는 스케일을 먼저 실행한 다음 회전, 그다음 평행이동을 실행합니다. 누구나 결국에는 필요로 하는 합성은 이미지 중심을 기준으로 한 회전입니다 – 단순한 회전 행렬은 좌측 상단 모서리의 픽셀 원점을 중심으로 이미지를 돌리므로, 중심을 맞춘 버전은 중심 \((c_x, c_y)\) 을 원점으로 옮기고, 회전한 다음, 다시 되돌립니다:
5.23.2. transform 키워드¶
행렬은 3x3 ulab.numpy.ndarray 로 공급되어 transform 키워드를 통해 들어갑니다. 사용할 메서드는 draw_image() 으로, 소스를 대상에 그리면서 행렬을 통해 워핑합니다 – 결과는 애플리케이션이 제어하는 버퍼에 들어가며, 워핑은 호출의 다른 모든 것, 즉 스케일링, 알파 블렌딩, 마스킹과 합성됩니다.
import ulab.numpy as np
M = np.array([[1.2, 0.0, -20.0],
[0.0, 1.2, -15.0],
[0.0, 0.0, 1.0]])
canvas.draw_image(img, transform=M)
이 예제는 img 를 각 방향으로 1.2배 스케일링하고 각각 왼쪽으로 20픽셀, 위로 15픽셀 이동시켜 canvas 위에 워핑합니다 – 위에서 설명한 행렬 항목들로부터 직접 만든 어파인 워핑입니다. copy(), crop(), scale() 의 동일한 키워드는 워핑을 이미지 자체에 적용합니다.