HOWTO · Python
OpenCV 이미지 회전
이 기사에서는 OpenCV의 rotate() 및 warpAffine() 함수를 사용하여 이미지를 회전하는 방법을 설명합니다.
이 페이지의 내용
Python에서 OpenCV로 이미지를 회전하는 방법은 두 가지입니다. 직각 회전에는 cv2.rotate()를 사용하고, 다른 각도로 회전하거나 변환의 중심과 배율을 직접 지정하려면 cv2.getRotationMatrix2D()와 함께 cv2.warpAffine()을 사용합니다. 두 함수 모두 이미지 배열을 처리합니다. 예제는 코드에서 작은 배열을 직접 정의하므로 외부 이미지 파일이 필요하지 않습니다. OpenCV 예제를 실행하려면 OpenCV와 NumPy를 설치하세요. 제공된 실행 기록에서는 필요한 패키지를 사용할 수 없어 OpenCV 호출을 실행하지 않았습니다.
OpenCV rotate()로 90°, 180°, 270° 회전하기
cv2.rotate()는 이미지 배열과 세 가지 방향 상수 중 하나를 받습니다. 시계 방향으로 90° 회전하려면 cv2.ROTATE_90_CLOCKWISE를, 반시계 방향으로 90° 회전하려면 cv2.ROTATE_90_COUNTERCLOCKWISE를 사용합니다. 후자는 시계 방향 270° 회전과 같은 방향입니다. 180° 회전에는 cv2.ROTATE_180을 사용합니다. 90° 회전하면 너비와 높이가 서로 바뀌고, 180° 회전하면 크기는 그대로입니다. 이 예제는 작은 이미지 배열에 세 가지 회전을 모두 적용하고 각 결과의 모양을 출력합니다. OpenCV나 NumPy가 설치되어 있지 않으면 설치 안내를 대신 출력합니다.
이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.
try:
import cv2
import numpy as np
except ImportError:
print("Install opencv-python and numpy to run this example.")
else:
image = np.zeros((2, 3, 3), dtype=np.uint8) # 2 rows, 3 columns, 3 color channels
rotations = {
"clockwise": cv2.ROTATE_90_CLOCKWISE,
"counterclockwise": cv2.ROTATE_90_COUNTERCLOCKWISE,
"half-turn": cv2.ROTATE_180,
}
for name, orientation in rotations.items():
rotated = cv2.rotate(image, orientation)
print(f"{name}: {rotated.shape[1]}x{rotated.shape[0]}")
다음 목록 예제는 좌표가 어떻게 재배치되는지 별도로 보여 줍니다. 예제를 실행해 보세요.
image = [["A", "B", "C"], ["D", "E", "F"]]
rotated = [list(row) for row in zip(*image[::-1])]
print(f"original: {len(image[0])}x{len(image)}")
print(f"rotated: {len(rotated[0])}x{len(rotated)}")
print("rows:", rotated)
original: 3x2
rotated: 2x3
rows: [['D', 'A'], ['E', 'B'], ['F', 'C']]
칸에 표시된 숫자를 보면 화면 표시 창 없이도 회전 방향과 크기 변화를 확인할 수 있습니다. OpenCV 예제는 크기를 너비와 높이 순서로 출력하지만, NumPy의 이미지 모양은 높이, 너비, 채널 순서로 저장됩니다. 파일을 사용하려면 cv2.imread()가 반환한 배열을 cv2.rotate()에 전달하고, 먼저 이미지가 정상적으로 읽혔는지 확인하세요. cv2.rotate()는 이 직각 방향 회전에만 사용할 수 있으며 임의의 각도는 받지 않습니다.
OpenCV warpAffine()으로 임의의 각도 회전하기
cv2.getRotationMatrix2D(center, angle, scale)은 2×3 아핀 행렬을 반환합니다. center는 (x, y) 좌표이고, angle은 도 단위입니다. OpenCV 이미지 좌표계에서 양수 각도는 반시계 방향 회전을 뜻합니다. scale은 이미지 크기에 곱해지는 배율입니다. 1.0이면 크기를 유지하고, 1.0보다 작으면 줄어들며, 크면 확대됩니다. cv2.warpAffine(image, matrix, (width, height))는 이 행렬을 대상 캔버스에 적용합니다. 크기 인수는 너비 다음에 높이를 지정합니다. 이 예제는 120×80 이미지의 중심을 기준으로 30° 회전하고 원래 캔버스 크기를 유지하므로 모서리가 잘릴 수 있습니다. 필요한 패키지가 없으면 설치 안내를 출력합니다.
이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.
try:
import cv2
import numpy as np
except ImportError:
print("Install opencv-python and numpy to run this example.")
else:
height, width = 80, 120
image = np.zeros((height, width, 3), dtype=np.uint8)
center = (width / 2, height / 2)
angle = 30
scale = 1.0
matrix = cv2.getRotationMatrix2D(center, angle, scale)
rotated = cv2.warpAffine(image, matrix, (width, height))
print(f"input canvas: {width}x{height}")
print(f"rotated canvas: {rotated.shape[1]}x{rotated.shape[0]}")
이 예제는 의도적으로 원래의 (width, height)를 대상 크기로 사용합니다. 따라서 출력 크기는 원본과 같고, 캔버스 바깥으로 나간 회전 이미지의 모서리는 잘립니다. 이미지 전체를 보존하려면 회전된 경계를 기준으로 더 큰 대상 크기를 계산하고, 변환된 중심이 새 캔버스의 중심에 오도록 행렬의 평행 이동 값을 조정하세요. 대상 크기만 키우면 변환은 원래 좌표를 기준으로 적용됩니다.
warpAffine()은 소스 픽셀에 대응하지 않는 대상 픽셀을 채웁니다. 기본값인 cv2.BORDER_CONSTANT는 일정한 색으로 채우며, 기본 색은 검정입니다. 다른 색을 쓰려면 borderValue를 지정하세요. cv2.BORDER_REPLICATE는 가장 가까운 소스 가장자리 픽셀을 늘려 채웁니다. cv2.BORDER_TRANSPARENT는 해당 대상 픽셀을 변경하지 않으므로, 이 모드를 쓸 때는 대상 배열을 먼저 초기화하세요. 이 모드는 소스의 테두리를 자동으로 재현하지 않습니다. 사용 가능한 모드는 OpenCV 테두리 모드 참조에서 확인할 수 있습니다.