在ARKit上显示具有透明背景的视频

时间:2019-04-14 23:25:18

标签: arrays arkit skeffectnode

我正试图简单地显示一个视频,该视频去除了背景的一部分,这意味着它是透明的。我已经尝试了Stack Overflow提供的几种方法,到目前为止,它们都未达到标准。最接近我要搜索的结果的一个是此链接中的一个:ARKit / SpriteKit - set pixelBufferAttributes to SKVideoNode or make transparent pixels in video (chroma-key effect) another way

但是,尽管这种方法很明智,而且对于提出问题的人似乎很有效,但在我看来,这只会使整个视频变白。

我的策略是显示视频并添加如下效果:

func setVideoNode(named name: String, in node: SCNNode, with imageReference: ARReferenceImage?, size: CGSize = CGSize(width: 500, height: 320), extension ext: String = "mp4") {

        let nodeWidth = imageReference!.physicalSize.width
        let nodeHeigth = imageReference!.physicalSize.height

        guard let videoUrl = Bundle.main.url(forResource: name, withExtension: ext) else {
            print("Guard Fail")
            return
        }

        self.currentPlayer = AVPlayer(url: videoUrl)

        let videoNode = SKVideoNode(avPlayer: self.currentPlayer)
        videoNode.size = size
        videoNode.name = name
        videoNode.yScale = -1.0
        videoNode.play()

        let effectNode = SKEffectNode()
        effectNode.addChild(videoNode)
        effectNode.filter = colorCubeFilterForChromaKey(hueAngle: 0)

        let planeGeometry = SCNPlane(width: nodeWidth, height: nodeHeigth)
        planeGeometry.firstMaterial?.diffuse.contents = effectNode
        planeGeometry.firstMaterial?.isDoubleSided = true

        let planeNode = SCNNode()
        planeNode.geometry = planeGeometry
        planeNode.position = SCNVector3(planeNode.position.x + 1, 0.5, 0)
        planeNode.eulerAngles.x = -.pi / 2

        node.addChildNode(planeNode)

        self.currentPlayer.play()


    }

func RGBtoHSV(r : Float, g : Float, b : Float) -> (h : Float, s : Float, v : Float) {
        var h : CGFloat = 0
        var s : CGFloat = 0
        var v : CGFloat = 0
        let col = UIColor(red: CGFloat(r), green: CGFloat(g), blue: CGFloat(b), alpha: 1.0)
        col.getHue(&h, saturation: &s, brightness: &v, alpha: nil)
        return (Float(h), Float(s), Float(v))
    }

    func colorCubeFilterForChromaKey(hueAngle: Float) -> CIFilter {

        let hueRange: Float = 20 // degrees size pie shape that we want to replace
        let minHueAngle: Float = (hueAngle - hueRange/2.0) / 360
        let maxHueAngle: Float = (hueAngle + hueRange/2.0) / 360

        let size = 64
        var cubeData = [Float](repeating: 0, count: size * size * size * 4)
        var rgb: [Float] = [0, 0, 0]
        var hsv: (h : Float, s : Float, v : Float)
        var offset = 0

        for z in 0 ..< size {
            rgb[2] = Float(z) / Float(size) // blue value
            for y in 0 ..< size {
                rgb[1] = Float(y) / Float(size) // green value
                for x in 0 ..< size {

                    rgb[0] = Float(x) / Float(size) // red value
                    hsv = RGBtoHSV(r: rgb[0], g: rgb[1], b: rgb[2])
                    // TODO: Check if hsv.s > 0.5 is really nesseccary
                    let alpha: Float = (hsv.h > minHueAngle && hsv.h < maxHueAngle && hsv.s > 0.5) ? 0 : 1.0

                    cubeData[offset] = rgb[0] * alpha
                    cubeData[offset + 1] = rgb[1] * alpha
                    cubeData[offset + 2] = rgb[2] * alpha
                    cubeData[offset + 3] = alpha
                    offset += 4
                }
            }
        }
        let b = cubeData.withUnsafeBufferPointer { Data(buffer: $0) }
        let data = b as NSData

        let colorCube = CIFilter(name: "CIColorCube", parameters: [
            "inputCubeDimension": size,
            "inputCubeData": data
            ])
        return colorCube!
    }

就我而言,我正在尝试消除红色。还有其他方法可以实现这一目标吗?

1 个答案:

答案 0 :(得分:0)

您在此 link 中看到的亲爱的朋友 。330 to 360 degree之间不能使用no来消除红色。

effectNode.filter = colorCubeFilterForChromaKey(hueAngle: 330)