소스 뷰어
양선형 보간법 (bilinear interpolation)¶
- 영상을 확대할 때 확대비율이 커지면, 최근접 이웃 보간법은 모자이크 현상 혹은 경계부분에서 계단 현상이 나타나게 된다. 이러한 문제를 보완하는 방법이 양선형 보간법 이다.
- 여기서 선형(linear)의 의미는 쉽게 표현하자면 직선의 특징을 가진 것이라 할 수 있는데, 직선의 방정식을 예로 들 수 있다. 두 개 화소의 값을 알고 있을 때 그 값을 직선으로 그려보면 이때 직선 위에 위치한 화소들의 값은 직선의 쉭을 이용해서 쉽게 게산할 수 있다.
- 각 수식은 블로그를 참고
보간 방법 옵션 상수¶
옵션 상수 | 값 | 설명 |
---|---|---|
cv2.INTER_NEAREST | 0 | 최근접 이웃 보간 |
cv2.INTER_LINEAR | 1 | 양선형 보간(기본값) |
cv2.INTER_CUBIC | 2 | 바이큐빅 보간 - 4x4 이웃 화소 이용 |
cv2.INTER_AREA | 3 | 픽셀 영역의 관계로 리샘플링 |
cv2.INTER_LANCZOS4 | 4 | Lanczos 보간 - 8x8 이웃 화소 이용 |
import numpy as np, cv2
def scaling_nearest(img, size): # 크기 변경 함수
dst = np.zeros(size[::-1], img.dtype) # 행렬과 크기는 원소가 역순
ratioY, ratioX = np.divide(size[::-1], img.shape[:2])
i = np.arange(0, size[1], 1)
j = np.arange(0, size[0], 1)
i, j = np.meshgrid(i, j)
y, x = np.int32(i / ratioY), np.int32(j / ratioX)
dst[i,j] = img[y,x]
return dst
# 단일 화소 양선형 보간 수행 함수
def bilinear_value(img, pt):
x, y = np.int32(pt)
if x >= img.shape[1]-1: x = x -1 # 영상 범위 벗어남을 처리
if y >= img.shape[0]-1: y = y - 1
P1, P3, P2, P4 = np.float32(img[y:y+2,x:x+2].flatten())
## 4개의 화소 가져옴 – 화소 직접 접근
# P1 = float(img[y, x] ) # 상단 왼쪽 화소
# P3 = float(img[y + 0, x + 1]) # 상단 오른쪽 화소
# P2 = float(img[y + 1, x + 0]) # 하단 왼쪽 화소
# P4 = float(img[y + 1, x + 1]) # 하단 오른쪽 화소
alpha, beta = pt[1] - y, pt[0] - x # 거리 비율
M1 = P1 + alpha * (P3 - P1) # 1차 보간
M2 = P2 + alpha * (P4 - P2)
P = M1 + beta * (M2 - M1) # 2차 보간
return np.clip(P, 0, 255) # 화소값 saturation후 반환
def scaling_bilinear(img, size): # 양선형 보간
ratioY, ratioX = np.divide(size[::-1], img.shape[:2]) # 변경 크기 비율
dst = [[ bilinear_value(img, (j/ratioX, i/ratioY)) # for문 이용한 리스트 생성
for j in range(size[0])]
for i in range(size[1])]
return np.array(dst, img.dtype)
image = cv2.imread('img/interpolation.jpg', cv2.IMREAD_GRAYSCALE)
if image is None: raise Exception("영상 파일 읽기 에러")
size = (350, 400)
dst1 = scaling_bilinear(image, size) # 크기 변경 - 양선형 보간
dst2 = scaling_nearest(image, size) # 크기 변경 - 최근접 이웃 보간
dst3 = cv2.resize(image, size, 0, 0, cv2.INTER_LINEAR) # OpenCV 함수 적용
dst4 = cv2.resize(image, size, 0, 0, cv2.INTER_NEAREST)
cv2.imshow("image", image)
cv2.imshow("User_bilinear", dst1)
cv2.imshow("User_Nearest", dst2)
cv2.imshow("OpenCV_bilinear", dst3)
cv2.imshow("OpenCV_Nearest", dst4)
cv2.waitKey(0)