You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于OpenCV从畸变/无畸变图像求解投影仪畸变系数的技术问询

投影仪畸变系数求解问题

我存在概念理解上的困惑,现说明我的条件与需求:

  • 拥有两张模拟图像:一张畸变图像,一张无畸变图像(可为棋盘格或任意图像)
  • 实际场景为投影仪(非相机),任务是使用OpenCV计算畸变系数

目前尝试的方法全部失败,我认为原因在于常规相机校准需要多组不同姿态的平面图像,教程式的自动方法在此场景下不适用。

我猜测无需求解相机矩阵(可直接使用Unity生成的矩阵),仅需获取畸变系数、旋转向量(rvecs)和平移向量(tvecs)。我多次尝试相机校准,将畸变图像视为z=0的虚拟物体,但得到的结果误差极大。

单独获取rvecs和tvecs不成问题,通过透视变换即可实现且效果良好。但是否存在半自动方法,仅从这两张图像中求解畸变系数?常规相机校准完全行不通。


问题复现代码

我编写了如下代码来体现问题:手动畸变/去畸变功能正常(多数参数设为0以简化),但相机校准结果完全错误。是否存在OpenCV中我尚未发现的可用函数?

#%%

import numpy as np
import cv2
import matplotlib.pyplot as plt

# 桶形畸变对应负径向位移,枕形畸变对应正径向位移

# 畸变系数
k1 = -3e-2  
k2 = -5e-4 
p1 = 0e-4  
p2 = 0e-2  
k3 = 0e-12
k4 = 0e-5
k5 = 0e-9
k6 = 0e-14
s1 = 0e-3
s2 = 0e-7
s3 = 0e-3
s4 = 0e-7
tx = 0e-1
ty = 0e-3


dist = np.array([k1, k2, p1, p2, k3, k4, k5, k6, s1, s2, s3, s4, tx, ty], dtype = "float32")


# 生成网格状物体点
grid_size, square_size = [20, 20], 0.2
object_points = np.zeros([grid_size[0] * grid_size[1], 3], dtype="float32")
mx, my = [(grid_size[0] - 1) * square_size / 2, (grid_size[1] - 1) * square_size / 2]
for i in range(grid_size[0]):
    for j in range(grid_size[1]):
        object_points[i * grid_size[0] + j] = [i * square_size - mx, j * square_size - my, 0]

# 绘制原始物体点
plt.scatter(object_points[:, 0], object_points[:, 1])
plt.title("原始物体点(物体平面)")
plt.axis('equal')
plt.xlim((-4, 4))
plt.ylim((-4, 4))
plt.grid()
plt.show()

# 设置相机参数
fx=2.
fy=2.
cx= 0.
cy= 0.
alpha = 0   # 倾斜因子,用于修正坐标系切变
mtx = np.array([[fx, alpha, cx], [0, fy, cy], [0, 0, 1]])
rvec = np.array([0.0, 0.0, 0.0])
tvec = np.array([0.0, 0.0, 0.0])


# 对物体点添加畸变,结果在图像平面上
image_points, jacobian = cv2.projectPoints(object_points, rvec, tvec, mtx, dist)

# 绘制畸变后的图像点
plt.scatter(*zip(*image_points[:, 0, :]))
plt.title("畸变后点(图像平面)")
plt.axis('equal')
plt.xlim((-4, 4))
plt.ylim((-4, 4))
plt.grid()
plt.show()



# 用已知相机矩阵和畸变系数去畸变,功能正常
undistpoints= cv2.undistortPoints(src= image_points , cameraMatrix= mtx, distCoeffs=dist)

# 绘制去畸变后的点
plt.scatter(*zip(*undistpoints[:, 0, :]))
plt.title("去畸变后点(物体平面)")
plt.axis('equal')
plt.xlim((-4, 4))
plt.ylim((-4, 4))
plt.grid()
plt.show()

objp =[object_points]
imp= [undistpoints]
retval, cameraMatrix, distCoeffs, rvecs, tvecs = cv2.calibrateCamera(objectPoints=objp, imagePoints=imp, imageSize=(100,100), cameraMatrix= None, distCoeffs= None)

print("相机矩阵:")
print(cameraMatrix)
print("畸变系数:")
print(distCoeffs)
print("旋转向量:")
print(rvecs)
print("平移向量:")
print(tvecs)

内容的提问来源于stack exchange,提问作者Philipp Enöckl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 13:07:03