###### 问题描述
在使用ScaramuzzaOCamCalib 鱼眼镜头的matlab程序对图像进行标定后,使用标定后参数以及cam2world函数进行反投影,并计算三维坐标系下的天顶角。发现角度超出相机视场范围,不明白是为什么。
###### 棋盘格图片来自官网提供的 190°鱼眼相机拍摄的棋盘格。以下是官网提供给的cam2world函数测试用例
/*
测试用例:
VMRImage0.jpg calib_results.txt
*/
#include"ocam_functions.h"
#include<fstream>
void cam2world_test(double point3D[3], double point2D[2], struct ocam_model *myocam_model)
{
double *pol = myocam_model->pol;
double xc = (myocam_model->xc);
double yc = (myocam_model->yc);
double c = (myocam_model->c);
double d = (myocam_model->d);
double e = (myocam_model->e);
int length_pol = (myocam_model->length_pol);
double invdet = 1 / (c - d * e); // 1/det(A), where A = [c,d;e,1] as in the Matlab file
double xp = invdet * ((point2D[0] - xc) - d * (point2D[1] - yc));
double yp = invdet * (-e * (point2D[0] - xc) + c * (point2D[1] - yc));
double r = sqrt(xp*xp + yp * yp); //distance [pixels] of the point from the image center
double r_temp = r;
double zp = pol[0];
double r_i = 1;
int i;
for (i = 1; i < length_pol; i++)
{
r_i *= r;
zp += r_i * pol[i];
}
//normalize to unit norm
double invnorm = 1 / sqrt(xp*xp + yp * yp + zp * zp);
point3D[0] = invnorm * xp;
point3D[1] = invnorm * yp;
point3D[2] = invnorm * zp;
double z = point3D[2];
double theta = atan(sqrt(point3D[0] * point3D[0] + point3D[1] * point3D[1]) / point3D[2])*90;
//cout << r << "\t" << theta << endl;
//if (r_temp > 290) {
int a = point2D[0];
int b = point2D[1];
ofstream ofs;
ofs.open("test.txt", ios::app); //不指定地址的时候,会把文件和当前cpp文件放在一起
ofs << point2D[0] << "\t" << point2D[1] << "\t" << r << "\t" << theta << endl;
ofs.close();
//}
}
int main() {
struct ocam_model o;
//get_ocam_model(&o, "./calib_results_fisheye.txt");
get_ocam_model(&o, "./calib_results.txt"); //获取标定文件
//IplImage *src1 = cvLoadImage("./undistorted_perspective.jpg");
IplImage *src1 = cvLoadImage("./Fisheye190deg1.jpg");
//IplImage *src1 = cvLoadImage("./VMRImage0.jpg"); //获取图像
CvMat* mapx_persp = cvCreateMat(src1->height, src1->width, CV_32FC1);
int width = mapx_persp->cols; //New width
int height = mapx_persp->rows;//New height //获取像素数
for (int i = 0; i < height; i += 1) {
//for (int j = 0; j < width; j += 10) {
double point2D[2] = { i,375 };
//double point2D[2] = { 0,0 };
double point3D[3] = { 0 ,0 ,0 };
cam2world_test(point3D, point2D, &o);
//}
}
return 0;
}
###### 190°视场的相机,按照 double theta = atan(sqrt(point3D[0] * point3D[0] + point3D[1] * point3D[1]) / point3D[2])*90; 这个方式计算,最终theta值应该在0-95°之间,但我实际计算出来是在0-104°之间。