在Swift中使用Arkit识别图像后,如何播放本地视频?

时间:2018-07-10 13:18:42

标签: swift xcode scenekit arkit image-recognition

我有使用AR套件识别图像的功能,当检测到图像时,我需要在呈现的场景上显示和播放视频(如检测到的图像上方)?

lazy  var fadeAndSpinAction: SCNAction = {
    return .sequence([
        .fadeIn(duration: fadeDuration),
        .rotateBy(x: 0, y: 0, z: CGFloat.pi * 360 / 180, duration: rotateDuration),
        .wait(duration: waitDuration),
        .fadeOut(duration: fadeDuration)
        ])
}()

lazy var fadeAction: SCNAction = {
    return .sequence([
        .fadeOpacity(by: 0.8, duration: fadeDuration),
        .wait(duration: waitDuration),
        .fadeOut(duration: fadeDuration)
        ])
}()

lazy var fishNode: SCNNode = {
    guard let scene = SCNScene(named: "Catfish1.scn"),
        let node = scene.rootNode.childNode(withName: "Catfish1", recursively: false) else { return SCNNode() }
    let scaleFactor = 0.005
    node.scale = SCNVector3(scaleFactor, scaleFactor, scaleFactor)
    node.eulerAngles.x = -.pi / 2
    return node
}()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    sceneView.delegate = self
    configureLighting()
}
func configureLighting()  {
    sceneView.autoenablesDefaultLighting = true
    sceneView.automaticallyUpdatesLighting = true
}

override func viewWillAppear(_ animated: Bool) {
    resetTrackingConfiguration()
}
func resetTrackingConfiguration() {
    guard let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else { return }
    let configuration = ARWorldTrackingConfiguration()
    configuration.detectionImages = referenceImages
    let options: ARSession.RunOptions = [.resetTracking, .removeExistingAnchors]
    sceneView.session.run(configuration, options: options)
    statusLabel.text = "Move camera around to detect images"
}
extension ViewController: ARSCNViewDelegate {

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    DispatchQueue.main.async {
        guard let imageAnchor = anchor as? ARImageAnchor,
            let imageName = imageAnchor.referenceImage.name else { return }
        // TODO: Overlay 3D Object
        let overlayNode = self.getNode(withImageName: imageName)
        overlayNode.opacity = 0
        overlayNode.position.y = 0.2
        overlayNode.runAction(self.fadeAndSpinAction)
        node.addChildNode(overlayNode)
        self.statusLabel.text = "Image detected: \"\(imageName)\""

        self.videoNode.geometry = SCNPlane(width: 1276.0 / 2.0, height: 712.0 / 2.0)
        self.spriteKitScene.scaleMode = .aspectFit
        self.videoSpriteKitNode?.position = CGPoint(x: self.spriteKitScene.size.width / 2.0, y: self.spriteKitScene.size.height / 2.0)
        self.videoSpriteKitNode?.size = self.spriteKitScene.size
        self.spriteKitScene.addChild(self.videoSpriteKitNode!)
        self.videoNode.geometry?.firstMaterial?.diffuse.contents = self.spriteKitScene
        var transform = SCNMatrix4MakeRotation(Float(M_PI), 0.0, 0.0, 1.0)
        transform = SCNMatrix4Translate(transform, 1.0, 1.0, 0)
        self.videoNode.geometry?.firstMaterial?.diffuse.contentsTransform = transform
        self.videoNode.position = SCNVector3(x: 0, y: 30, z: 7)
        node.addChildNode(self.videoNode)
        self.videoSpriteKitNode?.play()
    }
}

