opencv-python 코드 snippets
2018, Jul 21
목차
-
warpAffine을 이용한 기하학적 변환
-
warpAffine과 warpPerspective를 이용한 기하학적 변환
-
resize를 이용한 크기 변환
-
flip을 이용한 대칭 변환
-
window 창 크기 조절하는 방법
-
contrast와 brightness 변경 방법
-
이미지 붙이기(hconcat, vconcat)
-
OpenCV 한글 쓰기
-
90도 이미지 회전
-
gif 만들기 with imageio
-
jupyter notebook에 numpy image 동영상 재생
-
두 이미지를 오버레이 하기
-
픽셀의 하한, 상한 값 정하기
-
Automatic Canny Edge Detection
-
erosion과 dilation
-
rvecs와 Rodrigues 함수
-
기타 참조 내용
warpAffine을 이용한 기하학적 변환
- Affine 변환에 대한 이론적 개념은 아래 링크를 참조하시기 바랍니다.
Translation Transformation (이동 변환)
- Affine 변환을 이용하여
이동 변환을 구현해 보도록 하겠습니다. 사용 방법은 다음과 같습니다.

src는 입력 영상을 뜻하고M은 이동 변환을 위한 affine 변환 행렬 입니다. 위의 이론과 관련된 링크를 참조하면 Affine 변환에서 사용되는 2 X 3 크기의 affine 변환 행렬의 의미를 확인하실 수 있습니다. affine 변환 행렬은np.float32로 선언되어야 합니다.dsize는 출력 영상의 크기이며dst는 출력 영상이 저장되는 array 입니다. 이 때,dsize가src의 사이즈와 다르면 resize를 해야 하는데 그 때 사용되는interpolation방법이flags입니다. 기본적으로 bilinear interpolation이 사용됩니다.- 이동 변환을 하게 되는 경우 dst 사이즈 영역에서 값이 존재하는 영역이 있는 반면 값이 없는 영역도 발생하게 됩니다. 이 영역을 어떤 값으로 채울 지가
borderValue에 해당하며 기본값은 검정색인 0이 됩니다.
src = cv2.imread('test.png')
'''
x' ← x + 200
y' ← y + 100
[1, 0, 200
0, 1, 100]
'''
aff = np.array([[1, 0, 200], [0, 1, 100]], dtype=np.float32)
dst = cv2.warpAffine(src, aff, (0, 0))

- 위 결과와 같이 \(x\) 방향으로 200, \(y\) 방향으로 100만큼 이동 변환하였고, 픽셀값이 없는 영역은 검은색 (0)으로 입력된 것을 확인할 수 있습니다.
Shear Transformation (전단 변환)
- 먼저 전단 변환과 관련된 이론적인 내용은 링크를 참조하시기 바랍니다. 위 링크를 통하여 전단 변환 적용 시 어떻게 Affine 행렬을 작성해야 할 지 알 수 있습니다.
- 아래 예제는 x축을 y축 대비 0.5의 비율로 기울인 효과를 나타냅니다.
src = cv2.imread('test.png')
'''
x' ← x + 0.5 * y
y' ← y
[1, 0.5, 0
0, 1, 0]
'''
aff = np.array([[1, 0.5, 0], [0, 1, 0]], dtype=np.float32)
h, w = src.shape[:2]
# dst의 크기는 affine 변환 행렬에서 x축 방향으로 늘어난 만큼 더 더해주어야 합니다.
# affine 변환 행렬에서 x축의 사이즈가 늘어난 크기는 y축 사이즈의 반 만큼 늘어나게 되므로 (h*0.5)를 w에 더해줍니다.
dst = cv2.warpAffine(src, aff, (w + int(h * 0.5), h))

- 따라서 위 코드의 Affine 변환을 적용하였을 때, 위 그림과 같이 Shear Transformation이 적용됩니다.
Rotation Transformation (회전 변환)
- 먼저 회전 변환에 관한 이론적인 배경은 아래 링크를 참조하시기 바랍니다.
- 앞에서 설명한
warpAffine을 이용하면 affine 변환 행렬만 회전 변환 행렬에 맞게 사용 하면 됩니다. - 아래 코드와 같이 회전할 각도를 radian으로 정한 뒤 affine 변환 행렬을 만들어서
warpAffine에 적용하면 회전 변환을 적용할 수 있습니다.
rad = 20 * math.pi / 180
aff = np.array([[math.cos(rad), math.sin(rad), 0],
[-math.sin(rad), math.cos(rad), 0]], dtype=np.float32)
dst = cv2.warpAffine(src, aff, (0, 0))

