📄 cal_main.cpp
字号:
#include "stdafx.h"#include <stdlib.h>#include <stdio.h>#include <iostream>#include <math.h>#include <errno.h>#include "matrix/matrix.h"#include "MINPACK/minpack.h"#include "cal_tran.h"#include "cal_main.h"/* Variables used by the subroutines for I/O (perhaps not the best way of doing this) */struct camera_parameters cp;struct calibration_data cd;struct calibration_constants cc;/* Local working storage */double Xd[MAX_POINTS], Yd[MAX_POINTS], r_squared[MAX_POINTS], U[7];char camera_type[256] = "unknown";/************************************************************************/void initialize_photometrics_parms ()//初始化不同类型的相机参数;{ strcpy (camera_type, "Photometrics Star I"); cp.Ncx = 576; /* [sel] */ cp.Nfx = 576; /* [pix] */ cp.dx = 0.023; /* [mm/sel] */ cp.dy = 0.023; /* [mm/sel] */ cp.dpx = cp.dx * cp.Ncx / cp.Nfx; /* [mm/pix] */ cp.dpy = cp.dy; /* [mm/pix] */ cp.Cx = 576 / 2; /* [pix] */ cp.Cy = 384 / 2; /* [pix] */ cp.sx = 1.0; /* [] */ /* something a bit more realistic */ cp.Cx = 258.0; cp.Cy = 204.0;}/************************************************************************/void initialize_general_imaging_mos5300_matrox_parms (){ strcpy (camera_type, "General Imaging MOS5300 + Matrox"); cp.Ncx = 649; /* [sel] */ cp.Nfx = 512; /* [pix] */ cp.dx = 0.015; /* [mm/sel] */ cp.dy = 0.015; /* [mm/sel] */ cp.dpx = cp.dx * cp.Ncx / cp.Nfx; /* [mm/pix] */ cp.dpy = cp.dy; /* [mm/pix] */ cp.Cx = 512 / 2; /* [pix] */ cp.Cy = 480 / 2; /* [pix] */ cp.sx = 1.0; /* [] */}/************************************************************************/void initialize_panasonic_gp_mf702_matrox_parms (){ strcpy (camera_type, "Panasonic GP-MF702 + Matrox"); cp.Ncx = 649; /* [sel] */ cp.Nfx = 512; /* [pix] */ cp.dx = 0.015; /* [mm/sel] */ cp.dy = 0.015; /* [mm/sel] */ cp.dpx = cp.dx * cp.Ncx / cp.Nfx; /* [mm/pix] */ cp.dpy = cp.dy; /* [mm/pix] */ cp.Cx = 268; /* [pix] */ cp.Cy = 248; /* [pix] */ cp.sx = 1.078647; /* [] */}/************************************************************************/void initialize_sony_xc75_matrox_parms (){ strcpy (camera_type, "Sony XC75 + Matrox"); cp.Ncx = 768; /* [sel] */ cp.Nfx = 512; /* [pix] */ cp.dx = 0.0084; /* [mm/sel] */ cp.dy = 0.0098; /* [mm/sel] */ cp.dpx = cp.dx * cp.Ncx / cp.Nfx; /* [mm/pix] */ cp.dpy = cp.dy; /* [mm/pix] */ cp.Cx = 512 / 2; /* [pix] */ cp.Cy = 480 / 2; /* [pix] */ cp.sx = 1.0; /* [] */}/************************************************************************/void initialize_sony_xc77_matrox_parms (){ strcpy (camera_type, "Sony XC77 + Matrox"); cp.Ncx = 768; /* [sel] */ cp.Nfx = 512; /* [pix] */ cp.dx = 0.011; /* [mm/sel] */ cp.dy = 0.013; /* [mm/sel] */ cp.dpx = cp.dx * cp.Ncx / cp.Nfx; /* [mm/pix] */ cp.dpy = cp.dy; /* [mm/pix] */ cp.Cx = 512 / 2; /* [pix] */ cp.Cy = 480 / 2; /* [pix] */ cp.sx = 1.0; /* [] */}/************************************************************************/void initialize_sony_xc57_androx_parms (){ strcpy (camera_type, "Sony XC57 + Androx"); cp.Ncx = 510; /* [sel] */ cp.Nfx = 512; /* [pix] */ cp.dx = 0.017; /* [mm/sel] */ cp.dy = 0.013; /* [mm/sel] */ cp.dpx = cp.dx * cp.Ncx / cp.Nfx; /* [mm/pix] */ cp.dpy = cp.dy; /* [mm/pix] */ cp.Cx = 512 / 2; /* [pix] */ cp.Cy = 480 / 2; /* [pix] */ cp.sx = 1.107914; /* [] */}/************************************************************************//* John Krumm, 9 November 1993 *//* This assumes that every other row, starting with the second row from *//* the top, has been removed. The Xap Shot CCD only has 250 lines, and *//* it inserts new rows in between the real rows to make a full size *//* picture. Its algorithm for making these new rows isn't very good, *//* so it's best just to throw them away. *//* The camera's specs give the CCD size as 6.4(V)x4.8(H) mm. *//* A call to the manufacturer found that the CCD has 250 rows *//* and 782 columns. It is underscanned to 242 rows and 739 columns. *//************************************************************************/void initialize_xapshot_matrox_parms ()//佳能{ strcpy (camera_type, "Canon Xap Shot"); cp.Ncx = 739; /* [sel] */ cp.Nfx = 512; /* [pix] */ cp.dx = 6.4 / 782.0; /* [mm/sel] */ cp.dy = 4.8 / 250.0; /* [mm/sel] */ cp.dpx = cp.dx * cp.Ncx / cp.Nfx; /* [mm/pix] */ cp.dpy = cp.dy; /* [mm/pix] */ cp.Cx = 512 / 2; /* [pix] */ cp.Cy = 240 / 2; /* [pix] */ cp.sx = 1.027753; /* from noncoplanar calibration *//* [] */}/***********************************************************************\* This routine solves for the roll, pitch and yaw angles (in radians)正交规范化矩阵的旋转,倾斜偏离角度 ** for a given orthonormal rotation matrix (from Richard P. Paul, ** Robot Manipulators: Mathematics, Programming and Control, p70). ** Note 1, should the rotation matrix not be orthonormal these will not ** be the "best fit" roll, pitch and yaw angles. ** Note 2, there are actually two possible solutions for the matrix. ** The second solution can be found by adding 180 degrees to Rz before ** Ry and Rx are calculated. *\***********************************************************************/void solve_RPY_transform (){ double sg, cg; cc.Rz = atan2 (cc.r4, cc.r1); SINCOS (cc.Rz, sg, cg); cc.Ry = atan2 (-cc.r7, cc.r1 * cg + cc.r4 * sg); cc.Rx = atan2 (cc.r3 * sg - cc.r6 * cg, cc.r5 * cg - cc.r2 * sg);}/***********************************************************************\* This routine simply takes the roll, pitch and yaw angles and fills in ** the rotation matrix elements r1-r9. *\***********************************************************************/void apply_RPY_transform (){ double sa, ca, sb, cb, sg, cg; SINCOS (cc.Rx, sa, ca); SINCOS (cc.Ry, sb, cb); SINCOS (cc.Rz, sg, cg); cc.r1 = cb * cg; cc.r2 = cg * sa * sb - ca * sg; cc.r3 = sa * sg + ca * cg * sb; cc.r4 = cb * sg; cc.r5 = sa * sb * sg + ca * cg; cc.r6 = ca * sb * sg - cg * sa; cc.r7 = -sb; cc.r8 = cb * sa; cc.r9 = ca * cb;}/***********************************************************************\* Routines for coplanar camera calibration共面相机的标定程序 *\***********************************************************************/void cc_compute_Xd_Yd_and_r_squared (){ int i; double Xd_, Yd_; for (i = 0; i < cd.point_count; i++) { Xd[i] = Xd_ = cp.dpx * (cd.Xf[i] - cp.Cx) / cp.sx; /* [mm] */ Yd[i] = Yd_ = cp.dpy * (cd.Yf[i] - cp.Cy); /* [mm] */ r_squared[i] = SQR (Xd_) + SQR (Yd_); /* [mm^2] */ }}void cc_compute_U (){ int i; dmat M, a, b; M = newdmat (0, (cd.point_count - 1), 0, 4, &errno); if (errno) { fprintf (stderr, "cc compute U: unable to allocate matrix M\n"); exit (-1); } a = newdmat (0, 4, 0, 0, &errno); if (errno) { fprintf (stderr, "cc compute U: unable to allocate vector a\n"); exit (-1); } b = newdmat (0, (cd.point_count - 1), 0, 0, &errno); if (errno) { fprintf (stderr, "cc compute U: unable to allocate vector b\n"); exit (-1); } for (i = 0; i < cd.point_count; i++) { M.el[i][0] = Yd[i] * cd.xw[i]; M.el[i][1] = Yd[i] * cd.yw[i]; M.el[i][2] = Yd[i]; M.el[i][3] = -Xd[i] * cd.xw[i]; M.el[i][4] = -Xd[i] * cd.yw[i]; b.el[i][0] = Xd[i]; } if (solve_system (M, a, b)) { fprintf (stderr, "cc compute U: unable to solve system Ma=b\n"); exit (-1); } U[0] = a.el[0][0]; U[1] = a.el[1][0]; U[2] = a.el[2][0]; U[3] = a.el[3][0]; U[4] = a.el[4][0]; freemat (M); freemat (a); freemat (b);}void cc_compute_Tx_and_Ty (){ int i, far_point; double Tx, Ty, Ty_squared, x, y, Sr, r1p, r2p, r4p, r5p, r1, r2, r4, r5, distance, far_distance; r1p = U[0]; r2p = U[1]; r4p = U[3]; r5p = U[4]; /* first find the square of the magnitude of Ty */ if ((fabs (r1p) < EPSILON) && (fabs (r2p) < EPSILON)) Ty_squared = 1 / (SQR (r4p) + SQR (r5p)); else if ((fabs (r4p) < EPSILON) && (fabs (r5p) < EPSILON)) Ty_squared = 1 / (SQR (r1p) + SQR (r2p)); else if ((fabs (r1p) < EPSILON) && (fabs (r4p) < EPSILON)) Ty_squared = 1 / (SQR (r2p) + SQR (r5p)); else if ((fabs (r2p) < EPSILON) && (fabs (r5p) < EPSILON)) Ty_squared = 1 / (SQR (r1p) + SQR (r4p)); else { Sr = SQR (r1p) + SQR (r2p) + SQR (r4p) + SQR (r5p); Ty_squared = (Sr - sqrt (SQR (Sr) - 4 * SQR (r1p * r5p - r4p * r2p))) / (2 * SQR (r1p * r5p - r4p * r2p)); } /* find a point that is far from the image center */ far_distance = 0; far_point = 0; for (i = 0; i < cd.point_count; i++) if ((distance = r_squared[i]) > far_distance) { far_point = i; far_distance = distance; } /* now find the sign for Ty */ /* start by assuming Ty > 0 */ Ty = sqrt (Ty_squared); r1 = U[0] * Ty; r2 = U[1] * Ty; Tx = U[2] * Ty; r4 = U[3] * Ty; r5 = U[4] * Ty; x = r1 * cd.xw[far_point] + r2 * cd.yw[far_point] + Tx; y = r4 * cd.xw[far_point] + r5 * cd.yw[far_point] + Ty; /* flip Ty if we guessed wrong */ if ((SIGNBIT (x) != SIGNBIT (Xd[far_point])) || (SIGNBIT (y) != SIGNBIT (Yd[far_point]))) Ty = -Ty; /* update the calibration constants */ cc.Tx = U[2] * Ty; cc.Ty = Ty;}void cc_compute_R (){ double r1, r2, r3, r4, r5, r6, r7, r8, r9; r1 = U[0] * cc.Ty; r2 = U[1] * cc.Ty; r3 = sqrt (1 - SQR (r1) - SQR (r2)); r4 = U[3] * cc.Ty; r5 = U[4] * cc.Ty; r6 = sqrt (1 - SQR (r4) - SQR (r5)); if (!SIGNBIT (r1 * r4 + r2 * r5)) r6 = -r6; /* use the outer product of the first two rows to get the last row */ r7 = r2 * r6 - r3 * r5; r8 = r3 * r4 - r1 * r6; r9 = r1 * r5 - r2 * r4; /* update the calibration constants */ cc.r1 = r1; cc.r2 = r2; cc.r3 = r3; cc.r4 = r4; cc.r5 = r5; cc.r6 = r6; cc.r7 = r7; cc.r8 = r8; cc.r9 = r9; /* fill in cc.Rx, cc.Ry and cc.Rz */ solve_RPY_transform ();}void cc_compute_approximate_f_and_Tz (){ int i; dmat M, a, b; M = newdmat (0, (cd.point_count - 1), 0, 1, &errno); if (errno) { fprintf (stderr, "cc compute apx: unable to allocate matrix M\n"); exit (-1); } a = newdmat (0, 1, 0, 0, &errno); if (errno) { fprintf (stderr, "cc compute apx: unable to allocate vector a\n"); exit (-1); } b = newdmat (0, (cd.point_count - 1), 0, 0, &errno); if (errno) { fprintf (stderr, "cc compute apx: unable to allocate vector b\n"); exit (-1); } for (i = 0; i < cd.point_count; i++) { M.el[i][0] = cc.r4 * cd.xw[i] + cc.r5 * cd.yw[i] + cc.Ty; M.el[i][1] = -Yd[i]; b.el[i][0] = (cc.r7 * cd.xw[i] + cc.r8 * cd.yw[i]) * Yd[i]; } if (solve_system (M, a, b)) { fprintf (stderr, "cc compute apx: unable to solve system Ma=b\n"); exit (-1); } /* update the calibration constants */ cc.f = a.el[0][0];//求f和tz; cc.Tz = a.el[1][0]; cc.kappa1 = 0.0; /* this is the assumption that our calculation was made under */ freemat (M); freemat (a); freemat (b);}/************************************************************************/
//计算精确的F和TZ误差;void cc_compute_exact_f_and_Tz_error (long *m_ptr, long *n_ptr, double *params, double *err){ int i; double f, Tz, kappa1, xc, yc, zc, Xu_1, Yu_1, Xu_2, Yu_2, distortion_factor; f = params[0]; Tz = params[1]; kappa1 = params[2]; for (i = 0; i < cd.point_count; i++) { /* convert from world coordinates to camera coordinates */
//世界坐标系和图像坐标系的转化;zw被假设为0; /* Note: zw is implicitly assumed to be zero for these (coplanar) calculations */ xc = cc.r1 * cd.xw[i] + cc.r2 * cd.yw[i] + cc.Tx; yc = cc.r4 * cd.xw[i] + cc.r5 * cd.yw[i] + cc.Ty; zc = cc.r7 * cd.xw[i] + cc.r8 * cd.yw[i] + Tz; /* convert from camera coordinates to undistorted sensor coordinates */ Xu_1 = f * xc / zc; Yu_1 = f * yc / zc; /* convert from distorted sensor coordinates to undistorted sensor coordinates */ distortion_factor = 1 + kappa1 * (SQR (Xd[i]) + SQR (Yd[i])); Xu_2 = Xd[i] * distortion_factor; Yu_2 = Yd[i] * distortion_factor; /* record the error in the undistorted sensor coordinates */ err[i] = hypot (Xu_1 - Xu_2, Yu_1 - Yu_2); }}void cc_compute_exact_f_and_Tz (){#define NPARAMS 3 int i; /* Parameters needed by MINPACK's lmdif() */ long m = cd.point_count; long n = NPARAMS; double x[NPARAMS]; double *fvec; double ftol = REL_SENSOR_TOLERANCE_ftol; double xtol = REL_PARAM_TOLERANCE_xtol; double gtol = ORTHO_TOLERANCE_gtol; long maxfev = MAXFEV; double epsfcn = EPSFCN; double diag[NPARAMS]; long mode = MODE; double factor = FACTOR; long nprint = 0; long info; long nfev; double *fjac; long ldfjac = m; long ipvt[NPARAMS]; double qtf[NPARAMS]; double wa1[NPARAMS]; double wa2[NPARAMS]; double wa3[NPARAMS]; double *wa4; /* allocate some workspace */ if (( fvec = (double *) calloc ((unsigned int) m, (unsigned int) sizeof(double))) == NULL ) { fprintf(stderr,"calloc: Cannot allocate workspace fvec\n"); exit(-1); } if (( fjac = (double *) calloc ((unsigned int) m*n, (unsigned int) sizeof(double))) == NULL ) { fprintf(stderr,"calloc: Cannot allocate workspace fjac\n"); exit(-1); } if (( wa4 = (double *) calloc ((unsigned int) m, (unsigned int) sizeof(double))) == NULL ) { fprintf(stderr,"calloc: Cannot allocate workspace wa4\n"); exit(-1); } /* use the current calibration constants as an initial guess */ x[0] = cc.f; x[1] = cc.Tz; x[2] = cc.kappa1; /* define optional scale factors for the parameters */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -