이미지 축소 시,
이미지 축소로 인한 어느정도 소실은 발생하며 사용한 보간법에 따라 그 정도의 크기가 다름
육안으로 식별이 안되지만 수치적으로 비교해봤을 때, 어느정도 차이가 있음
해당 포스트에서는 파이썬 Pillow 라이브러리를 사용해 이미지 축소 시 보간법마다의 소실 정도를 확인
- 정량적 : PSNR(이미지 품질 평가 방법 중 하나) 를 사용한 수치 비교
* 육안으로 식별 불가능한 경우에 사용
- 정성적 : 축소된 이미지 간 차이 비교
# 보간법 (Interpolation)
원본 이미지의 주변 픽셀값을 이용해 그 사이에 있는 픽셀값을 예측하는 방법
# 사용한 보간법 종류
1. Nearest
2. Lanczos
3. Bilinear
4. Box
5. Hamming
6. Bicubic
* 이미지 보간법에 대해서는 추후 예정
* 원리 이해 부족
# PSNR (Peak Signal-to-Noise Ratio)
최대 신호 대 잡음비
이미지 품질 평가 방법 중 하나
- 품질이 좋은 이미지 : 큰 psnr 값을 가짐
- 품질이 나쁜 이미지 : 작은 psnr 값을 가짐
> 개념
신호가 가질 수 있는 최대 신호에 대한 잡음의 비
압축된 이미지의 화질에 대한 손실 정보를 평가하기 위한 목적으로 사용
SRCNN 모델에서 출력된 이미지 Evaluation 하는 과정에서 사용
* SRCNN(Super Resolution CNN) : 저품질(blur image) Patch 이미지를 입력으로 고품질 이미지를 출력하는 딥러닝 알고리즘
> 단위
db(log scale), 데시벨
> 계산식
PSNR = 20 * log_10 ( MAX_f / 루트(MSE) )
> 적용
원본 이미지와 압축(축소) 이미지 사이의 품질 측정
> 단점
수치 평가 결과와 사람이 느끼는 결과가 다르게 보일순 있음
보완 : PSNR-HVS, SSIM, VIF 등의 다른 metric를 사용
# 원본 이미지
0 ~255 픽셀을 나타내는 Grayscale 이미지를 사용
* Pixabay 에서 가져온 풍차 이미지 사용
# 보간법에 따른 이미지 축소 & 저장
from PIL import Image
# resize 할 이미지 사이즈
img_size = 300
# Nearest
img_resize_nearest = img.resize((img_size, img_size), Image.NEAREST).convert("L")
img_resize_nearest.save('/gdrive/MyDrive/Colab/datasets/test/re_nearest.jpg')
# Lanczos
img_resize_lanczos = img.resize((img_size, img_size), Image.LANCZOS).convert("L")
img_resize_lanczos.save('/gdrive/MyDrive/Colab/datasets/test/re_lanczos.jpg')
# Bilinear
img_resize_bilinear = img.resize((img_size, img_size), Image.BILINEAR).convert("L")
img_resize_bilinear.save('/gdrive/MyDrive/Colab/datasets/test/re_bilinear.jpg')
# Box
img_resize_box = img.resize((img_size, img_size), Image.BOX).convert("L")
img_resize_box.save('/gdrive/MyDrive/Colab/datasets/test/re_box.jpg')
# Hamming
img_resize_hamming = img.resize((img_size, img_size), Image.HAMMING).convert("L")
img_resize_hamming.save('/gdrive/MyDrive/Colab/datasets/test/re_hamming.jpg')
# Bicubic
img_resize_bicubic = img.resize((img_size, img_size), Image.BICUBIC).convert("L")
img_resize_bicubic.save('/gdrive/MyDrive/Colab/datasets/test/re_bicubic.jpg')
* Pillow (Python Imaging Library): 이미지 처리에 대한 기능을 제공하는 라이브러리, PIL
# PSNR 함수 구현
# 최대 신호 대 잡음비
def psnr(ori_img, con_img):
"""
@params ori_img: 원본 이미지
@params con_img: 비교 대상 이미지
"""
# 해당 이미지의 최대값 (채널 최대값 - 최솟값)
max_pixel = 255.0
# MSE 계산
mse = np.mean((ori_img - con_img)**2)
if mse ==0:
return 100
# PSNR 계산
psnr = 20* math.log10(max_pixel / math.sqrt(mse))
return psnr
# 이미지 확대
PSNR을 적용하기 위해서, 이미지 간의 사이즈가 같아야 함
일종의 야매방법으로,
축소에 사용한 보간법으로 다시 원본 이미지 크기에 맞게 확대함
* 좋은 방법이 있으면 그 방법으로 하면 됨
ex. 원본이미지 -> (Nearest 보간법) -> 축소된 이미지 -> (Nearest 보간법) -> 확대된 이미지
# 이미지 확대
# - PSNR 이미지 비교를 위해 원본 사이즈로 이미지 확대 (축소때 사용한 보간법 그대로 적용)
img_nearest = img_resize_nearest.resize((w, h), Image.NEAREST)
img_nearest.save('/gdrive/MyDrive/Colab/datasets/test/nearest.jpg')
img_lanczos = img_resize_lanczos.resize((w, h), Image.LANCZOS)
img_lanczos.save('/gdrive/MyDrive/Colab/datasets/test/lanczos.jpg')
img_bilinear = img_resize_bilinear.resize((w, h), Image.BILINEAR)
img_bilinear.save('/gdrive/MyDrive/Colab/datasets/test/bilinear.jpg')
img_box = img_resize_box.resize((w, h), Image.BOX)
img_box.save('/gdrive/MyDrive/Colab/datasets/test/box.jpg')
img_hamming = img_resize_hamming.resize((w, h), Image.HAMMING)
img_hamming.save('/gdrive/MyDrive/Colab/datasets/test/hamming.jpg')
img_bicubic = img_resize_bicubic.resize((w, h), Image.BICUBIC)
img_bicubic.save('/gdrive/MyDrive/Colab/datasets/test/bicubic.jpg')
+ Image.fromarray(array_img) : 픽셀 이미지 -> PIL 타입의 Image
+ np.array(PIL_type_img) : PIL 타입의 Image -> 픽셀 이미지
PSNR 계산 시, pil_type_image 는 안됨*
# 원 사이즈 -> (보간법 적용된) 축소된 이미지 -> 원 사이즈로 확대 (축소에 사용한 보간법과 동일한 보간법 사용)
# PIL 타입 변경
origin_img = cv2.imread('/gdrive/MyDrive/Colab/datasets/test/origin_img.jpg')
nearest_img = cv2.imread('/gdrive/MyDrive/Colab/datasets/test/nearest.jpg')
lanczos_img = cv2.imread('/gdrive/MyDrive/Colab/datasets/test/lanczos.jpg')
bilinear_img = cv2.imread('/gdrive/MyDrive/Colab/datasets/test/bilinear.jpg')
box_img = cv2.imread('/gdrive/MyDrive/Colab/datasets/test/box.jpg')
bicubic_img = cv2.imread('/gdrive/MyDrive/Colab/datasets/test/bicubic.jpg')
hamming_img = cv2.imread('/gdrive/MyDrive/Colab/datasets/test/hamming.jpg')
> 확대된 이미지 확인
# PSNR 결과 출력
PSNR(원본 이미지, 보간법 이미지)
# PSNR 결과 출력 (클수록 원본이미지와 품질 근사함)
print("Nearest : ", psnr(origin_img, nearest_img))
print("Bicubic : ", psnr(origin_img, bicubic_img))
print("Bilinear : ", psnr(origin_img, bilinear_img))
print("Box : ", psnr(origin_img, box_img))
print("Lanzos : ", psnr(origin_img, lanczos_img))
print("Hamming : ", psnr(origin_img, hamming_img))
> 수치 비교
원본 이미지와 보간법 적용된 이미지 간 품질 평가 결과,
Nearest Neighbor 보간법이 품질이 높게 나옴
> 이미지
# 정리
이미지를 축소/확대 시, 발생할 수있는 손실을 확인 하기 위해서 이미지 품질 평가 방법 중 하나인 PSNR을 사용
단, PSNR 수행 시 두 이미지의 사이즈가 같아야하기 때문에 똑같은 보간법으로 축소/확대를 사용해서 비교 수행
# 결론
PSNR 식 자체에 대해서는 문제없다고 생각
보간법을 두번 사용(축소/확대)한 것에 대해서 PSNR을 수행했기 때문에 정확한 이미지 품질 평가 결과라고도 할 수 없음