Muy buenas, les saluda Luis y en esta ocasión les traigo este tutorial.
Índice
Aprenda a procesar imágenes de alimentación de cámara en tiempo real para funciones de visión por computadora
Cada día que pasa, más y más aplicaciones utilizan la cámara del iPhone para algo más que tomar fotos, videos o videollamadas.
Aplicaciones como Snapchat procesan imágenes en tiempo real para obtener una vista previa de los filtros. Facebook intenta hacer que las videollamadas sean divertidas con filtros.
Los pasos que daremos en esta publicación son:
- Crea una nueva aplicación.
- Mostrar la alimentación de la cámara.
- Procesando la alimentación de la cámara.
¡Vamos a sumergirnos!
Comencemos abriendo Xcode. Desde el menú, seleccione Expediente > Nuevo > Proyecto…
Cuando se le solicite «Elija una plantilla para su nuevo proyecto:«Buscar y seleccionar Aplicación de vista única. Hacer clic próximo.
Cuando se le solicite «Elija opciones para su nuevo proyecto:» tipo ProcessingCameraFeed
para «Nombre del producto:”.
Seleccione Rápido para «Idioma:”. Seleccione Storyboard
para «Interfaz de usuario:”. Desmarque todas las casillas de verificación. Hacer clic próximo.
Guarde el proyecto donde desee y luego haga clic en Crear.
En esta sección mostraremos el feed de la cámara al usuario.
Para acceder a la cámara en dispositivos iOS, Apple nos proporciona Marco de AVFoundation
.
El marco de AVFoundation
nos proporciona métodos para hacer uso de varios medios audiovisuales, como micrófono, reproducción inalámbrica utilizando dispositivos conectados a Airplay
, así como la cámara, entre otras cosas. En este post solo haremos uso de la cámara.
Primero abramos el controlador de nuestra pantalla en blanco. Abierto ViewController.swift
. Agregue la siguiente línea de código justo debajo import UIKit
:
import AVFoundation
Esto nos permitirá hacer uso de la Marco de AVFoundation
.
A continuación, creemos una instancia de AVCaptureSession
. Agregue la siguiente propiedad al ViewController
clase:
private let captureSession = AVCaptureSession()
Para generar la transmisión de la cámara, debemos usar AVCaptureSession
para coordinar las entradas de captura de dispositivos y el destino de salida.
A continuación, agreguemos la cámara trasera como entrada de captura a nuestro captureSession
. Agregue las siguientes funciones que nos permitirán hacerlo:
private func addCameraInput() let device = AVCaptureDevice.default(for: .video)! let cameraInput = try! AVCaptureDeviceInput(device: device) self.captureSession.addInput(cameraInput)
El código anterior toma la cámara predeterminada, que es la cámara trasera estándar, la envuelve en una entrada de captura y finalmente agrega la entrada de la cámara como parte de las entradas de nuestras sesiones. Como solo usaremos la cámara, esta será nuestra única entrada.
Ahora llamemos al función addCameraInput
. Agregue la siguiente línea de código a función viewDidLoad
:
self.addCameraInput()
Se agregó la entrada de la cámara al coordinador de la sesión de captura.
¿Por qué llamamos a esto en viewDidLoad
? Cubriremos eso en un momento.
A continuación, presentemos la transmisión de la cámara en la pantalla. Agregue la siguiente propiedad al controlador de vista, justo debajo de la propiedad captureSession
:
private lazy var previewLayer: AVCaptureVideoPreviewLayer = let preview = AVCaptureVideoPreviewLayer(session: self.captureSession) preview.videoGravity = .resizeAspect return preview ()
La propiedad anterior creará y configurará una instancia de AVCaptureVideoPreviewLayer
cuando se accede por primera vez; está cargado perezosamente.
Además, también especificamos cómo mostrar la imagen de la alimentación de la cámara; cambiará de tamaño para ajustarse a los límites de las capas de vista previa mientras mantiene la relación de aspecto de la imagen.
Para comprobar la opción de cambio de tamaño, marque AVLayerVideoGravity
.
A continuación, agreguemos la capa de vista previa de la cámara a la pantalla. Agregue la siguiente función para hacerlo:
private func addPreviewLayer() self.view.layer.addSublayer(self.previewLayer)
Observe que la capa de vista previa se agrega como una subcapa de una vista existente. Es por eso que lo más pronto que podemos esta función es después de que se cargue la vista, es decir, en función viewDidLoad
.
Ahora llamemos al addPreviewLayer
e inicie la sesión de captura para que coordine la entrada de la cámara con la sesión de captura. Agregue las siguientes dos líneas de código a viewDidLoad
:
self.addPreviewLayer() self.captureSession.startRunning()
Hay una cosa que hacer para que podamos ver correctamente la vista previa de la cámara. Debemos actualizar el marco de la capa de vista previa cuando se actualiza el marco de la vista del contenedor del controlador de vista.
Agregue la siguiente función para actualizar el marco de las capas de vista previa:
override func viewDidLayoutSubviews() super.viewDidLayoutSubviews() self.previewLayer.frame = self.view.bounds
Los CALayer
requieren la configuración manual del marco. AVCaptureVideoPreviewLayer
es una subclase de CALayer
. En este caso, estamos configurando la capa de vista previa para cubrir toda la pantalla.
Se agregó la capa de vista previa de la cámara a la pantalla.
Una última cosa antes de que podamos ejecutar la aplicación y mostrar la vista previa de la cámara. La aplicación requiere permiso del usuario para acceder a la cámara. La cámara se considera privada. Todos los datos considerados privados o de privacidad en iOS requieren que la aplicación:
- Declarar el requisito de uso de dicho aspecto considerado de privacidad.
- Solicitar permiso de usuario en tiempo de ejecución.
No necesitaremos gestionar los permisos de usuario en tiempo de ejecución. Asumiremos que el usuario autorizará el uso de la cámara. Sin embargo, si el usuario niega el permiso, nuestra aplicación se bloqueará.
Para la primera parte tenemos que declarar que la aplicación hace uso de la cámara. Necesitamos declarar esto en el Info.plist
archivo de la aplicación.
Agregar la clave NSCameraUsageDescription
con valor de cadena This message will be displayed to the user when requesting camera permission
.
Una vez NSCameraUsageDescription
se ingresa Xcode reemplazará la clave con una descripción más fácil de usar de la clave para mostrarla en el editor: Privacy — Camera Usage Description
.
Ejecute la aplicación en un dispositivo y acepte el permiso de la cámara. ¡Ahora debería ver la transmisión de la cámara!
Es importante tener en cuenta que el código utilizado en este paso asume que se ejecutará en un dispositivo. Todos los dispositivos iOS tienen cámaras traseras.
Sin embargo, la aplicación se bloqueará si se ejecuta en un simulador, ya que los simuladores no tienen cámaras y tampoco son capaces de usar una cámara conectada a macOS.
3. Procesando la imagen de la cámara
A continuación, obtengamos las imágenes de alimentación de la cámara para su procesamiento. Para tal tarea, necesitaremos hacer uso de AVCaptureVideoDataOutput
. Agregue la siguiente propiedad a ViewController.swift
:
private let videoOutput = AVCaptureVideoDataOutput()
Podemos decir videoOutput
para enviar las imágenes de alimentación de la cámara a un controlador de nuestra elección. Configuremos el videoOutput
y agregarlo a la sesión de captura. Agregue la siguiente función para hacerlo:
private func addVideoOutput() self.videoOutput.videoSettings = [(kCVPixelBufferPixelFormatTypeKey as NSString) : NSNumber(value: kCVPixelFormatType_32BGRA)] as [String : Any] self.videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "my.image.handling.queue")) self.captureSession.addOutput(self.videoOutput)
En el código de arriba, primero configuramos la imagen formato de pixel para recibir. En este caso, especificamos que cada píxel de la imagen debe tener un formato azul-verde-rojo-alfa
de 32 bits
(32BGRA
).
A continuación te contamos videoOutput
para enviar la imagen de la cámara a nuestro ViewController
instancia en un hilo de fondo en serie. Finalmente agregamos videoOutput
como parte de la sesión de captura, recibirá la alimentación de la cámara y la reenviará.
Es posible que haya notado que Xcode se queja de que no podemos configurar nuestro ViewController
instancia como el controlador de la salida de alimentación de la cámara.
Eso se debe a que para convertirse en un controlador de salida de video, la clase debe cumplir con AVCaptureVideoDataOutputSampleBufferDelegate
.
Cambie la declaración de la clase ViewController
a lo siguiente:
class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
Ahora estamos listos para recibir la imagen de la cámara. Para hacerlo, agregue lo siguiente Función de protocolo AVCaptureVideoDataOutputSampleBufferDelegate
:
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) guard let frame = CMSampleBufferGetImageBuffer(sampleBuffer) else debugPrint("unable to get image from sample buffer") return print("did receive image frame") // process image here
El código anterior extrae el búfer de imagen del búfer de muestra. CMSampleBuffer
puede contener diferentes tipos de medios audiovisuales. Por lo tanto, primero nos aseguramos de que la muestra contenga una imagen.
Antes de que podamos recibir las imágenes de la cámara, debemos agregar la salida de video a la sesión de captura. Agregue la siguiente línea a viewDidLoad
antes de self.captureSession.startRunning()
:
self.addVideoOutput()
Ejecute la aplicación en un dispositivo y observe cómo entran esos marcos en la consola (Ver > Área de depuración > Activar consola).
Gracias por leer este tutorial.
Añadir comentario