- 위 회전 결과는 직교 좌표계에서 (0, 0)을 기준 축으로 두고 회전을 하게 됩니다. 이와 같은 경우 회전되는 방향으로 많은 양의 이미지가 잘리게 됩니다.
- 이상적으로 이미지를 회전 하려면 이미지의 중앙 좌표를 기준으로 회전을 하는 것이 합리적으로 보입니다. 이미지의 임의의 점 (ex. 중앙 좌표)를 기준으로 회전 하려면 다음과 같은 과정 (① 이동 변환 ② 회전 변환 ③ 이동 변환)을 거쳐서 회전을 하게 됩니다.

- 이와 같은 변환을 하기 위해서 직접 affine 변환 행렬을 만들어도 상관 없고
getRotationMatrix2d함수를 사용해도 됩니다.

- 위 affine 변환 행렬에서
(x, y)는 이미지에서 회전 축을 의미합니다. angle은 degree 단위의 각도로 반시계 방향으로 30도 회전이 필요하면 30을 입력합니다. 시계 방향은 음수 각도로 입력하면 됩니다.scale은 회전하면서 영상을 확대할 지, 축소할 지에 대한 scale 값입니다. 보통 영상을 회전하면 잘리는 영역이 발생하기 때문에 축소하여 회전된 영상을 확인하곤 합니다.
- 그러면
getRotationMatrix2d와warpAffine함수를 어떻게 섞어서 사용하는 지 살펴보겠습니다.
center_point = (src.shape[1] / 2, src.shape[0] / 2)
# 20도 반시계 방향 회전 + scale 변환 없음
affine_matrix = cv2.getRotationMatrix2D(cp, 20, 1)
dst = cv2.warpAffine(src, affine_matrix, (0, 0))

warpAffine과 warpPerspective를 이용한 기하학적 변환
- 먼저 Affine Transformation과 Perspective Transformation에 관한 개념적인 내용은 아래 링크를 통해 확인할 수 있습니다.
- 먼저 Affine Transformation을 하기 위하여 사용하는 2가지 함수는
getAffineTransform함수와warpAffine함수입니다.
getAffineTransform함수는 원 영상의 3개의 좌표 \((x_{1}, y_{1}), (x_{2}, y_{2}), (x_{3}, y_{3})\)와 변환된 영상에서 3개의 좌표에 대응되는 좌표 \((x_{1}', y_{1}'), (x_{2}', y_{2}'), (x_{3}', y_{3}')\)를 입력으로 주면 2 X 3 형태의 Affine 변환 행렬을 반환합니다.

getAffineTransform을 통해 얻은 Affine 변환 행렬을warpAffine의 2번째 인자M에 넣으면 Affine Transformation을 할 수 있습니다.

- Perspective Transformation을 할 때에도 방식은 유사합니다.
getPerspectiveTransform함수를 통하여 perspective 변환 행렬을 얻고warpPerspective함수를 이용하여 변환을 합니다. getPerspectiveTransform함수는 원 영상의 4개의 좌표 \((x_{1}, y_{1}), (x_{2}, y_{2}), (x_{3}, y_{3}), (x_{4}, y_{4})\)와 변환된 영상에서 4개의 좌표에 대응되는 좌표 \((x_{1}', y_{1}'), (x_{2}', y_{2}'), (x_{3}', y_{3}'), (x_{4}', y_{4}')\)를 입력으로 주면 3 X 3 형태의 Perspective 변환 행렬을 반환합니다.

getAffineTgetPerspectiveTransformransform을 통해 얻은 Affine 변환 행렬을warpPerspective의 2번째 인자M에 넣으면 Perspective Transformation을 할 수 있습니다.

- Perspective Transformation을 OpenCV 코드로 어떻게 사용하는 지 예제를 살펴보겠습니다.
src = cv2.imread('namecard.jpg')
w, h = 720, 400
# 원 영상에서 4개의 점
srcQuad = np.array([[325, 307], [760, 369], [718, 611], [231, 515]], np.float32)
# perspective 변환 시 대응 되어야 할 점 (이미지의 각 모서리에 맞추는 예제)
dstQuad = np.array([[0, 0], [w-1, 0], [w-1, h-1], [0, h-1]], np.float32)
pers = cv2.getPerspectiveTransform(srcQuad, dstQuad)
dst = cv2.warpPerspective(src, pers, (w, h))
resize를 이용한 크기 변환
- 앞에서 다룬 Affine 변환 중 크기 변환은 기하학적 변환 중 가장 많이 사용되는 변환 중 하나입니다.
- 따라서 OpenCV에서는 크기 변환을 위한 별도 함수인
resize를 제공합니다.

