OpenCV solvepnp() 함수를 사용하여 PnP 문제 해결
OpenCV 라이브러리는 Computer Vision 작업을 돕기 위해 개발된 오픈 소스 라이브러리입니다. 이 라이브러리는 Python과 호환되며 다양한 이미지 처리 문제를 구현하고 해결하는 데 사용할 수 있습니다.
이 튜토리얼은 Python의 OpenCV 라이브러리에서 solvepnp()
함수를 사용하는 방법을 보여줍니다. 이 함수는 포즈 추정 문제를 해결하는 데 사용됩니다.
PnP 문제 이해
PnP 문제는 Computer Vision에서 매우 일반적이며 Perspective n-Points 문제를 나타냅니다. 이 문제에서는 2D 및 3D 좌표를 제공받은 후 카메라를 기준으로 물체의 포즈를 결정할 수 없습니다.
이것은 온라인 시험 중 얼굴 추적의 예를 통해 이해할 수 있습니다. 존경하는 대상의 자세는 방향의 변화에 따라 변할 수 있습니다.
다음 두 가지 유형의 동작이 이러한 변경을 용이하게 합니다.
- 첫 번째 유형의 모션은 병진 모션으로 세 축 중 어느 곳에서나 발생할 수 있습니다. 물체는 특정 방향으로 균일한 움직임으로 이동하여 좌표가 변경됩니다.
- 두 번째 유형의 모션은 개체가 세 축 중 하나를 중심으로 회전할 수 있는 회전 모션입니다.
opencv.solvepnp()
함수를 사용하여 PnP 문제 해결
OpenCV 라이브러리의 solvepnp()
함수는 카메라에 대한 주어진 객체의 포즈 추정에 사용되어 PnP 문제를 해결합니다. 회전 및 병진 벡터를 반환합니다.
카메라 매트릭스와 함께 객체의 2D 및 3D 좌표를 사용합니다. 제공된 좌표는 얼굴의 다양한 특징에 대한 것입니다.
이러한 특징은 코, 입가, 턱 및 양쪽 눈입니다.
이 기능을 사용하는 데 필요한 모든 매개변수에 대해 알아보겠습니다.
objectPoints
매개변수는 이전에 언급한 모든 기능의 3D 포인트를 사용합니다.imagePoints
매개변수는 개체 기능의 2D 포인트를 지정하는 데 사용됩니다.cameraMatrix
는 카메라의 고유 값을 지정하는 데 사용됩니다. 이 매트릭스는 카메라의 중심점과 초점 거리를 사용하여 생성됩니다.- 카메라에서 발생하는 왜곡을 해결하기 위해
distCoeffs
매개변수를 사용합니다. 카메라에 무시할 수 있는 왜곡이 있는 경우 이 벡터는 NULL일 수 있습니다. - true 또는 false일 수 있는
useExtrinsicGuess
매개변수를 사용하여 초기 계산에 대한 출력 결과를 사용할 수 있습니다. 그 외에는flags
매개변수만 있습니다.
이 함수에서 반환된 회전 및 병진 벡터는 개체의 포즈에 대한 선을 그리는 데 사용할 수 있습니다.
예를 들어 다음 이미지의 포즈를 결정합니다.
이 이미지의 포즈를 결정하는 코드는 아래와 같습니다.
import cv2
import numpy as np
img = cv2.imread("img.jpg")
size = img.shape
image_points_2D = np.array(
[
(196, 141), # Nose tip
(190, 202), # Chin
(196, 124), # Left eye corner
(236, 128), # Right eye corner
(186, 175), # Left mouth
(214, 177), # Right mouth
],
dtype="double",
)
figure_points_3D = np.array(
[
(0.0, 0.0, 0.0), # Nose tip
(0.0, -330.0, -65.0), # Chin
(-225.0, 170.0, -135.0), # Left eye left corner
(225.0, 170.0, -135.0), # Right eye right corne
(-150.0, -150.0, -125.0), # Left Mouth corner
(150.0, -150.0, -125.0), # Right mouth corner
]
)
distortion_coeffs = np.zeros((4, 1))
focal_length = size[1]
center = (size[1] / 2, size[0] / 2)
matrix_camera = np.array(
[[focal_length, 0, center[0]], [0, focal_length, center[1]], [0, 0, 1]],
dtype="double",
)
success, vector_rotation, vector_translation = cv2.solvePnP(
figure_points_3D, image_points_2D, matrix_camera, distortion_coeffs, flags=0
)
nose_end_point2D, jacobian = cv2.projectPoints(
np.array([(0.0, 0.0, 1000.0)]),
vector_rotation,
vector_translation,
matrix_camera,
distortion_coeffs,
)
for p in image_points_2D:
cv2.circle(img, (int(p[0]), int(p[1])), 3, (0, 0, 255), -1)
point1 = (int(image_points_2D[0][0]), int(image_points_2D[0][1]))
point2 = (int(nose_end_point2D[0][0][0]), int(nose_end_point2D[0][0][1]))
cv2.line(img, point1, point2, (255, 255, 255), 2)
cv2.imshow("Final", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
출력:
위에서 언급한 코드에서 많은 일이 일어나고 있습니다. 차근차근 이해해보자.
먼저 imread()
함수를 사용하여 필요한 이미지를 읽습니다. 얼굴 특징에 대한 포인트는 2D 및 3D로 언급됩니다.
점과 카메라 행렬은 포즈의 3D 좌표에 대한 회전 및 병진 벡터를 반환하는 solvepnp()
함수에 제공됩니다.
포즈의 선을 시각적으로 그린 후. 먼저 얼굴 특징을 플로팅합니다.
2D 포인트를 사용하고 circle()
함수를 사용하여 각 포인트를 플로팅합니다.
projectPoints()
는 이미지 평면에서 solvepnp()
함수에 의해 반환된 벡터의 투영을 결정하는 데 사용됩니다. 투영을 얻으려면 이 함수에서 카메라 매개변수도 전달해야 합니다.
solvepnp()
방법으로 결정된 포즈를 시각화하기 위해 line()
함수를 사용하여 투영된 점과 일치하는 얼굴 코의 선을 그립니다.
결론
이 튜토리얼에서는 solvepnp()
함수를 사용하여 Computer Vision에서 PnP 문제를 해결하는 방법을 배웠습니다. 이 방법을 사용하는 데 필요한 매개변수에 대해 알아야 합니다.
주요 매개변수는 이미지의 얼굴 특징과 카메라 매트릭스의 2D 및 3D 포인트입니다. 이 값을 사용하여 포즈의 3D 포인트를 결정하는 벡터를 반환합니다.
projectPoints()
함수를 사용하여 카메라에 대해 이러한 점을 2D로 투영합니다. 마지막으로 이 점을 사용하여 이미지에서 결정된 포즈를 나타내는 선을 그립니다.
Manav is a IT Professional who has a lot of experience as a core developer in many live projects. He is an avid learner who enjoys learning new things and sharing his findings whenever possible.
LinkedIn