Ios 使用SceneKit和OpenCV的增强现实。[外在矩阵]
一段时间以来,我一直在尝试让AR应用程序与Ios 使用SceneKit和OpenCV的增强现实。[外在矩阵],ios,opencv,matrix,opengl-es,scenekit,Ios,Opencv,Matrix,Opengl Es,Scenekit,一段时间以来,我一直在尝试让AR应用程序与SceneKit和OpenCV一起工作。我有些东西可以用,但还不够好 这是一个稍微复杂的管道,所以我将分部分描述它,也许你可以告诉我我是否犯了错误的假设/逻辑错误 首先,我通过运行用于相机校准的标准opencv棋盘算法来获得内在矩阵 然后我使用 intrinsic matrix, 3D model of the marker, points in the image corresponding to the marker
SceneKit
和OpenCV
一起工作。我有些东西可以用,但还不够好
这是一个稍微复杂的管道,所以我将分部分描述它,也许你可以告诉我我是否犯了错误的假设/逻辑错误
首先,我通过运行用于相机校准的标准opencv
棋盘算法来获得内在矩阵
然后我使用
intrinsic matrix,
3D model of the marker,
points in the image corresponding to the marker
在opencv
的solvePnP
(++rodrigues
)中获取外部矩阵
。标准的东西
现在我需要将这个外部矩阵
从OpenCv
的坐标系
转换为SceneKit
坐标系
此转换如下所示:
由于OpenCV
具有左手坐标系:
远离摄像机+Z
右侧+X
向下+Y
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;
因此,要按如下方式进行转换:
-(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;
}
-(SCNMatrix4)转换到场景:(cv::Mat&)右手转换
{
SCNMatrix4 mat=SCNMatrix4标识;
//RightHandtransform是主列
//场景套件是排大调。
RightHandtransform=RightHandtransform.t();//进行转置
//复制旋转行
//复制第一行。
mat.m11=在(0,0)处的右手变换;
mat.m12=在(0,1)处的右手变换;
mat.m13=在(0,2)处的右手变换;
mat.m14=在(0,3)处的右手变换;
mat.m21=在(1,0)处的右手变换;
mat.m22=在(1,1)处的右手变换;
mat.m23=在(1,2)处的右手变换;
mat.m24=在(1,3)处的右手变换;
mat.m31=在(2,0)处的右手变换;
mat.m32=在(2,1)处的右手变换;
mat.m33=在(2,2)处的右手变换;
mat.m34=在(2,3)处的右手变换;
//复制翻译行。这是SceneKIT中的底行
mat.m41=右手变换在(3,0)处;
mat.m42=在(3,1)处的右手变换;
mat.m43=在(3,2)处的右手变换;
mat.m44=在(3,3)处的右手变换;
返回垫;
}
问题2:这种转换正确吗?我所做的转置应该从列主键
顺序转换为行主键
顺序
现在我们有了场景工具包中opencv
中的外部矩阵。我对此不是绝对确定,因为我发现了与此相关的冲突信息,但从solvePnP
获得的外部矩阵描述了模型在摄影机坐标系中的旋转和平移
问题3:是这样吗
所以现在我唯一要做的就是设置SCNNode
的变换属性,模型应该显示在SCNCamera
坐标系的正确位置。但它有点车
我还有一些代码,用于从摄影机坐标进行透视投影,以剪裁空间(NDC
)。由于篇幅的关系,我将把它写成不同的问题
问题4:我做出的假设是否合理
我在图形方面没有很多经验,所以如果我做了一些非常愚蠢的事情,请提醒我。多谢各位
旁注:
我对使用3D派对软件不感兴趣 @sleek这部分有3个问题。我认为把问题分成几个小问题并不能提供足够的上下文。我很高兴你编辑了你的问题。我对其进行了进一步编辑,使其更加清晰。GL.@SLEK非常感谢您的更正。@nnrales:您知道如何正确创建投影矩阵和透视矩阵以使用OpenCV吗?OpenCV和SceneKit都有右手坐标系。它们只是相对于相机的方向不同。
-(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;
}