- 주의하실 점은 2번째 인자인
dsize입니다. 먼저 출력 영상의 size를(w, h)형태로 명시적으로 입력할 수 있습니다. 하지만 만약 dsize = (0, 0)이 입력된다면 이후에 입력되는(fx, fy)를 통하여 출력 영상의 확대/축소 비율을 정할 수 있습니다. 이 값은 \(x\)와 \(y\) 방향의 scale factor 입니다. 따라서 실제 출력되는 크기인 dsize = (w, h)가 입력되거나 dsize = (0, 0) && 확대/축소 비율 (fx, fy)이 반드시 입력되어야 합니다. - resize의 마지막 인자는
interpolation입니다. 앞에서 다룬 affine 변환에서는flags인자에서 interpolation을 다룹니다. interpolation은 이미지의 기하학적 변환이 발생할 때 (특히, 영상의 크기가 커질 때), 중간 중간에 채워지지 않는 값들을 어떻게 채워 나아갈 지에 대한 방법입니다. affine 변환과 affine 변환 중 하나인resize모두 기본 interpolation 방법은bilinear interpolation(양선형 보간법)입니다. bilinear interpolation은 interpolation 성능이 가장 좋은 방법은 아니지만 매우 효율적인 방법이면서 어느 정도 성능을 보장하기 때문에 많이 사용하는 방법입니다.- OpenCV에서 제공하는 5가지 interpolation 방법은 위 테이블을 참조하시면 됩니다. 아래에 있는 방법일수록 효율성은 떨어지지만 interpolation 성능은 높아집니다. 마지막의 INTER_AREA는 영상 축소 시 효과적입니다.
src = cv2.imread('rose.bmp') # 480x320
dst1 = cv2.resize(src, (0, 0), fx=4, fy=4, interpolation=cv2.INTER_NEAREST)
dst2 = cv2.resize(src, (1920, 1280)) # cv2.INTER_LINEAR
dst3 = cv2.resize(src, (1920, 1280), interpolation=cv2.INTER_CUBIC)
dst4 = cv2.resize(src, (1920, 1280), interpolation=cv2.INTER_LANCZOS4)

- 각 interpolation 방식에 따른 resize 결과를 살펴보면 INTER_NEAREST은 artifact가 관찰되는 문제가 있는 반면 나머지 방식은 큰 품질 차이가 보이진 않습니다.

- 앞에서 설명한 바와 같이 이미지를 축소할 때에는
INTER_AREA방식의 interpolation을 사용하는 것이 좋습니다. 이 방법의 특성상 위 그림과 같이 어떤 형상이 1 ~ 2 픽셀로 이루어진 경우 영상 축소 시 디테일이 사라지는 문제를 개선할 수 있기 때문입니다.
flip을 이용한 대칭 변환
- 영상의 대칭 변환을 사용하려면
flip함수를 이용하면 쉽게 구현할 수 있습니다. flip은 기본적으로좌우 대칭,상하 대칭,좌우 + 상하 대칭이 있습니다. 사용 방법은 다음과 같습니다.

