詳解相機的內參和外參,以及內外參的標定方法

1 四個坐標系

要想深入搞清楚相機的內參和外參含義, 首先得清楚以下4個坐標系的定義:

  • 世界坐標系: 名字看著很唬人, 其實沒什么大不了的, 這個就是你自己定義的某一個坐標系。 比如, 你把房間的某一個點定為原點, 并且定義好方向, 這就是世界坐標系。 一般是個三維坐標系, 單位是m
  • 相機坐標系: 以相機光心為原點, 一般我們把z軸指向相機前方,x向右,y向下,是個三維坐標系, 單位是m
  • 成像平面坐標系: 這個是定義在物理成像平面的坐標系,方向定義與相機坐標系一致(沒有z方向), 原點是光心在物理成像平面上的投影,是個二維坐標系, 單位是m。 注意, 我們一般都會忽略這個坐標系, 因為它是個中間過渡狀態, 很少直接使用它。
  • 像素坐標系: 這個應該是最為常用, 也最為大家熟悉的坐標系, 計算機視覺任務的輸出的坐標表達都是在這個坐標系。 它是個二維坐標系, 原點通常在圖像的左上角, x向右,y向下, 單位是像素, 沒有具體的尺度。
    在這里插入圖片描述

2 內參和外參

除了世界坐標系, 后面三個坐標系只跟相機本身有關。 相機內參表達的就是這三個坐標之間的轉換關系, 而相機外參表達的是相機與世界坐標系之間的轉換關系。

成像的過程實質上是幾個坐標系的轉換。首先空間中的一點由世界坐標系轉換到相機坐標系 ,然后再將其投影到物理成像平面 ( 成像平面坐標系 ) ,最后再將成像平面上的數據轉換像素坐標系 。

在這里插入圖片描述
從世界坐標到像素坐標總共有3步轉換, 前面2個合在一起就是相機內參, 最后一個是相機外參。

上面矩陣中的參數很好理解, 也都有明確的物理含義: a 和b 表示從成像平面坐標轉到像素坐標時, 分別在x和y軸上的縮放系數, u 0 u_0 u0? v 0 v_0 v0?是原點的平移量。 r r r是扭曲因子, 一般為0。 f f f是相機的焦距。 R和T是旋轉和平移矩陣。

把前面2個合一起, 就得到了如下更為常見的內參矩陣:

K = [ f x 0 c x 0 f y c y 0 0 1 ] \mathbf{K} = \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} K= ?fx?00?0fy?0?cx?cy?1? ?
下面的講解中, 我們直接用這種形式,跳過成像平面坐標系。

注意, 實際上內參包含2部分: 內參矩陣K和畸變系數D, 上面只講到了內參矩陣的原理, 沒有講畸變系數。 這里簡單列一下畸變系數, 不做詳細介紹。
D = [k1 k2 p1 p2 k3]
其中 k1、k2、k3 是徑向畸變系數(radial distortion coefficients) p1、p2 是切向畸變系數(tangential distortion coefficients)。

3 常用的坐標轉換

假設有某一個點, 在世界坐標下的坐標為 P w = ( X w , Y w , Z w ) P_w = (X_w, Y_w, Z_w) Pw?=(Xw?,Yw?,Zw?), 在相機坐標系下的坐標為 P = ( X c , Y c , Z c ) P = (X_c, Y_c, Z_c) P=(Xc?,Yc?,Zc?), 在像素坐標系下的坐標為 P u v = ( u , v ) P_{uv} = (u, v) Puv?=(u,v)

  • 世界坐標轉到相機坐標:
    P = R P w + t P = RP_w + t P=RPw?+t

  • 相機坐標轉到像素坐標:
    P u v = 1 Z c K P P_{uv} =\frac 1{Z_c} KP Puv?=Zc?1?KP
    展開就是:
    [ u v 1 ] = 1 Z c K [ X c Y c Z c ] = 1 Z c [ f x 0 c x 0 f y c y 0 0 1 ] [ X c Y c Z c ] \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = \frac 1{Z_c} \mathbf{K} \begin{bmatrix} X_c \\ Y_c \\ Z_c \\ \end{bmatrix} = \frac 1{Z_c} \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} X_c \\ Y_c \\ Z_c \\ \end{bmatrix} ?uv1? ?=Zc?1?K ?Xc?Yc?Zc?? ?=Zc?1? ?fx?00?0fy?0?cx?cy?1? ? ?Xc?Yc?Zc?? ?

  • 像素坐標轉到像素坐標
    這個轉換是最為常用的, 因為我們通常得到的都是像素坐標系下的信息, 如目標檢測、分割的結果就是像素坐標, 得到像素坐標后 ,可以轉為相機坐標, 進一步再轉為世界坐標。另外, 在點云目標檢測中, 通常要把原始的彩色圖像和深度信息轉換為點云, 就需要用到這個轉換。
    P = Z c K ? 1 P u v P = Z_cK^{-1}P_{uv} P=Zc?K?1Puv?
    展開就是:
    X c = u ? c x f x ? Z c X_c = \frac {u-c_x}{f_x}*Z_c Xc?=fx?u?cx???Zc?
    Y c = v ? c y f y ? Z c Y_c = \frac {v-c_y}{f_y}*Z_c Yc?=fy?v?cy???Zc?
    注意上面有個尺度因子 Z c Z_c Zc?, 從相機坐標系的三維坐標投影到像素平面的二維坐標, 實際上丟失了z方向也就是深度信息。 所以如果不知道深度, 從像素坐標就無法恢復出準確的相機坐標。深度通常可以通過深度相機直接測量得到, 或通過深度估計算法預測。

