Perspective transform
OpenCV APIs
Perspective(원근법) 변환은 직선의 성질만 유지가 되고, 선의 평행성은 유지가 되지 않는 변환입니다. 기차길은 서로 평행하지만 원근변환을 거치면 평행성은 유지 되지 못하고 하나의 점에서 만나는 것 처럼 보입니다.(반대의 변환도 가능)
4개의 Point의 Input값과이동할 output Point 가 필요합니다.
변환 행렬을 구하기 위해서는 cv2.getPerspectiveTransform 함수가 필요하며, cv2.warpPerspective 함수에 변환행렬값을 적용하여 최종 결과 이미지를 얻을 수 있습니다.
아래의 예는 원근법이 적용된 효과를 제거하는 예제입니다.
#-*- coding:utf-8 -*-
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('images/perspective.jpg')
# [x,y] 좌표점을 4x2의 행렬로 작성
# 좌표점은 좌상->좌하->우상->우하
pts1 = np.float32([[504,1003],[243,1525],[1000,1000],[1280,1685]])
# 좌표의 이동점
pts2 = np.float32([[10,10],[10,1000],[1000,10],[1000,1000]])
# pts1의 좌표에 표시. perspective 변환 후 이동 점 확인.
cv2.circle(img, (504,1003), 20, (255,0,0),-1)
cv2.circle(img, (243,1524), 20, (0,255,0),-1)
cv2.circle(img, (1000,1000), 20, (0,0,255),-1)
cv2.circle(img, (1280,1685), 20, (0,0,0),-1)
M = cv2.getPerspectiveTransform(pts1, pts2)
dst = cv2.warpPerspective(img, M, (1100,1100))
plt.subplot(121),plt.imshow(img),plt.title('image')
plt.subplot(122),plt.imshow(dst),plt.title('Perspective')
plt.show()
OpenCV_-_Perspective_Transformation.jpg
원근변환 후 비디오 녹화 샘플
#-*- coding:utf-8 -*-
import cv2
import sys
from numpy import array, float32
def main(input_file: str, output_file: str, headless=True):
cap = cv2.VideoCapture(input_file)
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
input_size = width, height
print("Input: ", input_file)
print("Input fps: ", fps)
print("Input size: ", input_size)
print("Input frames: ", frames)
resize_size = 1920, 1080
print("Resize size: ", resize_size)
left_top = 600, 37
left_bottom = 479, 906
right_top = 1068, 37
right_bottom = 1212, 906
points = left_top, left_bottom, right_top, right_bottom
pp_from = array(points, dtype=float32)
pp_roi = 0, 0, 733, 877
x1, y1, x2, y2 = pp_roi
pp_width = abs(x2 - x1)
pp_height = abs(y2 - y1)
pp_size = pp_width, pp_height
pp_to = array(((x1, y1), (x1, y2), (x2, y1), (x2, y2)), dtype=float32)
m = cv2.getPerspectiveTransform(pp_from, pp_to, cv2.DECOMP_LU)
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
writer = cv2.VideoWriter(output_file, fourcc, fps, pp_size)
print("Output: ", output_file)
print("Output fps: ", fps)
print("Output size: ", pp_size)
try:
i = 0
while True:
# print(f"{i}/{frames}")
i += 1
ret, image = cap.read()
if not ret:
break
if image.shape[0:2] != resize_size:
image = cv2.resize(image, dsize=resize_size)
image = cv2.warpPerspective(image, m, pp_size)
writer.write(image)
if not headless:
cv2.imshow("Preview", image)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
finally:
cap.release()
writer.release()
if not headless:
cv2.destroyAllWindows()
if __name__ == "__main__":
main(sys.argv[1], sys.argv[2], True)
See also
- Affine transformation
- Perspective transform
- OpenCV - Geometric Transformations of Images
- 리매핑 (Remapping)
- 오목/볼록 렌즈 왜곡 (Lens Distortion)
- 방사 왜곡(Radial Distortion)
- 핀홀 카메라 모델 (Pinhole camera model)
Favorite site
- 3D projection - Wikipedia # Perspective projection
- 이미지의 기하학적 변형 — gramman 0.1 documentation
- OpenCV: Geometric Transformations of Images
- (에러를 딛고 깨달은) opencv perspective transform 후 선 그린 후 원본에서 해당 선의 위치 구하기 - 역변환 하기, 점 변환
- OpenCV - 15. 리매핑(Remapping), 오목/볼록 렌즈 왜곡(Lens Distortion), 방사 왜곡(Radial Distortion)