RealityKit - Распознавание изображений и работа со многими сценами

Я создал приложение, используя файл шаблона RealityKit. Внутри RealityComposer есть несколько сцен, все сцены используют распознавание изображений, которое активирует некоторые анимации.

Внутри Xcode мне нужно загрузить все сцены как якоря и добавить эти якоря в массив arView.scene.anchors. Проблема очевидна, поскольку я представляю физическое 2D-изображение одно за другим, я получаю несколько якорей, наложенных друг на друга, что нежелательно. Мне известно о arView.scene.anchors.removeAll() до загрузки нового якоря, но моя проблема заключается в следующем:

Как проверить, появилось ли определенное изображение, чтобы удалить существующий якорь и загрузить правильный? Я пытался найти что-то вроде того, что есть в ARKit как didUpdate, но я не вижу ничего похожего в RealityKit.

Большое спасибо


person JeremyRaven    schedule 12.01.2021    source источник


Ответы (1)


Предисловие

AnchorEntity(.image) RealityKit от RC, соответствует ARImageTrackingConfig ARKit. Когда устройство iOS распознает эталонное изображение, оно создает привязку изображения (которая соответствует протоколу ARTrackable), которая привязывает соответствующую 3D-модель. И, как вы понимаете, вы должны показывать только одно эталонное изображение за раз (в вашем конкретном случае приложение AR не может нормально работать, если вы даете ему два или более изображений одновременно).


Фрагмент кода, показывающий, как может выглядеть if condition логика:

import SwiftUI
import RealityKit

struct ContentView : View {
    var body: some View {            
        return ARViewContainer().edgesIgnoringSafeArea(.all)
    }
}

struct ARViewContainer: UIViewRepresentable {

    func makeUIView(context: Context) -> ARView {    
        let arView = ARView(frame: .zero)

        let id02Scene = try! Experience.loadID2()            
        print(id02Scene)     // prints scene hierarchy
        
        let anchor = id02Scene.children[0]
        print(anchor.components[AnchoringComponent] as Any)
        
        if anchor.components[AnchoringComponent] == AnchoringComponent(
                      .image(group: "Experience.reality", 
                              name: "assets/MainID_4b51de84.jpeg")) {
            
            arView.scene.anchors.removeAll()
            print("LOAD SCENE")
            arView.scene.anchors.append(id02Scene)
        }
        return arView
    }
 
    func updateUIView(_ uiView: ARView, context: Context) { }
}

ID2 иерархия сцен, напечатанная в консоли:

введите описание изображения здесь

P.S.

Вам следует реализовать класс SwiftUI Coordinator (прочтите об этом здесь ), а внутри Координатора используйте сеанс ARSessionDelegate (_: didUpdate :) метод экземпляра для обновления свойств якорей со скоростью 60 кадров в секунду.

Также вы можете использовать следующую логику - если якорь сцены 1 активен или якорь сцены 3 активен, просто удалите все якоря из коллекции и загрузите сцену 2.

var arView = ARView(frame: .zero)

let id01Scene = try! Experience.loadID1()
let id02Scene = try! Experience.loadID2()
let id03Scene = try! Experience.loadID3()

func makeUIView(context: Context) -> ARView {    
    arView.session.delegate = context.coordinator

    arView.scene.anchors.append(id01Scene)
    arView.scene.anchors.append(id02Scene)
    arView.scene.anchors.append(id03Scene)
    return arView
}

...

