8

我正在开发一个 OpenCV 项目,并且正在进行校准。我相信我已经正确地实现了代码;但是我得到了不同的相机矩阵值,有时变化很大。在 6 次重复显示校准模式 10 次后,我得到(为清楚起见截断小数)

[573, 0,  386;
  0, 573, 312;
  0,  0,   1]

[642, 0,  404;
  0, 644, 288;
  0,  0,   1]

[664, 0,  395;
  0, 665, 272;
  0,  0,   1]

[629, 0,  403;
  0, 630, 288;
  0,  0,   1]

[484, 0,  377;
  0, 486, 307;
  0,  0,   1]

[644, 0,  393;
  0, 643, 289;
  0,  0,   1]

这些值相差不可接受的量。我需要相当准确地知道给定参数是什么。这些大的不准确的典型原因是什么,我如何评估给定矩阵的正确性?这似乎取决于我展示图案的距离和方向的多样性,但我无法理解图案。

代码:

using namespace cv;
using namespace std;

int main(int, char**)
{
    VideoCapture cap(1);
    if(!cap.isOpened())
        return -1;

    cap.set(CV_CAP_PROP_FRAME_WIDTH,800);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT,600);
    Mat edges;
    Size size(9,17);

    int counter = 10;

    vector<Point2f> corners;
    bool found;

    vector<Point3f> chess = fr::ChessGen::getBoard(size,1,true);

    vector<vector<Point3f> > objectPoints;
    vector<vector<Point2f> > imagePoints;

    Mat camera = Mat::eye(3,3,CV_64F);
    Mat distortion = Mat::zeros(8, 1, CV_64F);
    vector<Mat > rvecs;
    vector<Mat > tvecs;

    namedWindow("edges",1);
    for(;;)
    {
        Mat frame;
        cap >> frame;
        cvtColor(frame, edges, CV_BGR2GRAY);

        found = findCirclesGrid(edges,size,corners
                                ,CALIB_CB_ASYMMETRIC_GRID
                                );
        if(found) frame.convertTo(edges,-1,0.2);

        drawChessboardCorners(edges,size,corners,found);

        imshow("edges", edges);
        if(found){
            if(waitKey(200)>=0){
                objectPoints.push_back(chess);
                imagePoints.push_back(corners);
                if(--counter<= 0)
                    break;
            }
        }
        else waitKey(30);
    }

    calibrateCamera(objectPoints,imagePoints,Size(800,600),camera,distortion,rvecs,tvecs,0);

    if(found) imwrite("/home/ryan/snapshot.png",edges);

    cout << camera << endl;

    return 0;
}
4

4 回答 4

5

取决于相机/镜头和您需要的精度,但您可能需要超过 10 个位置,并且需要覆盖更广泛的视角。

我从 800x600 假设这是一个网络摄像头,带有一个简单的广角镜头,有很多失真。我会说您需要在与相机的 3-4 个不同角度中的每一个中目标的 6-8 个位置/旋转。您还需要确保目标和相机是固定的,并且在图像期间不会移动。再次假设相机具有简单的自动增益,您应该确保目标光线充足,因此它将使用快速快门速度和低增益。

openCV 使用的技术的一个问题是它需要查看目标上的所有角/点,以便在解决方案中识别和使用一帧 - 因此很难在图像的角附近找到点。您应该检查数据以了解校准中实际使用的图像数量 - 它可能只是在 10 个图像中的几个图像上找到所有点,并将解决方案基于该子集。

于 2012-12-02T18:33:22.963 回答
3

同样重要的是不要只拍摄垂直于相机的图案,而是要旋转它们。为了提高结果质量,您还可以仔细检查检测到的角落的位置,删除一些未正确检测到角落的图片,然后再次运行算法。

我不知道您使用的是哪款相机,但是由于相机的失真很大且不够锐利,因此很难正确检测到角落。OpenCV 校准也可以使用圆形图案来实现,在这种情况下可以提供更好的结果。

于 2012-12-05T10:33:05.890 回答
1

根据我的经验,您应该使用 OpenCV 提供的函数 undistort() 使用未失真的图像进行校准。

这意味着您需要运行两次校准,第一次是确定镜头系数。然后在第二次运行中不扭曲每个棋盘框架。使用不失真的校准框架,焦距 fx 和 fy 变得更加精确。

于 2015-05-28T13:10:09.280 回答
0

根据张正友的论文,正确的角度在45度以下,而且必须有6张以上的照片,最好拍20张。另外,你需要注意光的平衡,强度。

于 2014-07-24T12:02:25.980 回答