“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 + Triangulation | SLAM / SfM 的核心循环 | 互相交替求解相机和点的位置 |
✅ 总结一句话
PnP = 已知点 → 求相机位姿 (相机“看着”世界上哪些点 → 反推自己在哪里)
而 三角测量 = 已知相机 → 求点位置 两者是一对互补的几何问题。
如果你想,我可以画一张图展示 🔹 世界中的 3D 点、 🔹 相机成像平面、 🔹 以及 PnP 如何求出相机姿态。 要我画那张透视几何图吗?