func session(_ session: ARSession, didUpdate frame: ARFrame) {
    if arView.scene.anchors[0].isActive || arView.scene.anchors[2].isActive {
        arView.scene.anchors.removeAll()
        arView.scene.anchors.append(id02Scene)
        print("Load Scene Two")
    }
}
person Andy Fedoroff    schedule 12.01.2021
comment
Спасибо за это, однако я получаю эту ошибку. Не могу найти «anchorInRealityComposerScene» в области видимости. Я думаю, что мне следует разместить там свое собственное имя, иначе оно каким-то образом выходит за рамки. - person JeremyRaven; 12.01.2021
comment
anchorInRealityComposerScene - абстрактное имя вашего якоря в иерархии сцены ... - person Andy Fedoroff; 13.01.2021
comment
Я вижу, вы имеете в виду якоря внутри сцены Composer, но единственный доступ к якорям, который я вижу, - это просто использование arView.scene.anchors.components [AnchoringComponent], которое выдает ошибку. AnchorCollection не имеет членов 'components' - person JeremyRaven; 13.01.2021
comment
Если я использую ссылку из загрузки сцены опыта, могу ли я действительно загрузить все сцены сразу в одну переменную, чтобы я мог проверить эту переменную. Компоненты? Все, что я нашел в Интернете, - это загрузить сцену за сценой, но мне нужна переменная, которая ссылается на все сцены сразу, не так ли? - person JeremyRaven; 13.01.2021
comment
Конечно, я имею в виду анкерную сущность из каждой сцены внутри Experience.rcproject. - person Andy Fedoroff; 13.01.2021
comment
Опубликуйте свой код и поделитесь своей сценой через службу обмена файлами (dropmefiles.com можно) - и я постараюсь помочь ты. Вы дали минимум информации о своем проекте. - person Andy Fedoroff; 13.01.2021
comment
dropmefiles.com/zrcxY Это довольно неловко, так как я только что взламывал файл шаблона в Xcode, и это настоящий беспорядок , посмотрим, что вы можете сделать, чтобы помочь. Действительно ценю это. [email protected] - person JeremyRaven; 13.01.2021
comment
Я обновил свой ответ. - person Andy Fedoroff; 13.01.2021
comment
Да, но если я скопирую и вставлю код внутри makeUIView 7 раз и изменю имена, чтобы они соответствовали каждой сцене в RealityComposer, загрузит ли он правильную сцену в нужное время, когда распознает соответствующее изображение? Спасибо - person JeremyRaven; 13.01.2021
comment
Какую тактику вы выберете для загрузки сцен, зависит от вас. Я только что показал, как можно добраться до определенного якоря изображения, при срабатывании которого загружается необходимая 3D-модель. Это ваше приложение, а вы - конструктор приложений AR)) - person Andy Fedoroff; 13.01.2021
comment
И еще один комментарий - ваше приложение AR не может нормально работать, если оно одновременно видит два или более изображения для обнаружения. Только по одному. - person Andy Fedoroff; 13.01.2021
comment
Очень признателен за вашу помощь. Думаю, я не понимаю, как механика работает с распознаванием изображений, поскольку я хочу, чтобы изображение, видимое через камеру, определяло, какую сцену загружать, и какой якорь добавить в arview.scene - person JeremyRaven; 13.01.2021
comment
Механика проста: Событие - ›Якорь -› Модель. Если алгоритм обучения модели (ML) распознает эталонное изображение, он создает ImageAnchor, который привязывает 3D-модель. - person Andy Fedoroff; 13.01.2021
comment
Если вы хотите каждый раз удалять предыдущую модель и загружать новую, вам определенно нужно загружать камеру только одним изображением за раз (в вашем конкретном случае). Это все. - person Andy Fedoroff; 13.01.2021
comment
И помните две вещи: 1) Каждый ImageAnchor (AnchorEntity RealityKit) расположен в самом центре соответствующего ему эталонного изображения. 2) AnchorEntity (.image) соответствует ARImageTrackingConfiguration в ARKit (не ARWorldTrackingConfiguration), и это очень важно ... - person Andy Fedoroff; 13.01.2021
comment
dropmefiles.com/sIC9U Да, но логика, которую мне не хватает, находится в следующей ссылке. Загружается только последний якорь8, даже если камера видит другие изображения по одному. Я вижу, что removeall удаляет все остальное, но я просто хочу, чтобы якоря загружались, когда появляется нужное изображение. - person JeremyRaven; 13.01.2021
comment
Тебе удалось, Джереми? - person Andy Fedoroff; 13.01.2021
comment
Почти готово! :) У меня просто привязки моделей сохраняются после того, как эталонное изображение в поле зрения камеры исчезает. Таким образом, я одновременно вижу на экране несколько объектов. Я думаю, мне нужно использовать здесь метод updateUIView ()? - person JeremyRaven; 13.01.2021
comment
Уверен на 100% - вам обязательно нужно обновлять эти якоря со скоростью 60 кадров в секунду. ИМХО вам нужен SwiftUI Coordinator (например, здесь: stackoverflow.com/questions/60582392/), но вместо renderer(_:updateAtTime:) используйте метод экземпляра ARSessionDelegate session(_:didUpdate:). - person Andy Fedoroff; 14.01.2021