4 內外參標定方法

4.1 內參標定方法

內參標定通常使用張正友標定法, 也就是常見的棋盤格標定。

代碼可參考https://github.com/leo038/hand_eye_calibrate/blob/main/hand_eye_calibrate.py 中的camera_calibrate函數。

4.2 外參標定方法

外參標定的核心是:已知多個點分別在相機坐標系下的坐標和在世界坐標系下的坐標, 求它們之間的映射關系。
常用求解PnP 的方法,即已知多個點, 在像素坐標系的二維坐標, 和在世界坐標系的三維坐標,并且已知內參, 求解旋轉平移矩陣。

cv2 中提供了外參標定方法, cv2.solvePnP 只需提供對應的點對即可。
完整代碼實現如下:

import cv2
import numpy as np# 定義已知的3D空間點和對應的2D圖像點
objectPoints = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype=np.float32)
imagePoints = np.array([[10, 20], [30, 50], [20, 70], [50, 40]], dtype=np.float32)# 定義相機的內參矩陣和畸變系數
cameraMatrix = np.array([[1000, 0, 320], [0, 1000, 240], [0, 0, 1]], dtype=np.float32)
distCoeffs = np.zeros((4, 1), dtype=np.float32)# 使用solvePnP函數求解相機的位姿
ret, rvec, tvec = cv2.solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, flags=cv2.SOLVEPNP_EPNP)if ret:print("Rotation vector:\n", rvec)print("Translation vector:\n", tvec)
else:print("Failed to solve PnP.")res, _ = cv2.Rodrigues(rvec)
print(f"旋轉矩陣: {res}")

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/75812.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/75812.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/75812.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

學透Spring Boot — 011. 一篇文章學會Spring Test

