ARKit:你如何迭代所有检测到的特征点?
ARKit: How do you iterate all detected feature points?
我想对 ARKit 会话期间在单个帧中发现的每个检测到的特征点进行一些处理。如何遍历每个检测到的特征点,并获取它们的世界坐标?
我正在使用 Swift,但 Objective-C 答案也可以。
编辑: 在 Xcode 9.0 GM(及更高版本)中,points
是一个 Swift 数组 float3
向量,因此您可以像任何其他 Swift 数组一样对其进行迭代:
for point in frame.rawFeaturePoints.points {
...
}
或:
frame.rawFeaturePoints.points.map { point in
...
}
或者您最喜欢的 Array/Collection 算法是什么。
在各种 Xcode 9.x 测试版中,此 属性 的 Swift 数组版本不可用。因此,您不得不处理 underlying ObjC property,它作为 UnsafePointer
导入到 Swift,您无法轻松地对其进行迭代。 (因此 OP 的原始问题。)
如果该错误再次出现(或者您 运行 在其他地方遇到类似问题),您可以这样做:
for index in 0..<frame.rawFeaturePoints.count {
let point = frame.rawFeaturePoints.points[index]
// do something with point
}
由于我花了一段时间才想出一个工作示例来说明获得特征点的渲染效果,这里有一个完整的工作示例:
SCNNode *ARPointCloudNode = nil;
- (void)session:(ARSession *)session didUpdateFrame:(ARFrame *)frame API_AVAILABLE(ios(11.0));
{
NSInteger pointCount = frame.rawFeaturePoints.count;
if (pointCount) {
// We want a root node to work in, it's going to hold the all of the represented spheres
// that come together to make the point cloud
if (!ARPointCloudNode) {
ARPointCloudNode = [SCNNode node];
[self.sceneView.scene.rootNode addChildNode:ARPointCloudNode];
}
// It's going to need some colour
SCNMaterial *whiteMaterial = [SCNMaterial material];
whiteMaterial.diffuse.contents = [UIColor whiteColor];
whiteMaterial.locksAmbientWithDiffuse = YES;
// Remove the old point clouds (this happens per-frame
for (SCNNode *child in ARPointCloudNode.childNodes) {
[child removeFromParentNode];
}
// Use the frames point cloud to create a set of SCNSpheres
// which live at the feature point in the AR world
for (NSInteger i = 0; i < pointCount; i++) {
vector_float3 point = frame.rawFeaturePoints.points[i];
SCNVector3 vector = SCNVector3Make(point[0], point[1], point[2]);
SCNSphere *pointSphere = [SCNSphere sphereWithRadius:0.001];
pointSphere.materials = @[whiteMaterial];
SCNNode *pointNode = [SCNNode nodeWithGeometry:pointSphere];
pointNode.position = vector;
[ARPointCloudNode addChildNode:pointNode];
}
}
}
我想对 ARKit 会话期间在单个帧中发现的每个检测到的特征点进行一些处理。如何遍历每个检测到的特征点,并获取它们的世界坐标?
我正在使用 Swift,但 Objective-C 答案也可以。
编辑: 在 Xcode 9.0 GM(及更高版本)中,points
是一个 Swift 数组 float3
向量,因此您可以像任何其他 Swift 数组一样对其进行迭代:
for point in frame.rawFeaturePoints.points {
...
}
或:
frame.rawFeaturePoints.points.map { point in
...
}
或者您最喜欢的 Array/Collection 算法是什么。
在各种 Xcode 9.x 测试版中,此 属性 的 Swift 数组版本不可用。因此,您不得不处理 underlying ObjC property,它作为 UnsafePointer
导入到 Swift,您无法轻松地对其进行迭代。 (因此 OP 的原始问题。)
如果该错误再次出现(或者您 运行 在其他地方遇到类似问题),您可以这样做:
for index in 0..<frame.rawFeaturePoints.count {
let point = frame.rawFeaturePoints.points[index]
// do something with point
}
由于我花了一段时间才想出一个工作示例来说明获得特征点的渲染效果,这里有一个完整的工作示例:
SCNNode *ARPointCloudNode = nil;
- (void)session:(ARSession *)session didUpdateFrame:(ARFrame *)frame API_AVAILABLE(ios(11.0));
{
NSInteger pointCount = frame.rawFeaturePoints.count;
if (pointCount) {
// We want a root node to work in, it's going to hold the all of the represented spheres
// that come together to make the point cloud
if (!ARPointCloudNode) {
ARPointCloudNode = [SCNNode node];
[self.sceneView.scene.rootNode addChildNode:ARPointCloudNode];
}
// It's going to need some colour
SCNMaterial *whiteMaterial = [SCNMaterial material];
whiteMaterial.diffuse.contents = [UIColor whiteColor];
whiteMaterial.locksAmbientWithDiffuse = YES;
// Remove the old point clouds (this happens per-frame
for (SCNNode *child in ARPointCloudNode.childNodes) {
[child removeFromParentNode];
}
// Use the frames point cloud to create a set of SCNSpheres
// which live at the feature point in the AR world
for (NSInteger i = 0; i < pointCount; i++) {
vector_float3 point = frame.rawFeaturePoints.points[i];
SCNVector3 vector = SCNVector3Make(point[0], point[1], point[2]);
SCNSphere *pointSphere = [SCNSphere sphereWithRadius:0.001];
pointSphere.materials = @[whiteMaterial];
SCNNode *pointNode = [SCNNode nodeWithGeometry:pointSphere];
pointNode.position = vector;
[ARPointCloudNode addChildNode:pointNode];
}
}
}