Как обнаружить 2D-изображение с помощью ARKit и RealityKit?
Я хочу обнаружить 2D-изображение с помощью ARKit и RealityKit. Я не хочу использовать SceneKit, поскольку многие реализации основаны на RealityKit (доступ к Experience.rcproject). Есть идеи?
Я пробовал этот код
import ARKit
import RealityKit
class ViewController: UIViewController, ARSessionDelegate {
func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {
guard let imageAnchor = anchors.first as? ARImageAnchor,
let _ = imageAnchor.referenceImage.name
else { return }
let anchor = AnchorEntity(anchor: imageAnchor)
// Add Model Entity to anchor
anchor.addChild(model)
arView.scene.anchors.append(anchor)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
arView.session.delegate = self
resetTrackingConfig()
}
func resetTrackingConfig() {
guard let refImg = ARReferenceImage.referenceImages(inGroupNamed: "Sub",
bundle: nil)
else { return }
let config = ARWorldTrackingConfiguration()
config.detectionImages = refImg
config.maximumNumberOfTrackedImages = 1
let options = [ARSession.RunOptions.removeExistingAnchors,
ARSession.RunOptions.resetTracking]
arView.session.run(config, options: ARSession.RunOptions(options))
}
}
Из предыдущего поста, но он кажется устаревшим / неполным. Приведенный ниже код работает для SceneKit, но я не могу получить доступ к сценам из Experience.rcproject.
import UIKit
import RealityKit
import SceneKit
import ARKit
class ViewController: UIViewController, ARSCNViewDelegate {
@IBOutlet var sceneView: ARSCNView!
override func viewDidLoad() {
super.viewDidLoad()
sceneView.delegate = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let configuration = ARImageTrackingConfiguration()
guard let trackedImages = ARReferenceImage.referenceImages(inGroupNamed: "Photos", bundle: Bundle.main) else {
print("No images available")
return
}
configuration.trackingImages = trackedImages
configuration.maximumNumberOfTrackedImages = 7
sceneView.session.run(configuration)
}
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
<#code#>
}
func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
let node = SCNNode()
if let imageAnchor = anchor as? ARImageAnchor {
let plane = SCNPlane(width: imageAnchor.referenceImage.physicalSize.width, height: imageAnchor.referenceImage.physicalSize.height)
plane.firstMaterial?.diffuse.contents = UIColor(white: 1, alpha: 0.8)
let planeNode = SCNNode(geometry: plane)
planeNode.eulerAngles.x = -.pi / 2
let shipScene = SCNScene(named: "ship.scn")!
let shipNode = shipScene.rootNode.childNodes.first!
shipNode.position = SCNVector3Zero
shipNode.position.z = 0.15
planeNode.addChildNode(shipNode)
node.addChildNode(planeNode)
}
return node
}
}
2 ответа
В качестве альтернативы включению эталонных изображений в ваш пакет добавьте свои изображения - во время выполнения, если хотите - например:
а. Настройте словарь, чтобы помочь связать изображения с якорями:
private var imageAnchorToEntity: [ARImageAnchor: AnchorEntity] = [:]
б. Установите эталонные изображения вviewDidLoad()
или в любом другом месте по вашему выбору:
let exampleImage = ARReferenceImage(UIImage(named: "example"), orientation: .up, physicalWidth: 0.2)
let set = Set<ARReferenceImage>()
set.insert(exampleImage)
let config = ARImageTrackingConfiguration()
config.trackingImages = set
c. В методе делегата, который вызывается после добавления ARAnchor с помощью ARKit, определите привязку как ARImageAnchor, создайте из него AnchorEntity и свяжите его с ARImageAnchor для использования в будущем при помощи словаря:
func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
anchors.compactMap { $0 as? ARImageAnchor }.forEach {
let anchorEntity = AnchorEntity(anchor: $0)
// Add other entities as children to your AnchorEntity
anchorEntity.addChild(yourEntity)
imageAnchorToEntity[$0] = anchorEntity // Setting the reference
arView.scene.addAnchor(anchorEntity)
}
d. Соответственно, вы можете получить ссылку на свой AnchorEntity и его дочерние элементы в методе делегата сеанса (_:didUpdate:), открыв свой словарь:
func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {
anchors.compactMap { $0 as? ARImageAnchor }.forEach {
let anchorEntity = imageAnchorToEntity[$0]
anchorEntity?.transform.matrix = $0.transform
}
}
Примечание: я использовал ARImageTrackingConfiguration
в данном случае, который используется в основном для отслеживания изображений. Он работает наARWorldTrackingConfiguration
также, но ARKit может не отслеживать ваши изображения, а пользователь перемещает устройство.
- Добавьте новую "группу ресурсов AR" к ресурсам вашего проекта и добавьте туда свое изображение маркера. Обязательно укажите ширину и высоту. Я назвал группу "Маркеры".
- Добавьте следующий код (у меня он есть в viewWillAppear) моего UIViewController:
let imageAnchor = AnchorEntity(.image(group: "Markers", name: "YourImageName"))
yourARView.scene.anchors.append(imageAnchor)
// Setup some models to add etc
imageAnchor.addChild(someModel)