728x90
반응형
개요
이미지의 크기를 조정할 때 일반적으로 cv2.resize() 함수를 이용하게 됩니다.
이 때, 이미지의 종횡비를 왜곡하지 않고 테두리를 추가는 방법들을 살펴 보겠습니다.
일반적인 이미지 복사
무작위 이미지를 HD(1280 X 720)으로 크기를 조정할 때 다음과 같이 종횡비를 고정하여 만들 수 있습니다.
target_height, target_width = 720, 1280
img_org = cv2.imdecode(np.fromfile(full_image_filename, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
img_height, img_width = img_org.shape[:2]
height_scale, width_scale = (img_height / target_height), (img_width / target_width)
img_scale = min(height_scale, width_scale)
# 원본 이미지를 설정에 맞게 축소
scaled_height, scaled_width = round(img_width * img_scale), round(img_height * img_scale)
scaled_img = cv2.resize(img_org, (scaled_width, scaled_height), interpolation = cv2.INTER_CUBIC)
img_new = np.full((target_height, target_width, 3), (127, 127, 127), dtype = np.uint8)
img_new[0:scaled_height, 0:scaled_width] = scaled_img
np.full() 함수를 이용하여 미리 지정된 크기의 빈 이미지를 생성하고, 거기에 크기를 조정한 이미지를 붙여넣기 하는 방식입니다.
copyMakeBorder() 함수 이용
종횡비는 고정한 채 이미지의 크기를 조정할 때 copyMakeBorder() 함수를 이용하면 조금 더 간편하고 빠르게 동작합니다. copyMakeBorder() 함수 사용 예시입니다.
target_height, target_width = 720, 1280
img_org = cv2.imdecode(np.fromfile(full_image_filename, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
img_height, img_width = img_org.shape[:2]
height_scale, width_scale = (img_height / target_height), (img_width / target_width)
img_scale = min(height_scale, width_scale)
# 원본 이미지를 설정에 맞게 축소
scaled_height, scaled_width = round(img_width * img_scale), round(img_height * img_scale)
scaled_img = cv2.resize(img_org, (scaled_width, scaled_height), interpolation = cv2.INTER_CUBIC)
img_new2 = cv2.copyMakeBorder(scaled_img, 0, target_height - scaled_height, 0, target_width - scaled_width, cv2.BORDER_CONSTANT, (127, 127, 127))
위 두 방식간의 성능 비교
위 두 방식간 성능을 다음과 같이 간단하게 비교해 보았습니다.
from timeit import timeit
def main() -> int:
setup = """
import cv2
import numpy as np
target_height, target_width = 720, 1280
full_image_filename = 'D:/Temp/lpd/test/Red_Apple.jpg'
img_org = cv2.imdecode(np.fromfile(full_image_filename, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
img_height, img_width = img_org.shape[:2]
height_scale, width_scale = (target_height / img_height), (target_width / img_width)
img_scale = min(height_scale, width_scale)
# 원본 이미지를 설정에 맞게 축소
scaled_width, scaled_height = round(img_width * img_scale), round(img_height * img_scale)
"""
result1 = timeit ("""
scaled_img = cv2.resize(img_org, (scaled_width, scaled_height), interpolation = cv2.INTER_CUBIC)
img_new = np.full((target_height, target_width, 3), (127, 127, 127), dtype = np.uint8)
img_new[0:scaled_height, 0:scaled_width] = scaled_img
""", setup = setup, number = 1000)
print(f'result1 = {result1}')
result2 = timeit ("""
scaled_img = cv2.resize(img_org, (scaled_width, scaled_height), interpolation = cv2.INTER_CUBIC)
cv2.copyMakeBorder(scaled_img, 0, target_height - scaled_height, 0, target_width - scaled_width, cv2.BORDER_CONSTANT, (127, 127, 127))
""", setup = setup, number = 1000)
print(f'result2 = {result2}')
if (__name__ == '__main__'):
main()
실행결과는 다음과 같이 copyMakeBorder() 함수를 이용했을 때가 약 2배 정도 성능이 좋게 나왔습니다.
result1 = 4.855554999783635
result2 = 2.5016783997416496
'프로그래밍 > Python' 카테고리의 다른 글
[python] TypeError: argument 'data': 'memoryview' object cannot be converted to 'PyBytes' (0) | 2024.06.19 |
---|---|
[python] LM73 TI 온도센서에서 온도값 읽어오기 (0) | 2024.06.10 |
[Python] numpy 이용 시 발생한 'ImportError: libopenblas.so.0: cannot open shared object file' 오류 (0) | 2024.05.28 |
[python] 경로 문자열에서 파일명, 확장자 분리하기 (0) | 2024.05.22 |
[python] RGBA 형식의 이미지 찾기 (0) | 2024.05.21 |