opencv 鱼眼相机模型原理及去畸变方法
1. 官方文档地址
[官方文档地址点击这里](OpenCV: Fisheye camera model)
2. 命名空间
cv::fisheye
3. 详细描述鱼眼模型
设
P
P
P为世界参照系中坐标
X
X
X的三维点(存储在矩阵
X
X
X中)。摄像机参照系中
P
P
P的坐标向量为:
X
c
=
R
X
+
T
Xc=RX+T
Xc=RX+T
其中
R
R
R为旋转向量
o
r
or
or对应的旋转矩阵(
T
T
T为平移矩阵):
R
=
r
o
d
r
i
g
u
e
s
(
o
m
)
R = rodrigues(om)
R=rodrigues(om);称
x
,
y
,
z
x, y, z
x,y,z为
X
c
Xc
Xc的3个坐标:
x
=
X
c
1
y
=
X
c
2
z
=
X
c
3
x=Xc_1\\ y=Xc_2\\ z=Xc_3\\
x=Xc1y=Xc2z=Xc3
P
P
P的针孔投影坐标(归一化坐标)为
[
a
;
b
]
[a;b]
[a;b]:
a
=
x
/
z
b
=
y
/
z
r
2
=
a
2
+
b
2
θ
=
a
t
a
n
(
r
)
a=x/z \\ b=y/z \\ r^2= a^2+b^2 \\ \theta=atan(r)
a=x/zb=y/zr2=a2+b2θ=atan(r)
鱼眼畸变:
θ
d
=
θ
(
1
+
k
1
θ
2
+
k
2
θ
4
+
k
3
θ
6
+
k
4
θ
8
)
\theta_d=\theta(1+k_1\theta^2+k_2\theta^4+k_3\theta^6+k_4\theta^8)
θd=θ(1+k1θ2+k2θ4+k3θ6+k4θ8)
畸变点坐标为
[
x
′
;
y
′
]
[x';y']
[x′;y′]
x
′
=
(
θ
d
/
r
)
a
y
′
=
(
θ
d
/
r
)
b
x'=(\theta_d/r)a\\ y'=(\theta_d/r)b
x′=(θd/r)ay′=(θd/r)b
最后转换成像素坐标(重投影):最终像素坐标向量
[
u
;
v
]
[u;v]
[u;v]:
u
=
f
x
(
x
′
+
α
y
′
)
+
c
x
v
=
f
y
y
′
+
c
y
u=f_x(x'+\alpha y')+c_x \\ v=f_y y'+c_y
u=fx(x′+αy′)+cxv=fyy′+cy
最后再最近邻插值即可去畸变。
4. 代码
#include <opencv2/opencv.hpp>
// 文件路径,如果不对,请调整
std::string input_file = "../fisheye.jpg";
int main(int argc, char **argv) {
// 本程序实现鱼眼的等距投影去畸变模型
// 畸变参数(本例设为零)
double k1 = 0, k2 = 0, k3 = 0, k4 = 0;
// 内参
double fx = 689.21, fy = 690.48, cx = 1295.56, cy = 942.17;
cv::Mat image = cv::imread(input_file);
int rows = image.rows, cols = image.cols;
cv::Mat image_undistort = cv::Mat(rows, cols, CV_8UC3); // 去畸变以后的图
// 计算去畸变后图像的内容
for (int v = 0; v < rows; v++)
for (int u = 0; u < cols; u++) {
double u_distorted = 0, v_distorted = 0;
// 按照公式,计算点(u,v)对应到畸变图像中的坐标(u_distorted,v_distorted) (~6 lines)
// start your code here
//归一化平面
double x = (u - cx)/fx;
double y = (v - cy)/fy;
//引入畸变
double r = sqrt(x*x + y*y);
double theta = atan(r);
double theta_d = theta + k1*pow(theta, 3) + k2*pow(theta, 5) + k3*pow(theta, 7) + k4*pow(theta, 9);
double x_distorted = theta_d*x/r;
double y_distorted = theta_d*y/r;
//重新投影到像素坐标
u_distorted = (0.01*y_distorted+x_distorted)*fx + cx;
v_distorted = y_distorted*fy + cy;
// end your code here
// 赋值 (最近邻插值)去畸变
if (u_distorted >= 0 && v_distorted >= 0 && u_distorted < cols &&
v_distorted < rows) {
image_undistort.at<cv::Vec3b>(v, u) =
image.at<cv::Vec3b>((int)v_distorted, (int)u_distorted);
} else {
image_undistort.at<cv::Vec3b>(v, u) = 0;
}
}
// 画图去畸变后图像
cv::imshow("image undistorted", image_undistort);
cv::imwrite("fisheye_undist.jpg", image_undistort);
cv::waitKey();
return 0;
}
5.其它
其它的鱼眼模型的函数等请见opencv官方文档。