Add image to AR Resources on the fly for image recognition

前端 未结 2 1601
[愿得一人]
[愿得一人] 2021-02-04 10:15

ARKit 1.5 introduces image recognition. In the code you have to create a Set of the reference images like this:

let referenceImages = ARReferenceIma         


        
相关标签:
2条回答
  • 2021-02-04 10:25
    let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
    let pathToObject = documentDirectory + "/reference.jpg"
    let imageUrl = URL(fileURLWithPath: pathToObject)
    let imageData: Data = try! Data(contentsOf: imageUrl)
    let image = UIImage(data: imageData, scale: UIScreen.main.scale)
    let cgImage = image!.cgImage
    
    let referenceImages = ARReferenceImage.init(cgImage!, orientation: .up, physicalWidth: 0.595)
    referenceImages.name = "Reference Image"
    let configuration = ARImageTrackingConfiguration()
    configuration.trackingImages = [referenceImages]
    session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
    
    0 讨论(0)
  • 2021-02-04 10:33

    You cannot amend the contents of the default folder at runtime, although you can create images on the fly.

    As an example let's put an image into the Assets Folder (not the ARResources one), which in my case is called 'moonTarget'.

    We could then create a function which we call in viewDidLoad etc:

    /// Create ARReference Images From Somewhere Other Than The Default Folder
    func loadDynamicImageReferences(){
    
        //1. Get The Image From The Folder
        guard let imageFromBundle = UIImage(named: "moonTarget"),
        //2. Convert It To A CIImage
        let imageToCIImage = CIImage(image: imageFromBundle),
        //3. Then Convert The CIImage To A CGImage
        let cgImage = convertCIImageToCGImage(inputImage: imageToCIImage)else { return }
    
        //4. Create An ARReference Image (Remembering Physical Width Is In Metres)
        let arImage = ARReferenceImage(cgImage, orientation: CGImagePropertyOrientation.up, physicalWidth: 0.2)
    
        //5. Name The Image
        arImage.name = "CGImage Test"
    
        //5. Set The ARWorldTrackingConfiguration Detection Images
        configuration.detectionImages = [arImage]
    }
    
    
    /// Converts A CIImage To A CGImage
    ///
    /// - Parameter inputImage: CIImage
    /// - Returns: CGImage
    func convertCIImageToCGImage(inputImage: CIImage) -> CGImage? {
        let context = CIContext(options: nil)
        if let cgImage = context.createCGImage(inputImage, from: inputImage.extent) {
         return cgImage
        }
        return nil
    }
    

    We can then test this in the ARSCNViewDelegate:

    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    
        //1. If Out Target Image Has Been Detected Than Get The Corresponding Anchor
        guard let currentImageAnchor = anchor as? ARImageAnchor else { return }
    
        let x = currentImageAnchor.transform
        print(x.columns.3.x, x.columns.3.y , x.columns.3.z)
    
        //2. Get The Targets Name
        let name = currentImageAnchor.referenceImage.name!
    
        //3. Get The Targets Width & Height In Meters
        let width = currentImageAnchor.referenceImage.physicalSize.width
        let height = currentImageAnchor.referenceImage.physicalSize.height
    
        print("""
        Image Name = \(name)
        Image Width = \(width)
        Image Height = \(height)
        """)
    
        //4. Create A Plane Geometry To Cover The ARImageAnchor
        let planeNode = SCNNode()
        let planeGeometry = SCNPlane(width: width, height: height)
        planeGeometry.firstMaterial?.diffuse.contents = UIColor.white
        planeNode.opacity = 0.25
        planeNode.geometry = planeGeometry
    
        //5. Rotate The PlaneNode To Horizontal
        planeNode.eulerAngles.x = -.pi/2
    
        //The Node Is Centered In The Anchor (0,0,0)
        node.addChildNode(planeNode)
    
        //6. Create AN SCNBox
        let boxNode = SCNNode()
        let boxGeometry = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
    
        //7. Create A Different Colour For Each Face
        let faceColours = [UIColor.red, UIColor.green, UIColor.blue, UIColor.cyan, UIColor.yellow, UIColor.gray]
        var faceMaterials = [SCNMaterial]()
    
        //8. Apply It To Each Face
        for face in 0 ..< 5{
            let material = SCNMaterial()
            material.diffuse.contents = faceColours[face]
            faceMaterials.append(material)
        }
        boxGeometry.materials = faceMaterials
        boxNode.geometry = boxGeometry
    
        //9. Set The Boxes Position To Be Placed On The Plane (node.x + box.height)
        boxNode.position = SCNVector3(0 , 0.05, 0)
    
        //10. Add The Box To The Node
        node.addChildNode(boxNode)   
    }
    

    As you can see the same could also be applied from a live feed as well.

    Hope this helps...

    As @Karlis said you could also look at using OnDemandResouces and then converting them to desired specs of an ARReferenceImage.

    Update: For anyone looking to see an example of creating dynamic reference images from a Server please take a look at the following project I have created: Dynamic Reference Images Sample Code

    0 讨论(0)
提交回复
热议问题