Обнаруженное изображение ARKit снова появляется

В настоящее время я использую ARKit 2.0 (бета-версия) для распознавания изображений, и у меня есть одна проблема. Когда я обнаруживаю свое изображение, я помещаю рядом с ним объект (неважно, какой объект, это просто узел с материалом, основанным на найденном мной изображении).

Мой вопрос: есть ли функция ARKit, срабатывающая, когда найденное изображение появляется снова (то есть узел, связанный с imageanchor, тоже)? Я ищу прямо знаю, но я не нахожу ничего хорошего


person tacite    schedule 01.08.2018    source источник


Ответы (5)


В ARKit 3 мне удалось определить, когда изображение исчезло из поля зрения, используя renderer(_:didUpdate:for) и проверив, когда свойство isTracked якоря было установлено на false.

func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
    if let imageAnchor = anchor as? ARImageAnchor, imageAnchor.isTracked == false {
        view?.sceneView.session.remove(anchor: anchor)
    }
}
person EdmundBillary    schedule 15.12.2019
comment
Это должен быть утвержденный ответ - person Adam Wareing; 16.12.2019

Я взял несколько указателей из того, что было дано выше и что у меня уже было, и это то, что сработало для меня:

//add a variable to store the last image detected
var lastImageAnchor: ARAnchor!

//at every frame, detect image, compare with the last image stored, and show the node corresponding with the image
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    guard let imageAnchor = anchor as? ARImageAnchor else { return }
    if self.lastImageAnchor != nil && self.lastImageAnchor != imageAnchor {
        self.sceneView.session.remove(anchor: self.lastImageAnchor)
    }
    //add whatever code you need to have your nodes appear

    //lastly change the lastImageAnchor to the one what you just detected
    self.lastImageAnchor = imageAnchor
}

надеюсь это поможет ;)

person JAlves    schedule 06.03.2019

Когда вы настраиваете сеанс ARKit для обнаружения изображений, якорь добавляется в сцену при обнаружении изображения и вызывается метод renderer(renderer: nodeFor anchor:).

Когда изображение скрыто и «снова появляется» на экране, я думаю, следует вызвать рендерер (рендерер: didUpdate node: для привязки:).

Если нет, то он снова вызовет метод renderer(renderer: nodeFor anchor:), и вы можете вставить простую логическую логику, чтобы проверить, является ли это первым обнаружением или нет.

ИЗМЕНИТЬ:

Я сделал это с карточной игрой. У вас есть хранилище ARReferenceImage с каким-то именем. Когда вы представляете цель, renderer(_ renderer: SCNSceneRenderer, nodeFor привязка: ARAnchor) -> SCNNode? называется.

Сохраните его имя как необязательное в foundImagesNames: [String].

Затем снимите его с камеры, покажите обратно, он снова вызывается. Затем вам просто нужно проверить, было ли оно уже обнаружено.

if let imageAnchor = anchor as? ARImageAnchor,
   let name = imageAnchor.referenceImage.name {

if self.foundImagesNames.contains(name) {
    //already presented
}
else {
    //first time presenting
    self.foundImagesNames.append(name)
}
}
person michael-martinez    schedule 01.08.2018
comment
В настоящее время я использую метод renderer(renderer: nodeFor anchor:), и он вызывается только один раз, когда сеанс впервые обнаруживает изображение. Я пытался использовать рендерер (рендерер: didUpdate node: для привязки:), но этот называется, я думаю, что каждый кадр, когда мое изображение найдено, и я не нахожу способ узнать, когда мое изображение снова появляется и снова исчезает - person tacite; 02.08.2018
comment
Я прекрасно понимаю, что вы делаете, у меня проблема в том, что рендерер(_рендерер:SCNSceneRenderer,nodeFor anchor:ARAnchor) -> SCNNode? вызывается только тогда, когда я обнаруживаю новое изображение, а не когда я показываю обнаруженное изображение - person tacite; 02.08.2018
comment
Тогда я не знаю: / Когда я тестировал, он вызывался дважды. Вам нужно будет поместить точки останова в эти методы rendered(_:), чтобы найти обратный вызов, который соответствует вашим потребностям. Вы также можете реализовать пользовательскую логику в методе обновления средства визуализации, чтобы определить, видно ли положение узла с камеры или нет. - person michael-martinez; 02.08.2018

Я просто собираюсь бросить свои два цента здесь.

Если вы посмотрите на документацию ARKit - там написано:

https://developer.apple.com/documentation/arkit/recognizing_images_in_an_ar_experience

Подумайте, когда разрешить обнаружение каждого изображения для запуска (или повторения) взаимодействия с дополненной реальностью. ARKit добавляет привязку изображения к сеансу ровно один раз для каждого эталонного изображения в массиве discoveryImages конфигурации сеанса. Если ваш опыт дополненной реальности добавляет в сцену виртуальный контент при обнаружении изображения, это действие по умолчанию выполняется только один раз. Чтобы позволить пользователю снова увидеть этот контент без перезапуска приложения, вызовите метод сеанса remove(anchor:) для удаления соответствующего объекта ARImageAnchor. После удаления привязки ARKit добавит новую привязку при следующем обнаружении изображения.

Я также хотел бы отметить, что в ARkit есть два разных подкласса ARConfiguration, которые позволяют обнаруживать изображения:

ARWorldTrackingConfiguration: https://developer.apple.com/documentation/arkit/arworldtrackingconfiguration

ARImageTrackingConfiguration: https://developer.apple.com/documentation/arkit/arimagetrackingconfiguration

Я не знаю, поможет ли это вам вообще, но я просто подумал, что укажу на это будущим читателям этого поста.

Мы все учимся, делясь тем, что знаем

умный пес

person smartdog    schedule 03.08.2018

Попробуйте использовать self.session.remove(anchor: imageAnchor) в конце func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor). После func renderer(_ renderer: SCNSceneRenderer, didRemove node: SCNNode, for anchor: ARAnchor) будет вызвана функция. Этот ответ не идеален, но вы можете работать с ним, чтобы сделать его подходящим для вас.

Мое решение:

В моем приложении я сделал так. Создано var lastImageAnchor: ARAnchor!. В func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) добавлено self.lastImageAnchor = imageAnchor. После этой функции:

func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
        updateQueue.async {
            if let imageAnchor = anchor as? ARImageAnchor {
                guard let lastAnchor = self.lastImageAnchor else { return }
                if imageAnchor != lastAnchor {
                    self.session.remove(anchor: lastAnchor)
                }
            }
        }
    }
person Yerzhan Serikbay    schedule 26.12.2018