[ARKit] ARBodyAnchor와 ARSkeleton

silverCastle·2022년 7월 24일
0

💡 ARBodyAnchor

ARBodyAnchor는 후면 카메라에서 인체의 위치와 움직임을 추적하는 앵커이다. ARAnchor의 하위 클래스인데 ARAnchor에 대해 간단히 설명하면 물리적 환경에서 항목의 위치와 방향을 지정하는 object이다.
ARBodyTrackingConfiguration을 사용해 Session을 실행하여 신체 추적을 활성화한다.
ARKit가 후면 카메라 feed에서 사람을 인식하면 ARBodyAnchor를 사용하여 delegate의 session(_:didAdd:)기능을 호출한다. 이 기능은 하나 이상의 앵커가 Session에 추가되었음을 delegate에게 알리는 역할을 한다.

optional func session(
    _ session: ARSession,
    didAdd anchors: [ARAnchor]
)

여기서 session은 정보를 제공하는 세션, anchors는 세션에 새로 추가된 앵커이다.
추가뿐만 아니라 업데이트를 처리할 수 있는데 이는 아래와 같다.

  • func session(ARSession, didUpdate: [ARAnchor])
    세션이 하나 이상의 앵커 속성을 조정했음을 대리자에게 알린다.
  • func session(ARSession, didRemove: [ARAnchor])
    하나 이상의 앵커가 세션에서 제거되었음을 대리자에게 알린다.

body anchor의 transform 위치는 몸체의 고관절의 세계 위치를 정의한다. 또한, ARKit가 frame의 앵커 내에서 ARKit가 추적하는 몸체를 확인할 수 있다.
여기서 transform이란 앵커가 배치된 AR 세션의 세계 좌표 공간을 기준으로 앵커의 위치, 방향, 크기를 인코딩하는 매트릭스이다. 즉, 앵커에 대한 정보를 알고싶을 때 유용할 것이다. declaration은 다음과 같다.

var transform: simd_float4x4 { get }

✍️ 표면에 Skeleton 배치

body 앵커의 원점은 고관절에 매핑되기 때문에 몸체의 골격(Skeleton)을 표면에 배치하기 위해 엉덩이에 대한 발의 현재 offset을 계산한다. 발 관절(joint) index를 jointModelTransforms에 전달하면 골격의 원점에서 발의 offset을 얻을 수 있다. jointModelTransforms는 모델 공간이 각각의 관절에 대해 변환되는 기능을 제공한다.

static var hipToFootOffset: Float {
    // Get an index for a foot. 
    let footIndex = ARSkeletonDefinition.defaultBody3D.index(forJointName: .leftFoot)
    // Get the foot's world-space offset from the hip. 
    let footTransform = ARSkeletonDefinition.defaultBody3D.neutralBodySkeleton3D!.jointModelTransforms[footIndex]
    // Return the height by getting just the y-value. 
    let distanceFromHipOnY = abs(footTransform.columns.3.y) 
    return distanceFromHipOnY
}

💡ARSkeleton

ARSkeleton은 추적된 몸체의 골격에 대한 interface이다. 관절의 모음이므로 ARKit가 추적할 수 있는 인체의 상태를 알기 위해 이 프로토콜이 중요하다고 할 수 있다.
하위 클래스로는 아래와 같이 2개가 존재한다.

  • ARSkeleton3D
    3D 공간에서 추적된 몸체의 관절 위치를 제공하며 특히 jointLocalTransforms 및 jointModelTransforms property 제공한다.
  • ARSkeleton2D
    jointLandmarks property를 통해 2D 공간에서 추적된 몸체의 관절 위치를 제공한다.

필자는 3D 공간에서 body tracking을 할 예정이므로, ARSkeleton3D에 초점을 두겠다.

✍️ ARSkeleton3D

ARKit가 3D 공간에서 추적하는 인체의 골격으로써 ARBodyAnchor는 3D 공간에서 관절 위치를 제공하기 위해 서브 클래스인 ARSkeleton의 하나의 인스턴스를 포함한다.
jointLocalTransforms property는 상위 관절에서 관절의 3D offset을 설명한다.
jointModelTransforms는 몸체 앵커에서 관절의 3D offset을 설명한다.
이 둘의 차이는 각 관절에 대해 local 공간이 변환되는지, model 공간이 변환되는지의 차이이다.

관절의 자세 얻기 위한 property와 method는 다음과 같다.

  • var jointLocalTransforms: [simd_float4x4]
    로컬 공간은 각 관절에 대해 변환된다.
  • var jointModelTransforms: [simd_float4x4]
    모델 공간은 각 관절에 대해 변환된다.
  • func localTransform(for: ARSkeleton.JointName) -> simd_float4x4?
    주어진 이름을 가진 조인트에 대한 로컬 변환을 반환한다.
  • func modelTransform(for: ARSkeleton.JointName) -> simd_float4x4?
    주어진 이름을 가진 관절에 대한 모델 변환을 반환한다.

✍️ motion capture를 위한 model 검증

ARKit의 motion tracking 기능을 사용하려면 특정 형식의 모델을 사용해야 한다. 특정 형식과 일치하지 않는 모델은 제대로 작동하지 않거나 전혀 작동하지 않을 수 있으므로 주의해야 한다.
형식이 여러가지가 있어 하나만 설명하고 Apple의 개발자 문서로 대체하겠다.

몸통 관절 매치
골격의 몸통에는 8개의 관절이 있어야 한다.
고관절인 hips_joint가 루트이고 7개의 척추 관절이 있는데 캐릭터가 T-포즈 위치에 있을 때 엉덩이 관절과 첫 번째 척추 관절이 겹친다.

Joint nameParent joint
hips_jointroot
spine_1_jointhips_joint
spine_2_jointspine_1_joint
spine_3_jointspine_2_joint
spine_4_jointspine_3_joint
spine_5_jointspine_4_joint
spine_6_jointspine_5_joint
spine_7_jointspine_6_joint

https://developer.apple.com/documentation/arkit/content_anchors/validating_a_model_for_motion_capture

0개의 댓글