func getPlaneNode(withReferenceImage image: ARReferenceImage) -> SCNNode {
    let plane = SCNPlane(width: image.physicalSize.width,
                         height: image.physicalSize.height)
    let node = SCNNode(geometry: plane)
    return node
}`

1 个答案:

答案 0 :(得分:10)

看看您的代码,首先将SCNPlane设置为638米宽和356米高,我确定那不是您真正想要的^ ________ ^。

无论如何,下面是一个使用SKSceneSKVideoNode播放本地视频的示例,该示例效果很好:

//--------------------------
// MARK: - ARSCNViewDelegate
//--------------------------

extension ViewController: ARSCNViewDelegate {

    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

        //1. Check We Have An ARImageAnchor And Have Detected Our Reference Image
        guard let imageAnchor = anchor as? ARImageAnchor else { return }

        let referenceImage = imageAnchor.referenceImage

        //2. Get The Physical Width & Height Of Our Reference Image
        let width = CGFloat(referenceImage.physicalSize.width)
        let height = CGFloat(referenceImage.physicalSize.height)

        //3. Create An SCNNode To Hold Our Video Player With The Same Size As The Image Target
        let videoHolder = SCNNode()
        let videoHolderGeometry = SCNPlane(width: width, height: height)
        videoHolder.transform = SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0)
        videoHolder.geometry = videoHolderGeometry

        //4. Create Our Video Player
        if let videoURL = Bundle.main.url(forResource: "BlackMirrorz", withExtension: "mp4"){

            setupVideoOnNode(videoHolder, fromURL: videoURL)
        }

        //5. Add It To The Hierarchy
        node.addChildNode(videoHolder)
    }

    /// Creates A Video Player As An SCNGeometries Diffuse Contents
    ///
    /// - Parameters:
    ///   - node: SCNNode
    ///   - url: URL
    func setupVideoOnNode(_ node: SCNNode, fromURL url: URL){

        //1. Create An SKVideoNode
        var videoPlayerNode: SKVideoNode!

        //2. Create An AVPlayer With Our Video URL
        let videoPlayer = AVPlayer(url: url)

        //3. Intialize The Video Node With Our Video Player
        videoPlayerNode = SKVideoNode(avPlayer: videoPlayer)
        videoPlayerNode.yScale = -1

        //4. Create A SpriteKitScene & Postion It
        let spriteKitScene = SKScene(size: CGSize(width: 600, height: 300))
        spriteKitScene.scaleMode = .aspectFit
        videoPlayerNode.position = CGPoint(x: spriteKitScene.size.width/2, y: spriteKitScene.size.height/2)
        videoPlayerNode.size = spriteKitScene.size
        spriteKitScene.addChild(videoPlayerNode)

        //6. Set The Nodes Geoemtry Diffuse Contenets To Our SpriteKit Scene
        node.geometry?.firstMaterial?.diffuse.contents = spriteKitScene

        //5. Play The Video
        videoPlayerNode.play()
        videoPlayer.volume = 0

    }
}

更新

如果要将视频放置在目标上方,则可以执行以下操作:

  func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

        //1. Check We Have An ARImageAnchor And Have Detected Our Reference Image
        guard let imageAnchor = anchor as? ARImageAnchor else { return }


        let referenceImage = imageAnchor.referenceImage

        //2. Get The Physical Width & Height Of Our Reference Image
        let width = CGFloat(referenceImage.physicalSize.width)
        let height = CGFloat(referenceImage.physicalSize.height)

        //3. Create An SCNNode To Hold Our Video Player
        let videoHolder = SCNNode()
        let planeHeight = height/2
        let videoHolderGeometry = SCNPlane(width: width, height: planeHeight)
        videoHolder.transform = SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0)
        videoHolder.geometry = videoHolderGeometry

        //4. Place It About The Target
        let zPosition = height - (planeHeight/2)
        videoHolder.position = SCNVector3(0, 0, -zPosition)

        //5. Create Our Video Player
        if let videoURL = Bundle.main.url(forResource: "BlackMirrorz", withExtension: "mp4"){

            setupVideoOnNode(videoHolder, fromURL: videoURL)
        }

        //5. Add It To The Hierachy
        node.addChildNode(videoHolder)
    }

希望有帮助...