window 창 크기 조절하는 방법
- 이미지의 height, width의 크기는 유지한 상태로 window에서 이미지를 크게 보고 싶으면 아래 코드를 통하여 창의 크기를 변경할 수 있습니다.
- 이 때, window의 크기만 조정하고 이미지의 크기는 변경하지 않으므로, 화면에 보이는 픽셀 한 개의 크기가 확대/축소 되어 전체 window의 크기가 변경된다고 이해하면 됩니다. 따라서 확대할 경우 한 픽셀의 크기가 커져서 보이는 것을 확인할 수 있습니다.
cv2.namedWindow("image", 0)
cv2.resizeWindow("image", win_width, win_height)
- 위 코드와 같은 경우 window의 크기가
win_width,win_height크기로 변경됩니다. 물론 이미지의 실제 크기 변경은 없습니다.
contrast와 brightness 변경 방법
- 참조 : https://docs.opencv.org/3.4/d3/dc1/tutorial_basic_linear_transform.html
- 픽셀의 값에 곱을 하면
contrast가 조절되고 덧셈을 하면brightness가 조절됩니다.
- \[g(i,j) = \alpha \cdot f(i,j) + \beta\]
- 위 수식과 같이 각 픽셀에 대하여 \(\alpha\) 값을 곱해주면
contrast가 조정되고 \(\beta\) 값을 더해주면brightness가 조정됩니다. - 코드를 간단히 살펴보면 다음과 같습니다. (물론 아래 코드를 사용하진 않습니다. 느리기 때문입니다.)
for y in range(image.shape[0]):
for x in range(image.shape[1]):
for c in range(image.shape[2]):
new_image[y,x,c] = np.clip(alpha*image[y,x,c] + beta, 0, 255)
- 실제
opencv에서 제공하는 코드는 다음과 같습니다.
new_image = cv.convertScaleAbs(image, alpha=alpha, beta=beta)
- 위 코드는 for-loop을 사용하지 않으면서도 opencv 내부적으로 잘 구현되어 있어서 for-loop의 naive한 버전 보다 상당히 빠르게 contrast와 brightness를 적용할 수 있습니다.
이미지 붙이기(hconcat, vconcat)
- 이미지를 가로로 또는 세로로 붙이고 싶을 때, 쉽게 사용할 수 있는 함수가
hconcat과vconcat이 있습니다. hconcat은 horizontal concatenate로 가로로 이미지를 붙이는 것이고vconcat은 vertical concatenate로 세로로 이미지를 붙이는 것입니다.hconcat을 이용하려면 가로로 붙여야 하기 때문에 height가 같아야 합니다. 반면vconcat은 세로로 이미지를 붙여야 하기 때문에 width가 같아야 합니다.
image = cv2.hconcat([image1, image2, image3])
image = cv2.vconcat([image1, image2, image3])
OpenCV 한글 쓰기
- OpenCV를 이용하여 이미지에 글자를 쓸 때, 한글은 안써집니다.
- 따라서 OpenCV 함수를 직접 이용하지 않고 PIL(Python Image Library)를 이용하여 우회해서 사용하면 사용 가능합니다.
- 아래 함수는 numpy와 pil을 이용하여 numpy 배열에 한글을 입력하는 함수
PutText를 작성한 것입니다. - PutText 함수의
fontpath의 font를 수정하면 원하는 font도 사용가능합니다.
import numpy as np
from PIL import ImageFont, ImageDraw, Image
def PutText(src, text, font_size, xy, bgr):
fontpath = "fonts/gulim.ttc"
font = ImageFont.truetype(fontpath, font_size)
src_pil = Image.fromarray(src)
draw = ImageDraw.Draw(src_pil)
draw.text(xy, text, font=font, fill=bgr)
target = np.array(src_pil)
return target
img = np.zeros((300,500,3),np.uint8)
img= PutText(img, "테스트입니다.", font_size = 30, xy = (100, 200), bgr = (255, 0, 0))
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
90도 이미지 회전
- 파이썬에서 이미지를 90도 회전하는 방법은 opencv를 이용하는 방법과 numpy를 이용하는 방법이 있습니다.
- 이 글에서는 opencv를 이용하는 방법에 대하여 간략하게 설명하겠습니다.
- 사용하는 함수는
cv2.rotate()함수이며 사용 방법은target_image = cv2.rotate(src_image, 옵션)로 사용합니다. - 사용 가능한 옵션은 다음과 같습니다.
cv2.ROTATE_90_CLOCKWISE: 90도 시계 방향 회전cv2.ROTATE_90_COUNTERCLOCKWISE: 90도 반시계 방향 회전cv2.ROTATE_180: 180도 회전
import cv2
img = cv2.imread('data/src/lena.jpg')
img_rotate_90_clockwise = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)
img_rotate_90_counterclockwise = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)
img_rotate_180 = cv2.rotate(img, cv2.ROTATE_180)
gif 만들기 with imageio
- 이미지를 이용하여 GIF를 만들 때에는
imageio라는 패키지를 이용하면 쉽게 만들 수 있습니다. - 설치 :
pip install imageio imageio.mimsave()함수를 통하여 gif 형태로 저장할 수 있습니다. 기본적으로 파일 경로와 gif로 만들 이미지 리스트를 파라미터로 받습니다.- 프레임 간 간격은
duration이란 옵션을 추가적으로 적용하여 간격 조정을 할 수 있습니다.
import imageio
images = []
for filename in filenames:
images.append(imageio.imread(filename))
imageio.mimsave('/path/to/movie.gif', images)
# imageio.mimsave('/path/to/movie.gif', images, duration=0.1)
jupyter notebook에 numpy image 동영상 재생
- jupyter notebook에서 연속적인 이미지를 읽은 다음 동영상 처럼 재생할 때 아래 코드를 사용하여 시각화할 수 있습니다. jupyter notebook에 표시할 때, 동영상을 보여주고 지우고 보여주고 지우는 것을 반복하는 작업입니다.
import cv2
import os
import glob
import IPython
path = "/path/to/the/images
image_paths = glob.glob(path + os.sep + "*.png")
image_paths.sort()
for image_path in image_paths:
image = cv2.imread(image_path, -1)
image = cv2.resize(image, (image.shape[1]//4, image.shape[0]//4))
_, ret = cv2.imencode('.jpg', image)
display_image = IPython.display.Image(data=ret)
IPython.display.clear_output(wait=True)
IPython.display.display(display_image)
- 실행 결과는 다음과 같습니다. 아래 데이터는
A2D2데이터의 영상입니다.

두 이미지를 오버레이 하기
- 두 이미지를 투명한 형태로 오버레이 하여 하나의 이미지에서 겹쳐서 보는 방법을 blending 이라고 합니다.
- 두 이미지를 blending 하기 위해서는 다음과 같은 간단한 연산을 통해 구현 가능합니다.
- \[dst = \alpha * src1 + \beta * src2 + \gamma\]
- \[\alpha + \beta = 1, \ \ 0 \le \alpha, \beta \le 1\]
- 위 식을 살펴보면 각 영상에 \(\alpha, \beta\)와 같은 가중치가 있습니다. 이 가중치가 1에 가까울수록 해당 영상을 좀 더 진하게 반영하고 0에 가까울수록 투명하게 반영됩니다.
- 위 식의 \(\gamma\)는 bias에 해당합니다.
- blending을 하기 위해서
cv2.addWeighted를 사용하며 사용 방법은 다음과 같습니다. dst = cv2.addWeighted(src1, alpha, src2, beta, gamma)- 위 함수는 src1과 src2 영상을 각각 \(\alpha, \beta\)의 가중치를 사용하여 blending 합니다.
픽셀의 하한, 상한 값 정하기
- 이미지 데이터에 어떤 연산을 가했을 때, uint8 데이터 타입의 값 범위인 [0, 255]를 벗어날 수 있습니다.
- 범위에 벗어난 값을 하한값, 상한값으로 saturation 시킬 때,
np.clip(array, lower_bound, upper_bound)을 이용할 수 있습니다.
lower_bound = 0
upper_bound = 255
img = np.clip(img, lower_bound, upper_bound).astype(np.uint8)
Automatic Canny Edge Detection
- 아래는
canny edge detection을 위한 코드 입니다.canny에서 필요한 하한값은 \(-\sigma\) 을 사용하고 상한값 \(\sigma\) 를 사용하여 각각의 이미지의 통계에 맞게 사용할 수 있도록 적용합니다.
def auto_canny(image, sigma=0.33):
# compute the median of the single channel pixel intensities
v = np.median(image)
# apply automatic Canny edge detection using the computed median
lower = int(max(0, (1.0 - sigma) * v))
upper = int(min(255, (1.0 + sigma) * v))
edged = cv2.Canny(image, lower, upper)
# return the edged image
return edged
erosion과 dilation
- 아래는
erosion과dilation을 위한 간단한 코드 입니다.
img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
kernel = np.ones((3, 3), np.uint8)
erosion = cv2.erode(img, kernel, iterations=1)
dilation = cv2.dilate(img, kernel, iterations=2)
rvecs와 Rodrigues 함수
- 참조 : https://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html?highlight=rodrigues#void%20Rodrigues(InputArray%20src,%20OutputArray%20dst,%20OutputArray%20jacobian)
-
참조 : https://www.andre-gaschler.com/rotationconverter/
opencv에서 캘리브레이션이나 3D 관련 함수 사용 시rvecs와tvecs를 입/출력 값으로 사용하곤 합니다.rvecs와tvecs는opencv함수에서 계산된 결과 또는 계산하고자 하는 \(X, Y, Z\) 축 순서의Rotation과Translation을 위한 정보입니다.
rvecs와tvecs의 타입은list이며 각 원소는 3개의 값을 가지는 벡터입니다.list는 처리한 이미지의 갯수를 의미합니다. 예를 들어 어떤 작업 (ex. 캘리브레이션)을 10장의 이미지로 처리하였으면list의 길이는 10이 되며 이미지 각 정보에 대한Rotation,Translation이 구성되어 입/출력됩니다.- 만약 \(i\) 번째 이미지의
Rotation과Translation을 구성한다고 하면rvces[i]와tvecs[i]가 대응이 되어 \(X, Y, Z\) 의Rotation과Translation을 구성할 수 있습니다. 관련 방법을 좀 더 자세하게 살펴보겠습니다.
rvecs[i] = rvec는 3개의 값을 가지는 벡터입니다. 이 벡터 값은Rodrigues변환을 통해 \(3 \times 3\) 크기의 행렬로 만들 수 있습니다.- 먼저
rvec은로드리게스 회전 (또는 축각 회전)으로 표현되어 있습니다. 이 방법은 3차원에서 회전하고자 하는 3차원 벡터 축(Axis)과 축을 기준으로 회전하고자 하는 회전량을 이용하는 방법입니다. 상세 내용은 아래 글을 참조하시기 바랍니다.

- 따라서
로드리게스 회전을 위해서는 기본적으로는 회전축axis를 표현하는 벡터값 3개와 회전각도 1개 총 4개의 값이 필요로 합니다. 하지만rvec은 3개의 값만 가지고 있는데, 이 부분은opencv에서 정보를 compact한 방식으로 압축하여 사용하기 때문이며 다음과 같이 4개의 값을 만들면 되는 것으로 소개됩니다.
- \[\text{rvec} = (a, b, c)\]
- \[\text{Rotation Angle : } \theta = \sqrt{a^{2} + b^{2} + c^{2}}\]
- \[\text{Rotation Axis : } v = (\frac{a}{\theta}, \frac{b}{\theta}, \frac{c}{\theta})\]
- 그러면 각각 3개의 원소를 가지는
rvec과tvec을 이용하여 어떻게 \(R \vert t\) 행렬을 만드는 지 살펴보도록 하겠습니다. - 먼저 실제 사용하는
OpenCV함수를 사용하여 로드리게스 회전을 구하려면cv2.Rodrigues를 사용하면 됩니다.
rvec
# array([[-0.18105588],
# [-0.12723858],
# [-1.53333626]])
tvec
# array([[-34.65648128],
# [ 4.21510712],
# [215.64322146]])
R, _ = cv2.Rodrigues(rvec)
# [[ 0.03493564 0.99890668 0.0310637 ]
# [-0.98012378 0.02817188 0.1963765 ]
# [ 0.19528667 -0.03730682 0.98003639]]
Rt = np.identity(4)
Rt[:3, :3] = R
Rt[:3, 3] = tvec.reshape(-1)
# [[ 0.03493564 0.99890668 0.0310637 -34.65648128]
# [ -0.98012378 0.02817188 0.1963765 4.21510712]
# [ 0.19528667 -0.03730682 0.98003639 215.64322146]
# [ 0. 0. 0. 1. ]]
- 위의
cv2.Rodrigues()함수는opencv에서 정의한rvec형식을 따릅니다. 그러면 실제opencv의 값과 계산기를 통해 구한 값이 같은 지 살펴보도록 하겠습니다. 계산기는 3D Rotation Converter를 사용하였습니다.
rvec
# array([[-0.18105588],
# [-0.12723858],
# [-1.53333626]])
theta = np.linalg.norm(rvec)
# 1.5492227001175765
v = rvec / theta
# [[-0.11686885]
# [-0.08213059]
# [-0.98974554]]

- 위 이미지의 빨간색 박스 위주로 보면 앞에서 구한
Axis와Angle을 통해Rotation Matrix를 구한 것이cv2.Rodrigues함수와 같은 결과임을 알 수 있습니다.
기타 참조 내용
- python에서 opencv를 사용 중에
cannot import name '_registerMatType' from 'cv2.cv2'와 같은 에러가 발생하는 경우opencv-python-headless를 설치하면 됩니다. head가 생겨서 2중으로 구성되어 (ex. cv2.cv2) 발생한 오류입니다. 아래 버전으로 install 하시면 문제를 해결할 수 있습니다.- 설치 :
pip install opencv-python-headless==4.1.2.30
- 설치 :