OpenCV 비전 실무14장 · 영상 기하학 변환과 Affine, Perspective5 / 21← 이전목차다음 →MetaContents

14장. 영상 기하학 변환과 Affine, Perspective

보간법

모자이크 타일 벽을 두 배로 넓힌다고 해 봅시다. 원래 타일 사이에 새 타일을 끼워야 하는데, 무슨 색으로 할까요? 옆 타일 색을 그대로 쓰면 빠르지만 경계가 계단처럼 보입니다. 양옆 색을 섞어 중간색을 쓰면 부드럽습니다. 크기를 바꿀 때 새로 생긴 칸의 값을 정하는 방법이 보간법입니다.

밝기 100 과 200 인 두 칸을 네 칸으로 키울 때 최근접 이웃과 양선형 보간이 채운 값을 견준 그림

밝기 100 과 200 인 두 칸을 네 칸으로 키운 결과입니다. 최근접 이웃(INTER_NEAREST)은 가까운 칸의 값을 그대로 가져와 100, 100, 200, 200 이 됩니다. 양선형 보간(INTER_LINEAR)은 사이를 고르게 나눠 100, 125, 175, 200 이 됩니다. 여기서 옆 타일 색을 그대로 쓰는 것이 최근접 이웃, 양옆 색을 섞는 것이 양선형 보간입니다.

양선형 보간을 손으로 계산하기

새 칸 하나가 원래 두 칸 사이의 어디에 놓이는지 보고, 가까운 쪽에 더 큰 무게를 줍니다. 위 그림의 둘째 칸은 100 쪽에서 4분의 1, 200 쪽에서 4분의 3 떨어진 자리입니다.

새 칸100 에 주는 무게200 에 주는 무게계산값
둘째 칸0.750.25100 × 0.75 + 200 × 0.25125
셋째 칸0.250.75100 × 0.25 + 200 × 0.75175

무게 둘을 더하면 늘 1 입니다. 가까운 쪽 값을 더 많이 섞는 가중 평균입니다. 그림은 가로와 세로가 있으므로, 가로로 한 번 섞고 세로로 한 번 더 섞습니다. 그래서 "양(兩, 둘)선형"입니다.

작은 아이콘을 8배로 키운 세 가지 결과와 동심원 무늬를 4분의 1로 줄인 두 가지 결과를 견준 그림

위 줄은 32×24 아이콘을 8배로 키운 결과입니다. 최근접 이웃은 네모 계단이 그대로 커지고, 양선형과 바이큐빅은 경계가 부드럽게 번집니다. 아래 줄은 촘촘한 동심원 무늬를 4분의 1로 줄인 결과입니다. 최근접 이웃은 칸을 띄엄띄엄 골라 원래 없던 굵은 물결무늬가 생겼고(계단 현상), 넓이 평균(INTER_AREA)은 검고 흰 고리를 평균 내어 고른 회색이 되었습니다. 6장에서 "크기 줄이기 전에 블러로 들쭉날쭉한 무늬를 막는다"고 한 것이 이 무늬입니다. INTER_AREA 는 줄이면서 평균을 내므로 블러를 따로 걸지 않아도 됩니다.

보간법 고르기

최근접 이웃, 양선형, 바이큐빅, 넓이 평균의 네 보간법을 쓰는 곳과 함께 견준 비교 그림

그림의 네 상자는 OpenCV 의 대표 보간법 네 가지입니다. 줄일 때는 넓이 평균, 키울 때는 양선형이나 바이큐빅을 고르는 것이 보통입니다.

상수이름채우는 법속도알맞은 곳
cv2.INTER_NEAREST최근접 이웃가장 가까운 칸 하나를 복사가장 빠름정답 마스크, 라벨 그림(값이 바뀌면 안 될 때)
cv2.INTER_LINEAR양선형둘레 4칸을 무게대로 섞음빠름키우기, cv2.resize 의 기본값
cv2.INTER_CUBIC바이큐빅둘레 16칸으로 매끈한 곡선느림키우기(더 또렷하게)
cv2.INTER_AREA넓이 평균덮는 칸들의 평균보통줄이기

짧은 예시

Python
import cv2
import numpy as np

# 밝기 100 과 200 인 두 칸짜리 그림(세로 1, 가로 2)
pair = np.array([[100, 200]], dtype=np.uint8)

# 가로 4칸, 세로 1칸으로 키운다. 방법마다 새 칸을 다르게 채운다
for name, flag in [("NEAREST", cv2.INTER_NEAREST), ("LINEAR", cv2.INTER_LINEAR),
                   ("CUBIC", cv2.INTER_CUBIC)]:
    big = cv2.resize(pair, (4, 1), interpolation=flag)
    print(name, [int(v) for v in big[0]])
# 결과: NEAREST [100, 100, 200, 200]
#       LINEAR [100, 125, 175, 200]
#       CUBIC [89, 123, 177, 211]

바이큐빅은 89 와 211 처럼 원래 범위(100~200)를 조금 넘는 값을 만듭니다. 매끈한 곡선이 경계에서 살짝 넘쳤다 돌아오기 때문입니다. 경계가 더 또렷해 보이는 대신, 경계 둘레에 옅은 테두리가 생길 수 있습니다.

주의할 점

  • 정답 마스크(0 과 255 만 있는 그림)를 양선형으로 키우면 경계에 128 같은 중간값이 생깁니다. 마스크나 라벨 그림은 INTER_NEAREST 로 바꿉니다.
  • 촘촘한 무늬를 INTER_NEAREST 로 줄이면 계단 현상이 생깁니다. 줄일 때는 INTER_AREA 를 씁니다.
  • interpolation 을 주지 않으면 INTER_LINEAR 입니다. 줄일 때도 기본값이 쓰이므로, 줄이는 코드에는 INTER_AREA 를 적어 줍니다.
← 이전 절14장 · 크기 바꾸기다음 절 →14장 · 자르기와 크기 맞추기