Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ opencv立体校准结果_C++_Opencv_Camera Calibration_Stereo 3d - Fatal编程技术网

C++ opencv立体校准结果

C++ opencv立体校准结果,c++,opencv,camera-calibration,stereo-3d,C++,Opencv,Camera Calibration,Stereo 3d,就像我有两个网络摄像头一样,标记为cam1,cam2。我想校准它们以获得它们之间的转换 我使用cv::stereoCalibrate()进行校准 在我得到从cam1到cam2的转换后,标记为R,T。我想检查校准结果的准确性 因此,我使用cam1和cam2为棋盘拍照,标记为pic1,pic2。我通过cv::solvePnP()获得了cam1的外部参数。我通过cv::projectPoints()在pic1中绘制了cam1的世界坐标系 然后,我认为cam2的旋转矩阵=cam1的旋转矩阵*R,以及ca

就像我有两个网络摄像头一样,标记为
cam1
cam2
。我想校准它们以获得它们之间的转换

我使用
cv::stereoCalibrate()
进行校准

在我得到从
cam1
cam2
的转换后,标记为
R
T
。我想检查校准结果的准确性

因此,我使用
cam1
cam2
为棋盘拍照,标记为
pic1
pic2
。我通过
cv::solvePnP()
获得了
cam1
的外部参数。我通过
cv::projectPoints()
pic1
中绘制了
cam1
的世界坐标系

然后,我认为
cam2
的旋转矩阵=
cam1
的旋转矩阵*
R
,以及
cam2
的平移矩阵=
cam1
的平移矩阵+
T

我用上述思想计算了
cam2
的外部参数,并用
pic2
中的
cv::projectPoints()
绘制了
cam2
的世界坐标系

但是
pic2
的原点位置不正确

这是我使用的部分代码

void check_res(const vector<string> &imgs_nm,const Mat &R,const Mat &T,const Mat &cam_c,const Mat &cam_h,const Mat &dist_c,const Mat &dist_h)
{
    int imgs_cnt=imgs_nm.size()/2;
    vector<Point3f> obj_pts;
    for(int i=0;i<boardDimensions.height;i++)
        for(int j=0;j<boardDimensions.width;j++)
            obj_pts.push_back(Point3f(i*CHESS_LEN,j*CHESS_LEN,0.f));
    for(int i=0;i<imgs_cnt;i++)
    {
        vector<Point2f> c_cners,h_cners;
        Mat imgc_gray,imgh_gray;
        Mat imgc=imread(imgs_nm[i*2],1);
        Mat imgc_rz=imgc.clone();

        bool c_found,h_found;
        c_found=HasChessBoard(imgc_rz,imgc_gray,c_cners);
        if(c_found)
            cv::cornerSubPix(imgc_gray, c_cners, cv::Size(11, 11), cv::Size(-1, -1),cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
        Mat imgh=imread(imgs_nm[i*2+1],1);
        h_found=HasChessBoard(imgh,imgh_gray,h_cners);
        if(h_found)
            cv::cornerSubPix(imgh_gray, h_cners, cv::Size(11, 11), cv::Size(-1, -1),cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
        Mat rvec_c,rvec_h,tvec_c,tvec_h;
        cv::solvePnP(obj_pts,c_cners,cam_c,dist_c,rvec_c,tvec_c);
        cv::solvePnP(obj_pts,h_cners,cam_h,dist_h,rvec_h,tvec_h);
        Mat rrvec_c,rrvec_h;
        cv::Rodrigues(rvec_c,rrvec_c);
        cv::Rodrigues(rvec_h,rrvec_h);
        Mat r1=rrvec_c*R;
        Mat t1=tvec_c+T;

        Mat img1=imgh.clone();
        draw_chess(imgh,rrvec_h,tvec_h,cam_h,dist_h);
        imshow("pic1",imgh);
        draw_chess(img1,r1,t1,cam_h,dist_h);
        imshow("pic2",img1);


        char resc=waitKey(0);
        if(resc=='q')
            exit(1);

    }
}
void check\u res(常数向量和imgs\u nm,常数矩阵和R,常数矩阵和T,常数矩阵和凸轮c,常数矩阵和凸轮h,常数矩阵和距离c,常数矩阵和距离h)
{
int imgs_cnt=imgs_nm.size()/2;
向量对象;
对于(int i=0;i,公式为:

  • 摄影机1的姿势(在齐次矩阵中):

  • 从摄影机1到摄影机2的均匀变换:

  • 摄像机2的姿势:

<> P>检查立体校准的准确性,我会考虑不同的方法:

  • 使用功能
    stereovertive
    获取相机的校正变换。使用从
    stereovertificate
    获得的平移和旋转矩阵
  • 对每个摄像头执行一次
    initundistortyMap
    。使用
  • 使用获得的结果重新映射两台摄像机的图像

  • 如果您的校准顺利,输出图像应该得到校正和不失真。

    是的,您是对的。
    opencv
    的示例代码使用的方法与您的方法相同。两个摄像头之间的R,T是从您提到的方法得到的。但是结果图像显示我可能犯了一些我不知道的错误。对不起,那么我很抱歉我一定是误解了你的问题。不过很高兴看到另一个方法奏效!没关系,这个答案可能会对其他人有所帮助。谢谢你的分享!我用你的答案尝试了一下。结果表明它几乎处于相同的位置。非常感谢!但我认为
    cam2
    的姿势=
    cam1
    的姿势*
    [R\T]
    .Mark
    cam1
    的姿势=
    [R1 | T1]
    cam2
    的姿势=
    [R2 | T2]
    ,它们之间的转换=
    [R | T]
    。世界坐标系的原点*
    [R1 | T1]
    =
    cam1
    的相机坐标系原点。然后我们将其乘以
    [R | T]
    ,所以我们将点转换为
    cam2
    的坐标系原点。我想知道我错在哪里,请告诉我。在camera1帧中表示的点:
    X_c1=(R_c1 | T_c1)。X_w
    ;两个摄像机之间的转换:
    X_c2=(c2_c1 | c2|T_c1).X_c1
    ;摄影机2帧中表示的点:
    X_c2=(c2_ru c1 | c2_T_c1)。(R_c1 | T_c1)。X_w
    其余为矩阵乘法。