使用SceneKit和OpenCV增强现实。 [外在矩阵]

时间:2017-03-31 18:15:59

标签: ios opencv matrix opengl-es scenekit

我一直试图让AR应用与SceneKitOpenCV一起使用一段时间。我有一些工作,但还不够好。

这是一个稍微复杂的管道,所以我将部分描述它,也许你可以告诉我是否做出了错误的假设/逻辑错误。

首先,我通过运行标准Intrinsic Matrix棋盘格算法进行相机校准来获得opencv

然后我使用

     intrinsic matrix,
     3D model of the marker,
     points in the image corresponding to the marker

opencv solvePnP(+ rodrigues)中获取extrinsic matrix。标准材料。

现在,我需要将此extrinsic matrixOpenCv' Coordinate System转换为SceneKit Coordinate System

此转换完成如下:

由于OpenCV具有左手坐标系:

  • +Z远离相机

  • +X向右

  • +Y down

SceneKit有一个右手坐标系:

  • +Z进入相机
  • +X向右
  • +Y向上

我使用以下代码反转YZ轴:

    // convert from left hand coor in opencv to right handed coor in opengl and scenekit

    cv::Mat cvToGl = cv::Mat::zeros(4, 4, CV_32F);
    cvToGl.at<float>(0, 0) = 1.0f;
    cvToGl.at<float>(1, 1) = -1.0f; // Invert the y axis.
    cvToGl.at<float>(2, 2) = -1.0f; // invert the z axis
    cvToGl.at<float>(3, 3) = 1.0f;

    extrinMatrix = cvToGl * extrinMatrix; 

问题1:这些假设是正确的,矩阵乘法是正确的吗?

更复杂的事项OpenCV有一个列顺序矩阵表示,而SceneKit有一个行顺序矩阵(矩阵是分别代表旋转和平移矩阵和向量的同质矩阵)。

    In OpenCV/GL :

    ROT | TRAN
    0   |   1

    In Scene Kit

    ROT  |   0
    TRAN |   1

所以要进行如下转换:

-(SCNMatrix4) transformToSceneKit:(cv::Mat&) RightHandtransform
{

    SCNMatrix4 mat = SCNMatrix4Identity; 

    // RightHandtransform is column major
    // Scene Kit is row major.
    RightHandtransform = RightHandtransform.t(); // Take the transpose

    // Copy the rotation rows
    // Copy the first row.
    mat.m11 = RightHandtransform.at<float>(0,0);
    mat.m12 = RightHandtransform.at<float>(0,1);
    mat.m13 = RightHandtransform.at<float>(0,2);
    mat.m14 = RightHandtransform.at<float>(0,3);

    mat.m21 = RightHandtransform.at<float>(1,0);
    mat.m22 = RightHandtransform.at<float>(1,1);
    mat.m23 = RightHandtransform.at<float>(1,2);
    mat.m24 = RightHandtransform.at<float>(1,3);

    mat.m31 = RightHandtransform.at<float>(2,0);
    mat.m32 = RightHandtransform.at<float>(2,1);
    mat.m33 = RightHandtransform.at<float>(2,2);
    mat.m34 = RightHandtransform.at<float>(2,3);

    //Copy the translation row. Which is the bottom row in SceneKIT
    mat.m41 = RightHandtransform.at<float>(3,0);
    mat.m42 = RightHandtransform.at<float>(3,1);
    mat.m43 = RightHandtransform.at<float>(3,2);
    mat.m44 = RightHandtransform.at<float>(3,3);

    return mat;
}

问题2:这种转换是否正确,我做的转置应该从column major订购转换为row major订购?

所以现在我们在opencv中有scene kit的外在矩阵。我并不完全确定这一点,因为我发现了有关此问题的相互矛盾的信息,但是从solvePnP获得的外在矩阵描述了模型在相机坐标系中的旋转和平移。

问题3:是吗?

所以现在我唯一需要做的就是设置SCNNode的transform属性,模型应显示在SCNCamera坐标系的正确位置。但它有点儿麻烦。

我还有代码用于从相机coor到剪辑空间(NDC)进行透视投影。由于篇幅,我会把它写成不同的问题。

问题4:我做出的假设是否合理?

我没有很多关于图形的经验,所以如果我做的事非常愚蠢,请提醒我。谢谢。

旁注:

我对使用3D派对软件不感兴趣。

0 个答案:

没有答案