Search code examples
swiftaugmented-realityscenekitarkitscene

Distinguish between multiple tracked images at the same time?


I currently have a group of 5 reference images that my app is tracking. However, I want it to be able distinguish between the reference images (i.e. if the image is of image A, image B, or image C. Tracking real photos I print out on postcards).

Currently, my code is able to detect the image and put a plane (i.e. a simple rectangle) over it. However, my question is, is it possible to distinguish whether the app has detected a picture of picture A vs picture B? If so, how?

I know there's an option to use ML, but wanted to see if there were any easier options in SceneKit/ARKit that I haven't considered; especially since I'm using the exact image and not trying to have the app guess an object.

class ViewController: UIViewController, ARSCNViewDelegate {
    
    @IBOutlet var sceneView: ARSCNView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        sceneView.delegate = self
    }
    
//MARK-: WHERE I CONFIGURE MY APP TO DETECT AN IMAGE

    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)
    }
    
//MARK-: WHERE I PLACE A PLANE OVER THE DETECTED IMAGE

    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

                node.addChildNode(planeNode)
            }
            return node
    }
    
}

Solution

  • You can easily do it using such instance properties as referenceImage and name.

    // The detected image referenced by the image anchor.
    var referenceImage: ARReferenceImage { get }
    

    and:

    // A descriptive name for your reference image.
    var name: String? { get set }  
    

    Here's how they look like in code:

    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        
        guard let imageAnchor = anchor as? ARImageAnchor,
              let _ = imageAnchor.referenceImage.name
        else { return }
        
        anchorsArray.append(imageAnchor)
    
        if imageAnchor.referenceImage.name == "apple" {
            print("Image with apple is successfully detected...")
        }
    }