OpenCV solvepnp() 함수를 사용하여 PnP 문제 해결

Manav Narula 2023년1월30일
  1. PnP 문제 이해
  2. opencv.solvepnp() 함수를 사용하여 PnP 문제 해결
  3. 결론
OpenCV solvepnp() 함수를 사용하여 PnP 문제 해결

OpenCV 라이브러리는 Computer Vision 작업을 돕기 위해 개발된 오픈 소스 라이브러리입니다. 이 라이브러리는 Python과 호환되며 다양한 이미지 처리 문제를 구현하고 해결하는 데 사용할 수 있습니다.

이 튜토리얼은 Python의 OpenCV 라이브러리에서 solvepnp() 함수를 사용하는 방법을 보여줍니다. 이 함수는 포즈 추정 문제를 해결하는 데 사용됩니다.

PnP 문제 이해

PnP 문제는 Computer Vision에서 매우 일반적이며 Perspective n-Points 문제를 나타냅니다. 이 문제에서는 2D 및 3D 좌표를 제공받은 후 카메라를 기준으로 물체의 포즈를 결정할 수 없습니다.

이것은 온라인 시험 중 얼굴 추적의 예를 통해 이해할 수 있습니다. 존경하는 대상의 자세는 방향의 변화에 ​​따라 변할 수 있습니다.

다음 두 가지 유형의 동작이 이러한 변경을 용이하게 합니다.

  1. 첫 번째 유형의 모션은 병진 모션으로 세 축 중 어느 곳에서나 발생할 수 있습니다. 물체는 특정 방향으로 균일한 움직임으로 이동하여 좌표가 변경됩니다.
  2. 두 번째 유형의 모션은 개체가 세 축 중 하나를 중심으로 회전할 수 있는 회전 모션입니다.

opencv.solvepnp() 함수를 사용하여 PnP 문제 해결

OpenCV 라이브러리의 solvepnp() 함수는 카메라에 대한 주어진 객체의 포즈 추정에 사용되어 PnP 문제를 해결합니다. 회전 및 병진 벡터를 반환합니다.

카메라 매트릭스와 함께 객체의 2D 및 3D 좌표를 사용합니다. 제공된 좌표는 얼굴의 다양한 특징에 대한 것입니다.

이러한 특징은 코, 입가, 턱 및 양쪽 눈입니다.

이 기능을 사용하는 데 필요한 모든 매개변수에 대해 알아보겠습니다.

  1. objectPoints 매개변수는 이전에 언급한 모든 기능의 3D 포인트를 사용합니다.
  2. imagePoints 매개변수는 개체 기능의 2D 포인트를 지정하는 데 사용됩니다.
  3. cameraMatrix는 카메라의 고유 값을 지정하는 데 사용됩니다. 이 매트릭스는 카메라의 중심점과 초점 거리를 사용하여 생성됩니다.
  4. 카메라에서 발생하는 왜곡을 해결하기 위해 distCoeffs 매개변수를 사용합니다. 카메라에 무시할 수 있는 왜곡이 있는 경우 이 벡터는 NULL일 수 있습니다.
  5. 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()

출력:

solvepnp를 사용하여 결정된 포즈

위에서 언급한 코드에서 많은 일이 일어나고 있습니다. 차근차근 이해해보자.

먼저 imread() 함수를 사용하여 필요한 이미지를 읽습니다. 얼굴 특징에 대한 포인트는 2D 및 3D로 언급됩니다.

점과 카메라 행렬은 포즈의 3D 좌표에 대한 회전 및 병진 벡터를 반환하는 solvepnp() 함수에 제공됩니다.

포즈의 선을 시각적으로 그린 ​​후. 먼저 얼굴 특징을 플로팅합니다.

2D 포인트를 사용하고 circle() 함수를 사용하여 각 포인트를 플로팅합니다.

projectPoints()는 이미지 평면에서 solvepnp() 함수에 의해 반환된 벡터의 투영을 결정하는 데 사용됩니다. 투영을 얻으려면 이 함수에서 카메라 매개변수도 전달해야 합니다.

solvepnp() 방법으로 결정된 포즈를 시각화하기 위해 line() 함수를 사용하여 투영된 점과 일치하는 얼굴 코의 선을 그립니다.

결론

이 튜토리얼에서는 solvepnp() 함수를 사용하여 Computer Vision에서 PnP 문제를 해결하는 방법을 배웠습니다. 이 방법을 사용하는 데 필요한 매개변수에 대해 알아야 합니다.

주요 매개변수는 이미지의 얼굴 특징과 카메라 매트릭스의 2D 및 3D 포인트입니다. 이 값을 사용하여 포즈의 3D 포인트를 결정하는 벡터를 반환합니다.

projectPoints() 함수를 사용하여 카메라에 대해 이러한 점을 2D로 투영합니다. 마지막으로 이 점을 사용하여 이미지에서 결정된 포즈를 나타내는 선을 그립니다.

작가: Manav Narula
Manav Narula avatar Manav Narula avatar

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

관련 문장 - Python OpenCV