14장. 영상 기하학 변환과 Affine, Perspective
변환 고르기와 잃는 정보
여행 가방을 쌀 때 옷을 접고, 말고, 눌러 담습니다. 접은 옷은 펴면 그대로지만, 진공 팩으로 세게 누른 옷은 펴도 주름이 남습니다. 기하학 변환도 되돌리면 그대로인 것과, 되돌려도 흔적이 남는 것이 있습니다. 뒤집기와 90도 돌리기는 접은 옷, 줄이기와 비스듬한 회전은 눌러 담은 옷입니다.
그림의 네 상자는 하고 싶은 일에 따라 고르는 함수입니다. 칸 수만 바꾸면 resize, 직각으로만 돌리거나 뒤집으면 flip·rotate, 평행한 선을 지키며 옮기고 돌리고 기울이면 warpAffine, 비스듬한 면을 펴면 warpPerspective 입니다.
왼쪽은 원본, 가운데는 4분의 1로 줄였다가 다시 키운 결과, 오른쪽은 30도 돌렸다가 −30도로 되돌린 결과입니다. 줄였다 키우면 글자와 모눈선이 흐려지고, 돌렸다 되돌리면 잘려 나갔던 네 모서리가 검게 비어 돌아옵니다. 여기서 진공 팩으로 누른 옷의 주름이 흐려짐과 빈 곳입니다.
고르는 기준
| 하고 싶은 일 | 고를 함수 | 정해 줄 것 | 잃는 것 |
|---|---|---|---|
| 크기만 바꾸기 | cv2.resize | 새 크기, 보간법 | 줄이면 잔무늬 |
| 정해진 크기로 맞추기 | 가운데 자르기, 레터박스 | 자를 곳, 여백 색 | 가장자리 또는 칸 수 |
| 뒤집기, 직각 회전 | cv2.flip, cv2.rotate | 방향 | 없음 |
| 옮기기, 비스듬한 회전, 기울이기 | cv2.warpAffine | 2×3 표 (또는 세 쌍의 점) | 잘린 모서리, 보간의 흐려짐 |
| 비스듬한 면 펴기 | cv2.warpPerspective | 3×3 표 (네 쌍의 점) | 먼 쪽을 늘린 만큼 흐려짐 |
짧은 예시
import cv2
img = cv2.imread("ch14_grid.png")
h, w = img.shape[:2]
# 뒤집기를 두 번 하면 원본과 숫자가 모두 같다(잃는 것 없음)
twice = cv2.flip(cv2.flip(img, 1), 1)
print(float(cv2.absdiff(img, twice).mean())) # 결과: 0.0
# 4분의 1로 줄였다가 다시 키우면 원본과 달라진다
small = cv2.resize(img, (w // 4, h // 4), interpolation=cv2.INTER_AREA)
back = cv2.resize(small, (w, h), interpolation=cv2.INTER_LINEAR)
print(round(float(cv2.absdiff(img, back).mean()), 2)) # 결과: 9.48cv2.absdiff(...).mean() 은 6장에서 본 평균 절대 차이(MAE)입니다. 0 이면 원본과 같고, 클수록 많이 달라졌다는 뜻입니다.
주의할 점
- 변환을 여러 번 이어 걸어야 하면, 표를 미리 합쳐 한 번에 걸거나 순서를 줄입니다. 걸 때마다 보간이 일어나 조금씩 흐려집니다.
- 원본 사진은 따로 보관하고, 변환한 사진은 다른 이름으로 저장합니다. 줄인 사진에서 큰 사진을 되살릴 수는 없습니다.