文章目录
- 概述
- 相机畸变类型
- 径向畸变
- 切向畸变
- 畸变数学模型
- 径向畸变模型
- 切向畸变模型
- 畸变数学模型总结
- 去畸变数学过程
- 去畸变步骤
- 畸变测试
- 结论
- 参考
概述
相机畸变是图像处理和计算机视觉中的常见问题。由于透镜的物理特性,图像边缘的物体往往会呈现扭曲,这种现象称为畸变。畸变主要分为两种类型:径向畸变和切向畸变。本文档将详细介绍相机畸变的数学模型、产生原因、以及去畸变的数学过程。
相机畸变类型
径向畸变
径向畸变是由于透镜形状不规则引起的,导致光线在远离透镜中心的地方比靠近中心的地方更加弯曲。这种畸变通常表现为枕形畸变(中间凹陷)或桶形畸变(中间凸起)。径向畸变的数学模型可以用泰勒级数展开式的前几项来描述,通常使用前两项和,即 k 1 k_1 k1 和 k 2 k_2 k2,对于畸变很大的镜头,如鱼眼镜头,可能需要增加第三项 k 3 k_3 k3 来进行描述。
切向畸变
切向畸变是由于透镜不完全平行于图像平面引起的,通常是由于透镜安装时的偏差导致的。这种畸变可以通过两个额外的参数
p
1
p_1
p1 和
p
2
p_2
p2 来描述。
畸变数学模型
径向畸变模型
对于成像仪上的某点,根据其在径向方向上的分布位置,畸变后的坐标 ( x ^ , y ^ ) (\hat{x}, \hat{y}) (x^,y^) 可以通过以下公式调节:
x ^ = x ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) \hat{x} = x(1 + k_1r^2 + k_2r^4 + k_3r^6) x^=x(1+k1r2+k2r4+k3r6)
y ^ = y ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) \hat{y} = y(1 + k_1r^2 + k_2r^4 + k_3r^6) y^=y(1+k1r2+k2r4+k3r6)
其中, ( x , y ) (x, y) (x,y) 是无畸变的归一化图像坐标, r r r 是图像像素点到图像中心点的距离,计算公式为 r 2 = x 2 + y 2 r^2 = x^2 + y^2 r2=x2+y2。
切向畸变模型
切向畸变的影响可以通过以下公式描述:
x ^ = x + 2 p 1 x y + p 2 ( r 2 + 2 x 2 ) \hat{x} = x + 2p_1xy + p_2(r^2 + 2x^2) x^=x+2p1xy+p2(r2+2x2)
y ^ = y + 2 p 2 x y + p 1 ( r 2 + 2 y 2 ) \hat{y} = y + 2p_2xy + p_1(r^2 + 2y^2) y^=y+2p2xy+p1(r2+2y2)
畸变数学模型总结
综合径向畸变和切向畸变,我们可以得到总体畸变模型:
x ^ = x ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) + 2 p 1 x y + p 2 ( r 2 + 2 x 2 ) \hat{x} = x(1 + k_1r^2 + k_2r^4 + k_3r^6) + 2p_1xy + p_2(r^2 + 2x^2) x^=x(1+k1r2+k2r4+k3r6)+2p1xy+p2(r2+2x2)
y ^ = y ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) + 2 p 2 x y + p 1 ( r 2 + 2 y 2 ) \hat{y} = y(1 + k_1r^2 + k_2r^4 + k_3r^6) + 2p_2xy + p_1(r^2 + 2y^2) y^=y(1+k1r2+k2r4+k3r6)+2p2xy+p1(r2+2y2)
去畸变数学过程
去畸变的过程实际上是对上述畸变模型的逆过程。首先,我们需要从畸变图像中恢复出无畸变的归一化图像坐标 ( x , y ) (x, y) (x,y),然后通过相机的内参矩阵将这些坐标转换为像素坐标。
去畸变步骤
- 确定畸变参数:通过相机标定过程获得的畸变参数 k 1 , k 2 , k 3 , p 1 , p 2 k_1, k_2, k_3, p_1, p_2 k1,k2,k3,p1,p2。
- 归一化坐标:将像素坐标转换为归一化图像坐标。
- 逆畸变计算:使用畸变参数和归一化坐标,通过逆畸变模型计算出无畸变的归一化坐标。
- 像素坐标转换:将无畸变的归一化坐标通过相机内参矩阵转换回像素坐标。
畸变测试
TEST(TestDistortion, AddDistortion)
{
cv::Mat white_image = cv::Mat::ones(500, 500, CV_8UC1) * 255;
// cv::Mat white_image = cv::imread("/home/xx/Pictures/house.jpeg", cv::IMREAD_GRAYSCALE);
cv::Mat image = white_image;
// make grid on white image
for (int i = 0; i < 500; i += 50)
{
cv::line(white_image, cv::Point(0, i), cv::Point(500, i), cv::Scalar(0, 0, 0), 1);
cv::line(white_image, cv::Point(i, 0), cv::Point(i, 500), cv::Scalar(0, 0, 0), 1);
}
cv::Mat distorted_image = cv::Mat::zeros(image.size(), image.type());
float cx = 0.0f;
float cy = 0.0f;
// 径向畸变参数 radial distortion
float k1 = 0.0;
float k2 = 0.0;
// 切向畸变参数 Tangential distortion
float p1 = -0.1;
float p2 = 0.0;
for (int row = 0; row < image.rows; row++)
{
for (int col = 0; col < image.cols; col++)
{
float x = (col - image.cols / 2.0f) / (float)image.cols;
float y = (row - image.rows / 2.0f) / (float)image.rows;
float rho = sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));
float rho2 = rho * rho;
float rho4 = rho2 * rho2;
float x_distortion = (1 + k1 * rho2 + k2 * rho4) * x + 2 * p1 * x * y + p2 * (rho2 + 2 * x * x);
float y_distortion = (1 + k1 * rho2 + k2 * rho4) * y + 2 * p2 * x * y + p1 * (rho2 + 2 * y * y);
int u = x_distortion * image.cols + image.cols / 2.0f;
int v = y_distortion * image.rows + image.rows / 2.0f;
// std::cout<<"x_distortion: "<<x_distortion<<" y_distortion: "<<y_distortion<<std::endl;
// std::cout << "u: " << u << " v: " << v << std::endl;
if (u >= 0 && u < image.cols && v >= 0 && v < image.rows)
{
distorted_image.ptr<uchar>(row)[col] = image.ptr<uchar>(v)[u];
}
else
{
distorted_image.ptr<uchar>(row)[col] = 0;
}
}
}
cv::imshow("image", image);
cv::imshow("distorted_image", distorted_image);
cv::waitKey(0);
}
请自行调整
k
1
,
k
2
,
p
1
,
p
2
k_1,k_2,p_1,p_2
k1,k2,p1,p2查看不同的畸变效果。
实例:
// 径向畸变参数 radial distortion
float k1 = 0.7;
float k2 = 0.3;
// 切向畸变参数 Tangential distortion
float p1 = -0.1;
float p2 = 0.0;
结论
相机畸变模型是理解和校正图像畸变的基础。通过掌握畸变的数学模型和去畸变过程,我们可以有效地矫正图像中的畸变,提高图像处理和计算机视觉任务的准确性。在实际应用中,如相机标定、三维重建、机器视觉等领域,去畸变技术都是不可或缺的一环。
参考
- https://www.qinxing.xyz/posts/b7ea425d/
- https://zhaoxuhui.top/blog/2018/04/17/CameraCalibration.html