我一直试图让AR应用与SceneKit
和OpenCV
一起使用一段时间。我有一些工作,但还不够好。
这是一个稍微复杂的管道,所以我将部分描述它,也许你可以告诉我是否做出了错误的假设/逻辑错误。
首先,我通过运行标准Intrinsic Matrix
棋盘格算法进行相机校准来获得opencv
。
然后我使用
intrinsic matrix,
3D model of the marker,
points in the image corresponding to the marker
在opencv
solvePnP
(+ rodrigues
)中获取extrinsic matrix
。标准材料。
现在,我需要将此extrinsic matrix
从OpenCv
' Coordinate System
转换为SceneKit
Coordinate System
。
此转换完成如下:
由于OpenCV
具有左手坐标系:
+Z
远离相机
+X
向右
+Y
down 和SceneKit
有一个右手坐标系:
+Z
进入相机+X
向右+Y
向上我使用以下代码反转Y
和Z
轴:
// 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派对软件不感兴趣。