Verwenden Sie die OpenCV-Funktion solvepnp(), um das PnP-Problem zu lösen

Manav Narula 15 Februar 2024
  1. Verstehe das PnP-Problem
  2. Verwenden Sie die Funktion opencv.solvepnp(), um das PnP-Problem zu lösen
  3. Fazit
Verwenden Sie die OpenCV-Funktion solvepnp(), um das PnP-Problem zu lösen

Die OpenCV-Bibliothek ist eine Open-Source-Bibliothek, die entwickelt wurde, um bei Computer-Vision-Aufgaben zu helfen. Diese Bibliothek ist mit Python kompatibel und kann verwendet werden, um verschiedene Bildverarbeitungsprobleme zu implementieren und zu lösen.

Dieses Tutorial demonstriert die Verwendung der Funktion solvepnp() aus der OpenCV-Bibliothek in Python. Diese Funktion wird verwendet, um das Posenschätzungsproblem zu lösen.

Verstehe das PnP-Problem

Das PnP-Problem ist in der Computer Vision sehr verbreitet und steht für das Perspective n-Points Problem. In dieser Ausgabe können wir die Pose eines Objekts in Bezug auf die Kamera nicht bestimmen, nachdem wir die 2D- und 3D-Koordinaten erhalten haben.

Dies lässt sich am Beispiel des Face-Trackings während einer Online-Prüfung nachvollziehen. Die Pose eines Objekts in Bezug kann sich mit der Richtungsänderung ändern.

Die folgenden zwei Arten von Bewegungen erleichtern diese Änderung:

  1. Die erste Bewegungsart ist die Translationsbewegung, die entlang jeder der drei Achsen erfolgen kann. Das Objekt bewegt sich in einer gleichförmigen Bewegung in eine bestimmte Richtung und ändert dadurch seine Koordinaten.
  2. Die zweite Bewegungsart ist die Rotationsbewegung, bei der sich das Objekt um jede der drei Achsen drehen kann.

Verwenden Sie die Funktion opencv.solvepnp(), um das PnP-Problem zu lösen

Die Funktion solvepnp() aus der OpenCV-Bibliothek wird zur Posenschätzung eines bestimmten Objekts in Bezug auf die Kamera verwendet und löst so das PnP-Problem. Es gibt Rotations- und Translationsvektoren zurück.

Es verwendet die 2D- und 3D-Koordinaten des Objekts mit der Kameramatrix. Die gelieferten Koordinaten beziehen sich auf die verschiedenen Merkmale des Gesichts.

Diese Merkmale sind die Nase, die Mundwinkel, das Kinn und beide Augen.

Lassen Sie uns alle Parameter besprechen, die für die Verwendung dieser Funktion erforderlich sind.

  1. Der Parameter objectPoints nimmt die 3D-Punkte aller zuvor erwähnten Features.
  2. Mit dem Parameter imagePoints werden die 2D-Punkte der Merkmale des Objekts angegeben.
  3. Mit der cameraMatrix wird der innere Wert der Kamera angegeben. Diese Matrix wird unter Verwendung des Mittelpunkts und der Brennweite der Kamera erstellt.
  4. Um die von der Kamera verursachte Verzerrung zu beseitigen, verwenden wir den Parameter distCoeffs. Dieser Vektor kann NULL sein, wenn es eine vernachlässigbare Verzerrung in der Kamera gibt.
  5. Wir können das Ausgabeergebnis für erste Berechnungen verwenden, indem wir den Parameter useExtrinsicGuess verwenden, der wahr oder falsch sein kann. Ansonsten gibt es nur den Parameter flags.

Die von dieser Funktion zurückgegebenen Rotations- und Translationsvektoren können verwendet werden, um die Linie für die Pose des Objekts zu zeichnen.

Zum Beispiel bestimmen wir die Pose des folgenden Bildes.

Beispielbild zur Bestimmung der Pose

Der Code zur Bestimmung der Pose für dieses Bild ist unten dargestellt.

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()

Ausgabe:

Pose bestimmt mit solvepnp

In dem oben erwähnten Code passiert eine Menge. Lass es uns Schritt für Schritt verstehen.

Zuerst lesen wir das gewünschte Bild mit der Funktion imread(). Die Punkte für die Gesichtszüge werden in 2D und 3D genannt.

Die Punkte und die Kameramatrix werden der Funktion solvepnp() zur Verfügung gestellt, die die Rotations- und Translationsvektoren für die 3D-Koordinaten der Pose zurückgibt.

Nachdem wir die Linie für die Pose visuell gezeichnet haben. Zuerst zeichnen wir die Gesichtszüge auf.

Wir verwenden die 2D-Punkte und zeichnen jeden Punkt mit der Funktion circle().

projectPoints() wird verwendet, um die Projektion der von der solvepnp()-Funktion zurückgegebenen Vektoren auf die Bildebene zu bestimmen. Wir müssen auch den Kameraparameter in dieser Funktion übergeben, um die Projektion zu erhalten.

Wir zeichnen eine Linie von der Nase des Gesichts entlang der projizierten Punkte mit der Funktion line(), um die durch die Methode solvepnp() bestimmte Pose zu visualisieren.

Fazit

Dieses Tutorial hat uns beigebracht, wie man die Funktion solvepnp() verwendet, um das PnP-Problem in Computer Vision zu lösen. Wir müssen die Parameter kennen, die für die Verwendung dieser Methode erforderlich sind.

Die Hauptparameter sind die 2D- und 3D-Punkte der Gesichtszüge des Bildes und der Kameramatrix. Unter Verwendung dieser Werte gibt es die Vektoren zurück, die die 3D-Punkte der Pose bestimmen.

Mit der Funktion projectPoints() erhalten wir eine Projektion dieser Punkte in 2D in Bezug auf die Kamera. Schließlich zeichnen wir mit diesen Punkten eine Linie, um die ermittelte Pose im Bild darzustellen.

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

Verwandter Artikel - Python OpenCV