1

我有一些问题。我尝试校准我的相机。我写了一些函数来做到这一点,但它需要一些奇怪的数据,所以我尝试用 O'Reilly OpenCV 书中的例子来检查它(第 12 章中有一个例子 12-3:投影和 3D 视觉)。我将该示例调整为我的程序,但程序挂起(如果它是好词)。我更深入地检查了 opencv 的函数,发现在 cvStereoCalibrate 中有 cvCalibrateCamera2 包含问题:在优化部分该行:

bool proceed = solver.updateAlt( _param, _JtJ, _JtErr, _errNorm ); //solver is object of CvLevMarq

需要很长时间(无限)。

为什么需要这么长时间(好几个小时)?或者也许我犯了一些错误,但我不知道在哪里(我从书中重写了它,也许是错的)

这是我的代码:

void Calibration::stereoCalibTest()
{
  int displayCorners = 0;
  int showUndistorted = 1;
  bool isVerticalStereo = false;
  const int maxScale = 1;
  const float squareSize = m_squareSize;
  int nframes, n = m_boardSize.width() * m_boardSize.height(), N = 0;
  int nx = m_boardSize.width();
  int ny = m_boardSize.height();

  vector<CvPoint3D32f> objectPoints;
  vector<CvPoint2D32f> points[2];
  vector<int> npoints;
  vector<CvPoint2D32f> temp(n);
  vector<uchar> active[2];

  CvSize imageSize = {0,0};

  //ARRAY AND VECTOR STORAGE
  double M1[3][3], M2[3][3], D1[5], D2[5];
  double R[3][3], T[3], E[3][3], F[3][3];
  CvMat _M1 = cvMat(3, 3, CV_64F, M1);
  CvMat _M2 = cvMat(3, 3, CV_64F, M2);
  CvMat _D1 = cvMat(1, 5, CV_64F, D1);
  CvMat _D2 = cvMat(1, 5, CV_64F, D2);
  CvMat _R = cvMat(3, 3, CV_64F, R);
  CvMat _T = cvMat(3, 1, CV_64F, T);
  CvMat _E = cvMat(3, 3, CV_64F, E);
  CvMat _F = cvMat(3, 3, CV_64F, F);

  //FOR LEFT CAMERA

  for(int  i = 0; i < m_imageList1.size(); i++)
  {
    IplImage *im_gray = cvCreateImage(cvGetSize(m_imageList1[i]),IPL_DEPTH_8U,1);
    cvCvtColor(m_imageList1[i],im_gray,CV_RGB2GRAY);

    vector<CvPoint2D32f> &pts = points[0];
    int count = 0, result = 0;
    imageSize = cvGetSize(m_imageList1[i]);
    result = cvFindChessboardCorners(im_gray, cvSize(nx, ny), &temp[0], &count, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_NORMALIZE_IMAGE);

    N = pts.size();
    pts.resize(N + n, cvPoint2D32f(0,0));
    active[0].push_back((uchar)result);

    if(result)
    {
      cvFindCornerSubPix(im_gray, &temp[0], count, cvSize(11, 11), cvSize(-1, -1), cvTermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 30, 0.01));
      copy(temp.begin(), temp.end(), pts.begin()+N);
    }

  }

  //FOR RIGHT CAMERA

  for(int  i = 0; i < m_imageList2.size(); i++)
  {
    vector<CvPoint2D32f> &pts = points[1];
    int count = 0, result = 0;
    imageSize = cvGetSize(m_imageList2[i]);
    IplImage *im_gray = cvCreateImage(imageSize,IPL_DEPTH_8U,1);
    cvCvtColor(m_imageList2[i],im_gray,CV_RGB2GRAY);
    result = cvFindChessboardCorners(im_gray, cvSize(nx, ny), &temp[0], &count, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_NORMALIZE_IMAGE);

    N = pts.size();
    pts.resize(N + n, cvPoint2D32f(0,0));
    active[0].push_back((uchar)result);

    if(result)
    {
      cvFindCornerSubPix(im_gray, &temp[0], count, cvSize(11, 11), cvSize(-1, -1), cvTermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 30, 0.01));
      copy(temp.begin(), temp.end(), pts.begin()+N);
    }
  }

  // HARVEST CHESSBOARD 3D OBJECT POINT LIST:

  nframes = active[0].size();
  objectPoints.resize(nframes * n);
  for(int i = 0; i < ny; i++)
    for(int j = 0; j < nx; j++)
      objectPoints[i * nx + j] = cvPoint3D32f(i*squareSize, j*squareSize, 0);

  for(int i = 1; i < nframes; i++)
    copy(objectPoints.begin(), objectPoints.begin() + n, objectPoints.begin() + i *n);
  npoints.resize(nframes, n);
  N = nframes * n;
  CvMat _objectPoints = cvMat(1, N, CV_32FC3, &objectPoints[0]);
  CvMat _imagePoints1 = cvMat(1, N, CV_32FC2, &points[0][0]);
  CvMat _imagePoints2 = cvMat(1, N, CV_32FC2, &points[1][0]);
  CvMat _npoints  = cvMat(1, npoints.size(), CV_32S, &npoints[0]);
  cvSetIdentity(&_M1);
  cvSetIdentity(&_M2);
  cvZero(&_D1);
  cvZero(&_D2);

  //CALIBRATE THE STEREO CAMERAS
  ui.teInfo->append("Calibrating from TEST FUNCTION");

  cvStereoCalibrate(&_objectPoints, &_imagePoints1, &_imagePoints2, &_npoints, &_M1, &_D1, &_M2, &_D2, imageSize, &_R, &_T, &_E, &_F, cvTermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 100, 1e-5), CV_CALIB_FIX_ASPECT_RATIO + CV_CALIB_ZERO_TANGENT_DIST + CV_CALIB_SAME_FOCAL_LENGTH);

  ui.teInfo->append("Done!");


  // CALIBRATION QUALITY CHECK
  // because the output fundamental matrix implicitly
  // includes all the output information,
  // we can check the quality of calibration using the
  // epipolar geometry constraint: m2^t * F * m1 = 0

  vector<CvPoint3D32f> lines[2];
  points[0].resize(N);
  points[1].resize(N);
  _imagePoints1 = cvMat(1, N, CV_32FC2, &points[0][0]);
  _imagePoints2 = cvMat(1, N, CV_32FC2, &points[1][0]);

  lines[0].resize(N);
  lines[1].resize(N);
  CvMat _L1 = cvMat(1, N, CV_32FC3, &lines[0][0]);
  CvMat _L2 = cvMat(1, N, CV_32FC3, &lines[1][0]);

  // Always work in undistorted space
  cvUndistortPoints(&_imagePoints1, &_imagePoints1, &_M1, &_D1, 0, &_M1);
  cvUndistortPoints(&_imagePoints2, &_imagePoints2, &_M2, &_D2, 0, &_M2);

  cvComputeCorrespondEpilines(&_imagePoints1, 1, &_F, &_L1);
  cvComputeCorrespondEpilines(&_imagePoints2, 2, &_F, &_L2);
  double avgErr = 0;
  for(int i = 0; i < N; i++)
  {
    double err = fabs(points[0][i].x*lines[1][i].x + 
      points[0][i].y*lines[1][i].y + lines[1][i].z) +
      fabs(points[1][i].x*lines[0][i].x + points[1][i].y*lines[0][i].y + lines[0][i].z);
    avgErr += err;
  }

  ui.teInfo->append("average error: " +QString::number(avgErr/(nframes*n)));

  double R1[3][3], R2[3][3], P1[3][4], P2[3][4];
  CvMat _R1 = cvMat(3, 3, CV_64F, R1);
  CvMat _R2 = cvMat(3, 3, CV_64F, R2);
  CvMat _P1 = cvMat(3, 4, CV_64F, P1);
  CvMat _P2 = cvMat(3, 4, CV_64F, P2);

  cvStereoRectify(&_M1, &_M2, &_D1, &_D2, imageSize, &_R, &_T, 
    &_R1, &_R2, &_P1, &_P2, 0,0);

  ui.teInfo->append("TEST: cameras calibrated");
  bool isSaved = saveToFile(&_M1, &_M2, &_D1, &_D2, &_R1, &_R2, &_P1, &_P2);
  if(isSaved)
    ui.teInfo->append("TEST: saved to file");
  else
    ui.teInfo->append("TEST: cannot save to file");
}

需要很长时间

4

0 回答 0