resolucion que profundidad por imagenes imagen color ios iphone camera swift core-image

ios - profundidad - que es 36 bits por pixel



Aplicar efecto visual a las imágenes píxel por píxel en Swift (1)

Tengo la tarea de una universidad de crear efectos visuales y aplicarlos a los cuadros de video capturados a través de la cámara del dispositivo. Actualmente puedo obtener la imagen y la pantalla, pero no puedo cambiar los valores de color de los píxeles.

Transformo el buffer de muestra a la variable imageRef y si lo transformo en UIImage todo está bien.

Pero ahora quiero tomar esa imagen. Si cambio los valores de su color píxel por píxel, en este ejemplo, cambie a colores negativos (tengo que hacer cosas más complicadas para que no pueda usar CIFilters) pero cuando ejecuto la parte comentada se estrelló debido a mal acceso.

import UIKit import AVFoundation class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate { let captureSession = AVCaptureSession() var previewLayer : AVCaptureVideoPreviewLayer? var captureDevice : AVCaptureDevice? @IBOutlet weak var cameraView: UIImageView! override func viewDidLoad() { super.viewDidLoad() captureSession.sessionPreset = AVCaptureSessionPresetMedium let devices = AVCaptureDevice.devices() for device in devices { if device.hasMediaType(AVMediaTypeVideo) && device.position == AVCaptureDevicePosition.Back { if let device = device as? AVCaptureDevice { captureDevice = device beginSession() break } } } } func focusTo(value : Float) { if let device = captureDevice { if(device.lockForConfiguration(nil)) { device.setFocusModeLockedWithLensPosition(value) { (time) in } device.unlockForConfiguration() } } } override func touchesBegan(touches: NSSet!, withEvent event: UIEvent!) { var touchPercent = Float(touches.anyObject().locationInView(view).x / 320) focusTo(touchPercent) } override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) { var touchPercent = Float(touches.anyObject().locationInView(view).x / 320) focusTo(touchPercent) } func beginSession() { configureDevice() var error : NSError? captureSession.addInput(AVCaptureDeviceInput(device: captureDevice, error: &error)) if error != nil { println("error: /(error?.localizedDescription)") } previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) previewLayer?.frame = view.layer.frame //view.layer.addSublayer(previewLayer) let output = AVCaptureVideoDataOutput() let cameraQueue = dispatch_queue_create("cameraQueue", DISPATCH_QUEUE_SERIAL) output.setSampleBufferDelegate(self, queue: cameraQueue) output.videoSettings = [kCVPixelBufferPixelFormatTypeKey: kCVPixelFormatType_32BGRA] captureSession.addOutput(output) captureSession.startRunning() } func configureDevice() { if let device = captureDevice { device.lockForConfiguration(nil) device.focusMode = .Locked device.unlockForConfiguration() } } // MARK : - AVCaptureVideoDataOutputSampleBufferDelegate func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) { let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) CVPixelBufferLockBaseAddress(imageBuffer, 0) let baseAddress = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0) let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer) let width = CVPixelBufferGetWidth(imageBuffer) let height = CVPixelBufferGetHeight(imageBuffer) let colorSpace = CGColorSpaceCreateDeviceRGB() var bitmapInfo = CGBitmapInfo.fromRaw(CGImageAlphaInfo.PremultipliedFirst.toRaw())! | CGBitmapInfo.ByteOrder32Little let context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, bitmapInfo) let imageRef = CGBitmapContextCreateImage(context) CVPixelBufferUnlockBaseAddress(imageBuffer, 0) let data = CGDataProviderCopyData(CGImageGetDataProvider(imageRef)) as NSData let pixels = data.bytes var newPixels = UnsafeMutablePointer<UInt8>() //for index in stride(from: 0, to: data.length, by: 4) { /*newPixels[index] = 255 - pixels[index] newPixels[index + 1] = 255 - pixels[index + 1] newPixels[index + 2] = 255 - pixels[index + 2] newPixels[index + 3] = 255 - pixels[index + 3]*/ //} bitmapInfo = CGImageGetBitmapInfo(imageRef) let provider = CGDataProviderCreateWithData(nil, newPixels, UInt(data.length), nil) let newImageRef = CGImageCreate(width, height, CGImageGetBitsPerComponent(imageRef), CGImageGetBitsPerPixel(imageRef), bytesPerRow, colorSpace, bitmapInfo, provider, nil, false, kCGRenderingIntentDefault) let image = UIImage(CGImage: newImageRef, scale: 1, orientation: .Right) dispatch_async(dispatch_get_main_queue()) { self.cameraView.image = image } } }


Tiene mal acceso en el bucle de manipulación de píxeles porque el nuevo Pixel UnsafeMutablePointer se inicializó con un RawPointer integrado y apunta a 0x0000 en la memoria y, en mi opinión, apunta a un espacio de memoria no asignado donde no tiene derecho a almacenar datos.

Para una explicación más larga y una "solución" hice algunos cambios ...

Primero, Swift cambió un poco desde que se publicó el OP, esta línea tuvo que ser modificada de acuerdo con la función de rawValue:

//var bitmapInfo = CGBitmapInfo.fromRaw(CGImageAlphaInfo.PremultipliedFirst.toRaw())! | CGBitmapInfo.ByteOrder32Little var bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedFirst.rawValue) | CGBitmapInfo.ByteOrder32Little

También se requirieron un par de cambios para los punteros, así que publiqué todos los cambios (dejé las líneas originales con marcas de comentarios).

let data = CGDataProviderCopyData(CGImageGetDataProvider(imageRef)) as NSData //let pixels = data.bytes let pixels = UnsafePointer<UInt8>(data.bytes) let imageSize : Int = Int(width) * Int(height) * 4 //var newPixels = UnsafeMutablePointer<UInt8>() var newPixelArray = [UInt8](count: imageSize, repeatedValue: 0) for index in stride(from: 0, to: data.length, by: 4) { newPixelArray[index] = 255 - pixels[index] newPixelArray[index + 1] = 255 - pixels[index + 1] newPixelArray[index + 2] = 255 - pixels[index + 2] newPixelArray[index + 3] = pixels[index + 3] } bitmapInfo = CGImageGetBitmapInfo(imageRef) //let provider = CGDataProviderCreateWithData(nil, newPixels, UInt(data.length), nil) let provider = CGDataProviderCreateWithData(nil, &newPixelArray, UInt(data.length), nil)

Algunas explicaciones: todos los bytes de píxel viejos se deben convertir en UInt8, por lo que en lugar de hacerlo, los píxeles se cambiaron para convertirlos en un UnsafePointer. Luego hice una matriz para los nuevos píxeles y eliminé el nuevo puntero de Pixel y trabajé directamente con la matriz. Finalmente, se agregó el puntero a la nueva matriz al proveedor para crear la imagen. Y eliminó la modificación de los bytes alfa.

Después de esto, pude obtener algunas imágenes negativas en mi vista con un rendimiento muy bajo, alrededor de 1 imagen cada diez segundos (iPhone 5, a través de XCode). Y lleva mucho tiempo presentar el primer fotograma en la vista de imagen.

Tuve una respuesta más rápida cuando agregué captureSession.stopRunning () al comienzo de la función didOutputSampleBuffer y luego, una vez que se completó el proceso, comencé de nuevo con captureSession.startRunning (). Con esto tuve casi 1 fps.

Gracias por el desafío interresting!