本文使用的是棋盘格标定法,先使用MATLAB相机标定工具箱获取相机内参,然后通过python代码输出畸变矫正后的图像。
实现:MATLAB R2024a , Pycharm
目录
一、通过MATLAB获取相机内参
我们需要的相机内参有:
(1)径向畸变系数(Radial Distortion):k1、k2、k3
(2)切向畸变系数(Tangential Distortion):p1、p2
(3)焦距(Focal Length):fx、fy
(4)主点(Principal Point):图像中心在x轴上的偏移 cx、cy
1、打开相机标定工具箱
点击下拉箭头后,搜索“camera calibrator”
2、导入拍好的图片,进行矫正
也可以打开相机开拍,但是需要安装USB Webcams包,具体安装方式参考用matlab对相机进行标定获取相机内参_matlab 相机内参 fc-CSDN博客
如果你的MATLAB许可证过期了,没法通过上述博客在线安装时,参考MATLAB的资源管理器中安装资源时弹出“要访问附加功能资源管理器,您的许可证必须在 MathWorks 软件维护有效期内。”的解决办法_要访问附加功能资源管理器,您的许可证必须在 mathworks 软件维护有效期内。-CSDN博客
这里我选择“From file”,导入拍好的照片,推荐拍15-25张图片,可以覆盖大多数情况,保证较好的标定精度。
导入之后弹出如下窗口,填写你的棋盘格网格实际物理尺寸,我放在电脑屏幕上大概27.74mm,然后点确定。
勾选如下参数,选择3阶径向畸变系数,并且计算切向畸变系数,然后点击Calibrate。
下图方框中重投影整体平均误差是0.24,小于0.5就可以用。
3、导出参数
点击后会弹窗,直接点确认即可,然后在工作区就可以看到导出的参数:
打开后,直接双击Intrinsics这个变量,我们需要的内参都在这里。
红框内从上至下依次为:焦距(Focal Length)fx和fy、主点坐标(Principal Point)、径向畸变系数(Radial Distortion)、切向畸变系数(Tangential Distortion)。
至此我们已经获取了相机的内参,下面通过Python代码输出矫正后的图像。
二、通过python实时输出矫正后的视频图像
import cv2
import numpy as np
def undistort_frame(frame, camera_matrix, dist_coeffs):
h, w = frame.shape[:2]
new_camera_matrix, roi = cv2.getOptimalNewCameraMatrix(
camera_matrix, dist_coeffs, (w, h), 1, (w, h)
)
# 去畸变
undistorted = cv2.undistort(frame, camera_matrix, dist_coeffs, None, new_camera_matrix)
# 裁剪图像(保留有效区域)
x, y, w_roi, h_roi = roi
undistorted = undistorted[y:y+h_roi, x:x+w_roi]
return undistorted
# 替换为你从 MATLAB 得到的参数
fx = 255.866501082375 # 焦距x
fy = 259.538529511375 # 焦距y
cx = 309.872526729665 # 图像中心x
cy = 219.880777322666 # 图像中心y
k1 = -0.301755464435774 # 径向畸变第1项
k2 = 0.122351817492402 # 径向畸变第2项
p1 = 0.000510975418145162 # 切向畸变第1项
p2 = -0.000827265079558502 # 切向畸变第2项
k3 = -0.0245909779190259 # 径向畸变第3项
camera_matrix = np.array([[fx, 0, cx],
[0, fy, cy],
[0, 0, 1]])
dist_coeffs = np.array([k1, k2, p1, p2, k3])
# 打开摄像头
cap = cv2.VideoCapture(0) # 如果是默认摄像头,一般是设备索引 0
if not cap.isOpened():
print("无法打开摄像头")
exit()
print("正在显示矫正后的视频画面... 按 'q' 键退出")
while True:
ret, frame = cap.read()
if not ret:
print("无法获取画面")
break
# 矫正图像
corrected_frame = undistort_frame(frame, camera_matrix, dist_coeffs)
# 显示矫正后的画面
cv2.imshow('Undistorted Video', corrected_frame)
# 按 q 键退出
if cv2.waitKey(1) == ord('q'):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()