【问题标题】:Calibrate camera to determine intrinsic params校准相机以确定内在参数
【发布时间】:2020-07-21 23:09:51
【问题描述】:

我一直在努力使用带有 c++ 的 openCV 完成正确的校准。 下面我已经包含了我的代码 sn-p 用于它的计算,如果你能指出我做错了什么,或者我可以如何改进它,将不胜感激。

// Initialize and reset calibration params
        void InitCaliberation()
        {
            //numBoards = 0;
            numCornersHor = horizontalCorners;
            numCornersVer = verticalCorners;
            numSquares = horizontalCorners * verticalCorners;

            board_sz = Size(horizontalCorners, verticalCorners);
            frame_sz = Size(frameWidth, frameHeight);
            sqSizeInmm = sqSizemm; //25 mm
            object_points.clear();
            image_points.clear();
            corners.clear();

            finishedCalberation = false;
        }

//Process frames
bool CheckCheckerboardFrame(Mat image, bool debug=false)
        {
            vector<Point3f> obj;
            Mat grayImage;
            cvtColor(image, grayImage, COLOR_BGR2GRAY);

            for (int j = 0; j < numSquares; j++)
                obj.push_back(Point3f(sqSizeInmm * j / numCornersHor, sqSizeInmm * j%numCornersHor, 0.0f));
            bool found = findChessboardCorners(grayImage, board_sz, corners, CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_FILTER_QUADS);

            if (found)
            {
                //sub-pixel accurate location
                cornerSubPix(grayImage, corners, Size(11, 11), Size(-1, -1), TermCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS, 30, 0.1));
                if(debug)
                    drawChessboardCorners(image, board_sz, corners, found);
                else {
                    image_points.push_back(corners);
                    object_points.push_back(obj);
                }
            }

            return found;
        }

// Calculate params
void FinishCaliberation()
        {
            calibrateCamera(object_points, image_points, frame_sz, intrinsic, distCoeffs, R, T);
            finishedCalberation = true;
            cout <<"\nIntrinsic: "<< intrinsic.size<<endl;

            for (int i = 0; i < intrinsic.rows; i++)
            {
                for (int j = 0; j < intrinsic.cols; j++)
                    cout << intrinsic.at<float>(i, j) << " ";
                cout << endl;
            }

            cout << "\nDist coeff: " << distCoeffs.size << endl;
            for (int i = 0; i < distCoeffs.rows; i++)
            {
                for (int j = 0; j < distCoeffs.cols; j++)
                    cout << distCoeffs.at<float>(i, j) << " ";
                cout << endl;
            }
            //cout<<
        }

以下是我使用 openCV 得到的输出。

这是预期的输出。我已经从 matlab 计算了这个校准。

我不想匹配结果!但想了解为什么 Fy 和 Cx 值为 0,以及为什么 intrinsic.at(0,1) 非零?我在这里做错了什么?

这是校准过程的最小代码:http://collabedit.com/3vay2 如果有人感兴趣的话。

【问题讨论】:

  • 您的 matlab 脚本和 C++ 代码存在逻辑错误。您可以在调试器中运行这两个代码并比较值。
  • @ThomasSablik 这里的逻辑错误是什么?
  • 我不知道,但你的调试器会告诉你。这是一个 C++ 问题。我在看代码。您将intrinsic.at&lt;float&gt;(0,1) 设为非零,因为您在其中写入了非零。找到您将值写入此变量的位置。
  • 尝试输入double 而不是float。 OpenCV 对那些小矩阵和镜头畸变值使用双精度,但您将内存区域解释为浮点数。
  • @Micka 你是生命的救星。非常感谢:)

标签: c++ opencv camera-calibration


【解决方案1】:

终于解决了问题。感谢 - @Micka

所以由于数据类型不匹配,我得到了垃圾值。 Opencv 需要双精度,而我对 Mat 参数使用浮点类型。这也是出现意外值的原因,例如intrinsic.at(0,1) 处的非零值。

这实际上让我对自己的实施产生了怀疑。但是将其转换为双重也可以解决此问题。 虽然我不确定 0 的双精度值是如何在浮点数中转换为 6.05179 的。可能与 OpenCV 的隐藏实现有关。

【讨论】:

  • 它不是类型转换。让我们有一个 16 位与 8 位无符号整数的类似示例。如果你有3倍16位的值,假设[2,255,1]这是本位数:0000000000000010 0000000011111111 0000000000000001和你解释的内存为8个整数,你将获得6个值:00000000 00000010 00000000 11111111 00000000 00000001 whih为[0 ,2,0,255,0,1],因此您会将预期的 3 个值读取为 [0,2,0](示例已简化,不处理小端、大端等,这可能会引入额外的东西)跨度>
  • 对。这就说得通了。谢谢你的详细解释。
猜你喜欢
  • 2018-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多