代码之家  ›  专栏  ›  技术社区  ›  nopassport1

在视频预览中转换每个像素的颜色-Swift

  •  1
  • nopassport1  · 技术社区  · 8 年前

    我有以下代码,它显示相机预览,从 UIImage

    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        connection.videoOrientation = orientation
        let videoOutput = AVCaptureVideoDataOutput()
        videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue.main)
    
        let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
        let cameraImage = CIImage(cvImageBuffer: pixelBuffer!)
    
        let typeOfColourBlindness = ColourBlindType(rawValue: "deuteranomaly")
    
        /* Gets colour from a single pixel - currently 0,0 and converts it into the 'colour blind' version */
    
        let captureImage = convert(cmage: cameraImage)
    
        let colour = captureImage.getPixelColour(pos: CGPoint(x: 0, y: 0))
    
        var redval: CGFloat = 0
        var greenval: CGFloat = 0
        var blueval: CGFloat = 0
        var alphaval: CGFloat = 0
    
        _ = colour.getRed(&redval, green: &greenval, blue: &blueval, alpha: &alphaval)
        print("Colours are r: \(redval) g: \(greenval) b: \(blueval) a: \(alphaval)")
    
        let filteredColour = CBColourBlindTypes.getModifiedColour(.deuteranomaly, red: Float(redval), green: Float(greenval), blue: Float(blueval))
        print(filteredColour)
    
        /* #################################################################################### */
    
        DispatchQueue.main.async {
            // placeholder for now
            self.filteredImage.image = self.applyFilter(cameraImage: cameraImage, colourBlindness: typeOfColourBlindness!)
        }
    }
    

    这里是 x: 0, y: 0 转换像素值:

    import Foundation
    
    enum ColourBlindType: String {
        case deuteranomaly = "deuteranomaly"
        case protanopia = "protanopia"
        case deuteranopia = "deuteranopia"
        case protanomaly = "protanomaly"
    }
    
    class CBColourBlindTypes: NSObject {
       class func getModifiedColour(_ type: ColourBlindType, red: Float, green: Float, blue: Float) -> Array<Float> {
            switch type {
            case .deuteranomaly:
                return [(red*0.80)+(green*0.20)+(blue*0),
                        (red*0.25833)+(green*0.74167)+(blue*0),
                        (red*0)+(green*0.14167)+(blue*0.85833)]
            case .protanopia:
                return [(red*0.56667)+(green*0.43333)+(blue*0),
                        (red*0.55833)+(green*0.44167)+(blue*0),
                        (red*0)+(green*0.24167)+(blue*0.75833)]
            case .deuteranopia:
                return [(red*0.625)+(green*0.375)+(blue*0),
                        (red*0.7)+(green*0.3)+(blue*0),
                        (red*0)+(green*0.3)+(blue*0.7)]
            case .protanomaly:
                return [(red*0.81667)+(green*0.18333)+(blue*0.0),
                        (red*0.33333)+(green*0.66667)+(blue*0.0),
                        (red*0.0)+(green*0.125)+(blue*0.875)]
            }
    
        }
    
    }
    

    这个 placeholder for now 注释是指以下功能:

    func applyFilter(cameraImage: CIImage, colourBlindness: ColourBlindType) -> UIImage {
    
        //do stuff with pixels to render new image
    
    
        /*      Placeholder code for shifting the hue      */
    
        // Create a place to render the filtered image
        let context = CIContext(options: nil)
    
        // Create filter angle
        let filterAngle = 207 * Double.pi / 180
    
        // Create a random color to pass to a filter
        let randomColor = [kCIInputAngleKey: filterAngle]
    
        // Apply a filter to the image
        let filteredImage = cameraImage.applyingFilter("CIHueAdjust", parameters: randomColor)
    
        // Render the filtered image
        let renderedImage = context.createCGImage(filteredImage, from: filteredImage.extent)
    
        // Return a UIImage
        return UIImage(cgImage: renderedImage!)
    }
    

    这是我检索像素颜色的扩展:

    extension UIImage {
        func getPixelColour(pos: CGPoint) -> UIColor {
    
            let pixelData = self.cgImage!.dataProvider!.data
            let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
    
            let pixelInfo: Int = ((Int(self.size.width) * Int(pos.y)) + Int(pos.x)) * 4
    
            let r = CGFloat(data[pixelInfo]) / CGFloat(255.0)
            let g = CGFloat(data[pixelInfo+1]) / CGFloat(255.0)
            let b = CGFloat(data[pixelInfo+2]) / CGFloat(255.0)
            let a = CGFloat(data[pixelInfo+3]) / CGFloat(255.0)
    
            return UIColor(red: r, green: g, blue: b, alpha: a)
        }
    
    }
    

    例如,如何为以下颜色范围创建过滤器? enter image description here

    Deuteranopia 并使用Swift在屏幕上实时显示。

    我正在使用UIImageView进行图像显示。

    2 回复  |  直到 8 年前
        1
  •  0
  •   Sébastien A    8 年前

    要了解如何对视频捕获进行过滤并实时显示过滤后的图像,您可能需要学习 AVCamPhotoFilter 来自Apple和其他来源的示例代码,例如 this objc.io tutorial

    简而言之,使用UIImage进行实时渲染不是一个好主意,因为它太慢了。使用金属(例如MTKView)的OpenGL(例如GLKView)。AVCamPhotoFilter代码使用MTKView并渲染到中间缓冲区,但您也可以使用适当的CIContext方法直接渲染CIImage,例如对于金属 https://developer.apple.com/documentation/coreimage/cicontext/1437835-render

    此外,关于滤色器,您可能需要查看CIColorCube核心图像滤色器,如图所示 here .

        2
  •  0
  •   Andrew    6 年前
    let filterName = "CIColorCrossPolynomial"
    //deuteronomaly
    let param = ["inputRedCoefficients" : CIVector(values: [0.8, 0.2, 0, 0, 0, 0, 0, 0, 0, 0], count: 10),
                 "inputGreenCoefficients" : CIVector(values: [0.25833, 0.74167, 0, 0, 0, 0, 0, 0, 0, 0], count: 10),
                 "inputBlueCoefficients" : CIVector(values: [0, 0.14167, 0.85833, 0, 0, 0, 0, 0, 0, 0], count: 10)]
    
    let filter = CIFilter(name: filterName, parameters: param)
    
    let startImage = CIImage(image: image!)
    filter?.setValue(startImage, forKey: kCIInputImageKey)
    
    let newImage = UIImage(ciImage: ((filter?.outputImage)!))
    

    筛选结果: filter result

    过滤结果2: filter result 2