2017-11-22 6 views
0

Ich habe den folgenden Code, der eine Kameravorschau anzeigt, ruft die Farbe eines einzelnen Pixels aus ab und konvertiert diesen Wert in eine 'gefilterte' Farbe.Konvertieren von Farben jedes Pixels in Videovorschau - Swift

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!) 
    } 
} 

Hier ist, wo die x: 0, y: 0 Pixelwert umgewandelt wird:

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)] 
     } 

    } 

} 

Der placeholder for now Kommentar auf die folgende Funktion verweist:

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!) 
} 

Und hier ist meine Erweiterung für eine Pixelfarbe Abrufen :

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) 
    } 

} 

Wie kann ich zum Beispiel einen Filter für den folgenden Farbbereich erstellen? enter image description here

Ich möchte in dem Kameraeingang nehmen, ersetzt die Farben des Deuteranopia Bereichs sein und diese auf dem Bildschirm angezeigt werden, in Echtzeit, mit Swift.

Ich verwende ein UIImageView für die Bildanzeige.

Antwort

0

Um zu erfahren, wie Filterung von Video-Capture auszuführen und Echtzeit-Anzeige des Bildes gefiltert, sollten Sie den AVCamPhotoFilter Beispielcode von Apple und anderen Quellen wie this objc.io tutorial

Kurz untersuchen, wird eine mit UIImage für Echtzeit-Rendering ist keine gute Idee - es ist zu langsam. Verwenden Sie eine OpenGL (z. B. GLKView) von Metal (z. B. MTKView). Der AVCamPhotoFilter-Code verwendet MTKView und rendert zu Zwischenpuffern, aber Sie können auch einen CImage direkt mit den entsprechenden CIContext-Methoden rendern, z. für Metall https://developer.apple.com/documentation/coreimage/cicontext/1437835-render

Darüber hinaus in Bezug auf Ihren Farbfilter - möchten Sie vielleicht auf den CIColorCube Kern Bildfilter wie gezeigt here.

Verwandte Themen