系列文章目錄 這是學透Spring Boot的第11篇文章。更多系列文章請關注 CSDN postnull 用戶的專欄 文章目錄 系列文章目錄Spring Test的依賴Spring Test的核心功能SpringBootTest 加載Spring上下文依賴注入有問題時Spring配置有問題時 WebMvcTest 測試Web層(Controll…

Mysql 數據庫編程技術01

一、數據庫基礎 1.1 認識數據庫 為什么學習數據庫 瞬時數據:比如內存中的數據,是不能永久保存的。持久化數據:比如持久化至數據庫中或者文檔中,能夠長久保存。 數據庫是“按照數據結構來組織、存儲和管理數據的倉庫”。是一個長…

新一代AI架構實踐:數字大腦AI+智能調度MCP+領域執行APP的黃金金字塔體系

新一代AI架構實踐:數字大腦智能調度領域執行的黃金金字塔體系 一、架構本質的三層穿透性認知 1.1 核心范式轉變(CPS理論升級) 傳統算法架構:數據驅動 → 特征工程 → 模型訓練 → 業務應用 新一代AI架構:物理規律建…

macOS可視化桌面配置docker加速器

macOS可視化桌面配置docker加速器 在鏡像settings->docker Engine改為國內鏡像修改為國內鏡像重啟docker(可視化界面啟動或者使用命令行)使用命令重啟可視化界面重啟 在鏡像settings->docker Engine改為國內鏡像 修改為國內鏡像 {"registry-mirrors": ["…

Nginx 基礎使用(2025)

一、Nginx目錄結構 [rootlocalhost ~]# tree /usr/local/nginx /usr/local/nginx ├── client_body_temp # POST 大文件暫存目錄 ├── conf # Nginx所有配置文件的目錄 │ ├── fastcgi.conf # fastcgi相…

用spring-webmvc包實現AI(Deepseek)事件流(SSE)推送

前后端: Spring Boot Angular spring-webmvc-5.2.2包 代碼片段如下: 控制層: GetMapping(value "/realtime/page/ai/sse", produces MediaType.TEXT_EVENT_STREAM_VALUE)ApiOperation(value "獲取告警記錄進行AI分析…

基于Python的招聘推薦數據可視化分析系統

【Python】基于Python的招聘推薦數據可視化分析系統(完整系統源碼開發筆記詳細部署教程)? 目錄 一、項目簡介二、項目界面展示三、項目視頻展示 一、項目簡介 🚀🌟 基于Python的招聘推薦數據可視化分析系統!&#x1…

使用注解開發springMVC

引言 在學習過第一個springMVC項目建造過后&#xff0c;讓我們直接進入真實開發中所必需的注解開發&#xff0c; 是何等的簡潔高效&#xff01;&#xff01; 注&#xff1a;由于Maven可能存在資源過濾的問題&#xff0c;在maven依賴中加入 <build><resources>&l…

linux專題3-----禁止SSH的密碼登錄

要在linux系統中禁止密碼登錄&#xff0c;您可以通過修改 SSH 配置來實現。請按照以下步驟操作(此處以 Ubuntu為例)&#xff1a; 1、SSH 登錄到您的服務器&#xff08;或直接在命令行模式下&#xff09;。 2、備份 SSH 配置文件&#xff1a; 在終端中運行以下命令以備份現有的…

基于LangChain和通義(Tongyi)實現NL2SQL的智能檢索(無需訓練)

在數據驅動的時代,如何高效地從數據庫中獲取信息成為了一個重要的挑戰。自然語言到SQL(NL2SQL)技術提供了一種便捷的解決方案,使用戶能夠用自然語言查詢數據庫,而無需深入了解SQL語法。本文將探討如何利用LangChain和通義(Tongyi)實現NL2SQL的智能檢索,具體步驟如下: …

深度學習處理文本(10)

保存自定義層 在編寫自定義層時&#xff0c;一定要實現get_config()方法&#xff1a;這樣我們可以利用config字典將該層重新實例化&#xff0c;這對保存和加載模型很有用。該方法返回一個Python字典&#xff0c;其中包含用于創建該層的構造函數的參數值。所有Keras層都可以被序…

機器視覺3D中激光偏鏡的優點

機器視覺的3D應用中,激光偏鏡(如偏振片、波片、偏振分束器等)通過其獨特的偏振控制能力,顯著提升了系統的測量精度、抗干擾能力和適應性。以下是其核心優點: 1. 提升3D成像精度 抑制環境光干擾:偏振片可濾除非偏振的環境雜光(如日光、室內照明),僅保留激光偏振信號,大…

線程同步的學習與應用

1.多線程并發 1).多線程并發引例 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <assert.h> #include <pthread.h>int wg0; void *fun(void *arg) {for(int i0;i<1000;i){wg;printf("wg%d\n",wg);} } i…

寫.NET可以指定運行SUB MAIN嗎?調用任意一個里面的類時,如何先執行某段初始化代碼?

VB.NET 寫.NET可以指定運行SUB MAIN嗎?調用任意一個里面的類時,如何先執行某段初始化代碼? 分享 1. 在 VB.NET 中指定運行 Sub Main 在 VB.NET 里&#xff0c;你能夠指定 Sub Main 作為程序的入口點。下面為你介紹兩種實現方式&#xff1a; 方式一&#xff1a;在項目屬性…

【AI插件開發】Notepad++ AI插件開發實踐(代碼篇):從Dock窗口集成到功能菜單實現

一、引言 上篇文章已經在Notepad的插件開發中集成了選中即問AI的功能&#xff0c;這一篇文章將在此基礎上進一步集成&#xff0c;支持AI對話窗口以及常見的代碼功能菜單&#xff1a; 顯示AI的Dock窗口&#xff0c;可以用自然語言向 AI 提問或要求執行任務選中代碼后使用&…

關聯容器-模板類pair數對

關聯容器 關聯容器和順序容器有著根本的不同:關聯容器中的元素是按關鍵字來保存和訪問的,而順序容器中的元素是按它們在容器中的位置來順序保存和訪問的。 關聯容器支持高效的關鍵字查找和訪問。 兩個主要的關聯容器(associative-container),set和map。 set 中每個元素只包…

京東運維面試題及參考答案

目錄 OSPF 實現原理是什么? 請描述 TCP 三次握手的過程。 LVS 的原理是什么? 闡述 Nginx 七層負載均衡的原理。 Nginx 與 Apache 有什么區別? 如何查看監聽在 8080 端口的是哪個進程(可舉例:netstat -tnlp | grep 8080)? OSI 七層模型是什么,請寫出各層的協議。 …

輸入框輸入數字且保持精度

在項目中如果涉及到金額等需要數字輸入且保持精度的情況下&#xff0c;由于輸入框是可以隨意輸入文本的&#xff0c;所以一般情況下可能需要監聽輸入框的change事件&#xff0c;然后通過正則表達式去替換掉不匹配的文本部分。 由于每次文本改變都會被監聽&#xff0c;包括替換…

使用 requests 和 BeautifulSoup 解析淘寶商品

以下將詳細解釋如何通過這兩個庫來實現按關鍵字搜索并解析淘寶商品信息。 一、準備工作 1. 安裝必要的庫 在開始之前&#xff0c;確保已經安裝了 requests 和 BeautifulSoup 庫。如果尚未安裝&#xff0c;可以通過以下命令進行安裝&#xff1a; bash pip install requests…

C#調用ACCESS數據庫,解決“Microsoft.ACE.OLEDB.12.0”未注冊問題

C#調用ACCESS數據庫&#xff0c;解決“Microsoft.ACE.OLEDB.12.0”未注冊問題 解決方法&#xff1a; 1.將C#采用的平臺從AnyCpu改成X64 2.將官網下載的“Microsoft Access 2010 數據庫引擎可再發行程序包AccessDatabaseEngine_X64”文件解壓 3.安裝解壓后的文件 點擊下載安…