Like Share Discussion Bookmark Smile

J.J. Huang   2026-02-09   Python OpenCV 05.特徵與進階篇   瀏覽次數:次   DMCA.com Protection Status

Python | OpenCV 相機校正與畸變矯正

📚 前言

在前一篇我們學會了 透視變換與圖片校正
這一篇要介紹 相機校正 (Camera Calibration)畸變矯正 (Distortion Correction)
相機鏡頭常會造成桶狀或枕狀畸變,導致圖片變形。透過校正,我們能得到更精準的圖片,這在 AR、3D 重建、工業檢測 等應用中非常重要。

🎨 範例圖片

這裡我們使用 GitHub 專案 tarkers/Camera_Calibration_OpenCV 提供的棋盤格圖片。
下載 Test 資料夾,裡面有多張棋盤格照片,非常適合用來做校正。

🔎 原理說明

  • 棋盤格:我們用棋盤格當作「標準尺」,因為它的格子大小固定。
  • 流程
    1. 拍或下載多張棋盤格照片。
    2. 找出棋盤格角落。
    3. 用這些角落去計算相機的「內部參數」和「畸變係數」。
    4. 用這些參數去修正照片。

🧠 函式與參數說明

📌 cv2.findChessboardCorners()

用途:偵測棋盤格圖片中的角點位置,作為相機校正的基礎資料。

1
ret, corners = cv2.findChessboardCorners(image, patternSize)
  • image:輸入圖片 (灰階)。
  • patternSize:棋盤格內角點數量,例如 (9,6)。
  • ret:是否成功找到角點。
  • corners:角點座標。

📌 cv2.calibrateCamera()

用途:利用多張棋盤格圖片的角點,計算相機的內部參數與畸變係數。

1
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, imageSize, None, None)
  • objpoints:棋盤格的 3D 座標。
  • imgpoints:圖片中的 2D 座標。
  • imageSize:圖片大小。
  • mtx:相機矩陣 (焦距、主點位置)。
  • dist:畸變係數。
  • rvecs, tvecs:旋轉與平移向量。

📌 cv2.undistort()

用途:利用校正得到的相機矩陣與畸變係數,修正圖片的變形。

1
dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
  • img:輸入圖片。
  • mtx:相機矩陣。
  • dist:畸變係數。
  • newcameramtx:優化後的相機矩陣。
  • dst:輸出矯正後的圖片。

💻 範例程式 — 相機校正

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import cv2
import numpy as np
import glob

# 棋盤格大小 (內角點數量)
chessboard_size = (9, 6)

# 建立棋盤格的 3D 座標
objp = np.zeros((np.prod(chessboard_size), 3), np.float32)
objp[:,:2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1,2)

objpoints = [] # 3D 點
imgpoints = [] # 2D 點

images = glob.glob("Test/*.jpg")

for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None)
if ret:
objpoints.append(objp)
imgpoints.append(corners)

cv2.drawChessboardCorners(img, chessboard_size, corners, ret)
cv2.imshow("Corners", img)
cv2.waitKey(500)

cv2.destroyAllWindows()

# 相機校正
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

print("Camera Matrix:\n", mtx)
print("Distortion Coefficients:\n", dist)

輸出:

1
2
3
4
5
6
7
Camera Matrix:
[[532.35423658 0. 342.42264659]
[ 0. 532.53995406 235.04228201]
[ 0. 0. 1. ]]
Distortion Coefficients:
[[-2.73462172e-01 -3.85288349e-02 1.12629584e-03 -1.75411180e-04
2.85170396e-01]]


圖:程式碼執行結果 — 取得相機矩陣與畸變係數

💻 範例程式 — 畸變矯正

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import cv2
import numpy as np

# 手動輸入相機矩陣 (mtx)
mtx = np.array([[532.35423658, 0. , 342.42264659],
[ 0. , 532.53995406, 235.04228201],
[ 0. , 0. , 1. ]])

# 手動輸入畸變係數 (dist)
dist = np.array([[-2.73462172e-01, -3.85288349e-02,
1.12629584e-03, -1.75411180e-04,
2.85170396e-01]])

# 讀取一張測試圖片
img = cv2.imread("Test/left01.jpg")
h, w = img.shape[:2]

# 計算最佳相機矩陣
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))

# 矯正圖片
dst = cv2.undistort(img, mtx, dist, None, newcameramtx)

# 裁切 ROI (避免黑邊)
x, y, w, h = roi
dst = dst[y:y+h, x:x+w]

cv2.imshow("Original", img)
cv2.imshow("Undistorted", dst)
cv2.waitKey(0)
cv2.destroyAllWindows()


圖:程式碼執行結果 — 修正鏡頭畸變後的圖片

⚠️ 注意事項

  • 校正需要 多張棋盤格圖片,角度與距離要多樣化。
  • 畸變矯正後可能需要裁切 ROI,避免黑邊。
  • 相機校正結果依鏡頭與拍攝環境而異。

📊 應用場景

  • AR/VR:提升圖片精準度。
  • 工業檢測:避免因畸變造成測量誤差。
  • 3D 重建:確保投影模型正確。
  • 攝影應用:修正廣角鏡頭的桶狀畸變。

🎯 結語

本篇我們學會了 相機校正與畸變矯正,並理解了如何利用棋盤格圖片計算相機矩陣與畸變係數,最後使用 cv2.undistort() 修正圖片。
這是電腦視覺中非常重要的一步,能讓後續的圖片處理與分析更加精準。

📖 如在學習過程中遇到疑問,或是想了解更多相關主題,建議回顧一下 Python | OpenCV 系列導讀,掌握完整的章節目錄,方便快速找到你需要的內容。

註:以上參考了
OpenCV Tutorials
OpenCV-Python Tutorials