“PnP” 是计算机视觉和三维重建中非常常见的术语。 它的全称是 Perspective-n-Point 问题

🎯 一句话解释

PnP(Perspective-n-Point)问题: 已知若干个三维点在世界坐标系中的位置,以及它们在图像中的对应像素坐标, 求出相机的姿态(位置和朝向)

📸 更正式的定义

在计算机视觉中,PnP 问题可以描述为:

给定:

  • 一组 3D 点 ( { P_i } ),在世界坐标系中;
  • 对应的 2D 投影点 ( { p_i } ),在图像平面上;
  • 相机的内参矩阵 ( K )(焦距、主点等);

求:

  • 相机的旋转矩阵 ( R ) 和平移向量 ( t ), 使得: [ s \cdot p_i = K [R|t] P_i ] 其中 ( s ) 是尺度因子。

🧮 举个例子

假设你知道:

世界坐标 (X, Y, Z)图像坐标 (u, v)
(0, 0, 0)(340, 220)
(1, 0, 0)(400, 220)
(0, 1, 0)(340, 280)

如果你知道相机的焦距等参数,就可以通过求解 PnP 来算出相机在世界坐标中的:

  • 位置 (x, y, z)
  • 姿态(朝向,rotation matrix)

🧠 名称含义:为什么叫 “Perspective-n-Point”

  • “Perspective” → 透视投影模型(相机遵循透视几何)
  • “n-Point” → 表示有 n 个已知的 3D–2D 对应点

特殊情况:

| 算法名称 | 点数 | 特点 | | — | | - | | P3P | n=3 | 最小可解情况(三点即可) | | EPnP | n≥4 | 常用的高效解法(Efficient PnP) | | UPnP | n≥4 | 通用解法(用于无噪声/有噪声) |

🔧 实际应用场景

PnP 是很多计算机视觉、机器人和 AR 任务的核心步骤,例如:

场景作用
相机位姿估计从已知特征点重建相机位置和姿态
AR(增强现实)把虚拟物体正确叠加到真实相机画面
SLAM / VIO通过匹配特征点,估计当前帧的相机位姿
机器人定位已知环境 3D 特征点 → 求出相机在环境中的位置
标定工具OpenCV 的 solvePnP() 就是标准实现

🧰 在 OpenCV 中的函数示例

import cv2
import numpy as np
 
# 3D 世界坐标
object_points = np.array([
    [0, 0, 0],
    [1, 0, 0],
    [0, 1, 0],
    [1, 1, 0]
], dtype=np.float32)
 
# 对应的 2D 图像坐标
image_points = np.array([
    [320, 240],
    [400, 240],
    [320, 320],
    [400, 320]
], dtype=np.float32)
 
# 已知相机内参矩阵
camera_matrix = np.array([
    [800, 0, 320],
    [0, 800, 240],
    [0, 0, 1]
], dtype=np.float32)
 
# 假设无畸变
dist_coeffs = np.zeros(5)
 
# 求解相机位姿
success, rvec, tvec = cv2.solvePnP(object_points, image_points, camera_matrix, dist_coeffs)

输出的:

  • rvec:旋转向量(Rodrigues 形式)
  • tvec:平移向量

🧩 与其他相关概念对比

概念功能区别
PnP由 3D–2D 对应求相机位姿需要已知 3D 点坐标
Triangulation(三角测量)由多视图的 2D 点求 3D 点坐标需要已知相机位姿
PnP + TriangulationSLAM / SfM 的核心循环互相交替求解相机和点的位置

✅ 总结一句话

PnP = 已知点 → 求相机位姿 (相机“看着”世界上哪些点 → 反推自己在哪里)

三角测量 = 已知相机 → 求点位置 两者是一对互补的几何问题。

如果你想,我可以画一张图展示 🔹 世界中的 3D 点、 🔹 相机成像平面、 🔹 以及 PnP 如何求出相机姿态。 要我画那张透视几何图吗?