Share via


Controlli Fotocamera manuali in Xamarin.iOS

I controlli Fotocamera manuali, forniti da AVFoundation Framework in iOS 8, consentono a un'applicazione mobile di assumere il controllo completo sulla fotocamera di un dispositivo iOS. Questo livello di controllo con granularità fine può essere utilizzato per creare applicazioni di fotocamera a livello professionale e fornire composizioni dell'artista modificando i parametri della fotocamera durante l'acquisizione di un'immagine o un video.

Questi controlli possono essere utili anche quando si sviluppano applicazioni scientifiche o industriali, in cui i risultati sono meno orientati verso la correttezza o la bellezza dell'immagine, e sono maggiormente orientati verso l'evidenziazione di alcune caratteristiche o elementi dell'immagine scattata.

Oggetti di acquisizione AVFoundation

Se si acquisiscono video o immagini ancora usando la fotocamera in un dispositivo iOS, il processo usato per acquisire tali immagini è in gran parte lo stesso. Ciò vale per le applicazioni che usano i controlli predefiniti della fotocamera automatizzata o quelli che sfruttano i nuovi controlli manuali Fotocamera:

Panoramica di AVFoundation Capture Objects

L'input viene ricavato da un AVCaptureDeviceInput oggetto in un AVCaptureSession tramite un oggetto AVCaptureConnection. Il risultato è l'output come immagine ancora o come flusso video. L'intero processo è controllato da un oggetto AVCaptureDevice.

Controlli manuali forniti

Usando le nuove API fornite da iOS 8, l'applicazione può assumere il controllo delle funzionalità della fotocamera seguenti:

  • Stato attivo manuale: consentendo all'utente finale di assumere direttamente il controllo dello stato attivo, un'applicazione può fornire un maggiore controllo sull'immagine acquisita.
  • Esposizione manuale: fornendo un controllo manuale sull'esposizione, un'applicazione può offrire maggiore libertà agli utenti e consentire loro di ottenere un aspetto stilizzato.
  • Bilanciamento del bianco manuale: il bilanciamento del bianco viene usato per regolare il colore in un'immagine, spesso per renderlo realistico. Diverse fonti di luce hanno temperature di colore diverse e le impostazioni della fotocamera usate per acquisire un'immagine vengono regolate per compensare queste differenze. Anche in questo caso, consentendo all'utente di controllare il bilanciamento del bianco, gli utenti possono apportare modifiche che non possono essere eseguite automaticamente.

iOS 8 offre estensioni e miglioramenti alle API iOS esistenti per fornire questo controllo granulare sul processo di acquisizione delle immagini.

Requisiti

Per completare i passaggi presentati in questo articolo, è necessario quanto segue:

  • Xcode 7+ e iOS 8 o versione successiva: le API Xcode 7 e iOS 8 o successive di Apple devono essere installate e configurate nel computer dello sviluppatore.
  • Visual Studio per Mac: la versione più recente di Visual Studio per Mac deve essere installata e configurata nel dispositivo utente.
  • Dispositivo iOS 8: un dispositivo iOS che esegue la versione più recente di iOS 8. Fotocamera funzionalità non possono essere testate nel simulatore iOS.

Configurazione generale dell'acquisizione AV

Quando si registrano video in un dispositivo iOS, è sempre necessario un codice di configurazione generale. Questa sezione illustra la configurazione minima necessaria per registrare video dalla fotocamera del dispositivo iOS e visualizzare il video in tempo reale in un oggetto UIImageView.

Delegato del buffer di esempio di output

Uno dei primi elementi necessari sarà un delegato per monitorare il buffer di output di esempio e visualizzare un'immagine afferrata dal buffer a un UIImageView nell'interfaccia utente dell'applicazione.

La routine seguente monitorerà il buffer di esempio e aggiornerà l'interfaccia utente:

using System;
using Foundation;
using UIKit;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using AVFoundation;
using CoreVideo;
using CoreMedia;
using CoreGraphics;

namespace ManualCameraControls
{
    public class OutputRecorder : AVCaptureVideoDataOutputSampleBufferDelegate
    {
        #region Computed Properties
        public UIImageView DisplayView { get; set; }
        #endregion

        #region Constructors
        public OutputRecorder ()
        {

        }
        #endregion

        #region Private Methods
        private UIImage GetImageFromSampleBuffer(CMSampleBuffer sampleBuffer) {

            // Get a pixel buffer from the sample buffer
            using (var pixelBuffer = sampleBuffer.GetImageBuffer () as CVPixelBuffer) {
                // Lock the base address
                pixelBuffer.Lock (0);

                // Prepare to decode buffer
                var flags = CGBitmapFlags.PremultipliedFirst | CGBitmapFlags.ByteOrder32Little;

                // Decode buffer - Create a new colorspace
                using (var cs = CGColorSpace.CreateDeviceRGB ()) {

                    // Create new context from buffer
                    using (var context = new CGBitmapContext (pixelBuffer.BaseAddress,
                        pixelBuffer.Width,
                        pixelBuffer.Height,
                        8,
                        pixelBuffer.BytesPerRow,
                        cs,
                        (CGImageAlphaInfo)flags)) {

                        // Get the image from the context
                        using (var cgImage = context.ToImage ()) {

                            // Unlock and return image
                            pixelBuffer.Unlock (0);
                            return UIImage.FromImage (cgImage);
                        }
                    }
                }
            }
        }
        #endregion

        #region Override Methods
        public override void DidOutputSampleBuffer (AVCaptureOutput captureOutput, CMSampleBuffer sampleBuffer, AVCaptureConnection connection)
        {
            // Trap all errors
            try {
                // Grab an image from the buffer
                var image = GetImageFromSampleBuffer(sampleBuffer);

                // Display the image
                if (DisplayView !=null) {
                    DisplayView.BeginInvokeOnMainThread(() => {
                        // Set the image
                        if (DisplayView.Image != null) DisplayView.Image.Dispose();
                        DisplayView.Image = image;

                        // Rotate image to the correct display orientation
                        DisplayView.Transform = CGAffineTransform.MakeRotation((float)Math.PI/2);
                    });
                }

                // IMPORTANT: You must release the buffer because AVFoundation has a fixed number
                // of buffers and will stop delivering frames if it runs out.
                sampleBuffer.Dispose();
            }
            catch(Exception e) {
                // Report error
                Console.WriteLine ("Error sampling buffer: {0}", e.Message);
            }
        }
        #endregion
    }
}

Con questa routine sul posto, AppDelegate può essere modificato per aprire una sessione di acquisizione AV per registrare un feed video live.

Creazione di una sessione di acquisizione AV

La sessione di acquisizione AV viene usata per controllare la registrazione di video live dalla fotocamera del dispositivo iOS ed è necessaria per ottenere video in un'applicazione iOS. Poiché l'applicazione di esempio ManualCameraControl usa la sessione di acquisizione in diverse posizioni, verrà configurata in AppDelegate e resa disponibile per l'intera applicazione.

Eseguire le operazioni seguenti per modificare l'applicazione AppDelegate e aggiungere il codice necessario:

  1. Fare doppio clic sul AppDelegate.cs file nel Esplora soluzioni per aprirlo per la modifica.

  2. Aggiungere le istruzioni using seguenti all'inizio del file :

    using System;
    using Foundation;
    using UIKit;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Linq;
    using AVFoundation;
    using CoreVideo;
    using CoreMedia;
    using CoreGraphics;
    using CoreFoundation;
    
  3. Aggiungere le variabili private e le proprietà calcolate seguenti alla AppDelegate classe :

    #region Private Variables
    private NSError Error;
    #endregion
    
    #region Computed Properties
    public override UIWindow Window {get;set;}
    public bool CameraAvailable { get; set; }
    public AVCaptureSession Session { get; set; }
    public AVCaptureDevice CaptureDevice { get; set; }
    public OutputRecorder Recorder { get; set; }
    public DispatchQueue Queue { get; set; }
    public AVCaptureDeviceInput Input { get; set; }
    #endregion
    
  4. Eseguire l'override del metodo completato e modificarlo in:

    public override void FinishedLaunching (UIApplication application)
    {
        // Create a new capture session
        Session = new AVCaptureSession ();
        Session.SessionPreset = AVCaptureSession.PresetMedium;
    
        // Create a device input
        CaptureDevice = AVCaptureDevice.DefaultDeviceWithMediaType (AVMediaType.Video);
        if (CaptureDevice == null) {
            // Video capture not supported, abort
            Console.WriteLine ("Video recording not supported on this device");
            CameraAvailable = false;
            return;
        }
    
        // Prepare device for configuration
        CaptureDevice.LockForConfiguration (out Error);
        if (Error != null) {
            // There has been an issue, abort
            Console.WriteLine ("Error: {0}", Error.LocalizedDescription);
            CaptureDevice.UnlockForConfiguration ();
            return;
        }
    
        // Configure stream for 15 frames per second (fps)
        CaptureDevice.ActiveVideoMinFrameDuration = new CMTime (1, 15);
    
        // Unlock configuration
        CaptureDevice.UnlockForConfiguration ();
    
        // Get input from capture device
        Input = AVCaptureDeviceInput.FromDevice (CaptureDevice);
        if (Input == null) {
            // Error, report and abort
            Console.WriteLine ("Unable to gain input from capture device.");
            CameraAvailable = false;
            return;
        }
    
        // Attach input to session
        Session.AddInput (Input);
    
        // Create a new output
        var output = new AVCaptureVideoDataOutput ();
        var settings = new AVVideoSettingsUncompressed ();
        settings.PixelFormatType = CVPixelFormatType.CV32BGRA;
        output.WeakVideoSettings = settings.Dictionary;
    
        // Configure and attach to the output to the session
        Queue = new DispatchQueue ("ManCamQueue");
        Recorder = new OutputRecorder ();
        output.SetSampleBufferDelegate (Recorder, Queue);
        Session.AddOutput (output);
    
        // Let tabs know that a camera is available
        CameraAvailable = true;
    }
    
  5. Salvare le modifiche apportate al file.

Con questo codice, i controlli manuali Fotocamera possono essere facilmente implementati per la sperimentazione e i test.

Stato attivo manuale

Consentendo all'utente finale di assumere direttamente il controllo dello stato attivo, un'applicazione può fornire un controllo più artistico sull'immagine acquisita.

Ad esempio, un fotografo professionista può ammorbidire lo stato attivo di un'immagine per ottenere un effetto Bokeh. In alternativa, creare un effetto di pull dello stato attivo.

Per gli scienziati o uno scrittore di applicazioni mediche, l'applicazione potrebbe voler spostare a livello di codice l'obiettivo per gli esperimenti. In entrambi i casi, la nuova API consente all'utente finale o all'applicazione di assumere il controllo dello stato attivo al momento in cui viene acquisita l'immagine.

Funzionamento dello stato attivo

Prima di discutere i dettagli del controllo dello stato attivo in un'applicazione IOS 8. Di seguito viene illustrato il funzionamento dello stato attivo in un dispositivo iOS:

Funzionamento dello stato attivo in un dispositivo iOS

La luce entra nell'obiettivo della fotocamera sul dispositivo iOS e si concentra su un sensore di immagine. La distanza dell'obiettivo dal sensore controlla dove il punto focale (l'area in cui l'immagine apparirà più nitida) è, in relazione al sensore. Più lontano l'obiettivo è dal sensore, gli oggetti distanza sembrano più nitidi e più vicini, gli oggetti vicini sembrano più nitidi.

In un dispositivo iOS, l'obiettivo viene spostato più vicino, o più lontano, dal sensore da magneti e sorgenti. Di conseguenza, il posizionamento esatto dell'obiettivo è impossibile, in quanto varia da dispositivo a dispositivo e può essere influenzato da parametri come l'orientamento del dispositivo o l'età del dispositivo e primavera.

Termini importanti per lo stato attivo

Quando si lavora con lo stato attivo, ci sono alcuni termini che lo sviluppatore deve avere familiarità con:

  • Profondità di Field : distanza tra gli oggetti più vicini e più lontani nello stato attivo.
  • Macro - Si tratta della fine quasi dello spettro dello stato attivo ed è la distanza più vicina in cui l'obiettivo può concentrarsi.
  • Infinity - Questa è la fine dello spettro dello stato attivo ed è la distanza più lontana in cui l'obiettivo può concentrarsi.
  • Distanza iperfocale: si tratta del punto nello spettro dello stato attivo in cui l'oggetto più lontano nella cornice si trova solo all'estremità dello stato attivo. In altre parole, questa è la posizione focale che ottimizza la profondità del campo.
  • Posizione lente : questo è ciò che controlla tutti gli altri termini precedenti. Questa è la distanza dell'obiettivo dal sensore e quindi il controller dello stato attivo.

Tenendo presenti questi termini e conoscenze, i nuovi controlli dello stato attivo manuale possono essere implementati correttamente in un'applicazione iOS 8.

Controlli dello stato attivo esistenti

iOS 7 e versioni precedenti, hanno fornito controlli dello stato attivo esistenti tramite FocusModela proprietà come:

  • AVCaptureFocusModeLocked – Lo stato attivo è bloccato in un singolo punto attivo.
  • AVCaptureFocusModeAutoFocus – La fotocamera spazza l'obiettivo attraverso tutti i punti focali fino a quando non trova lo stato attivo tagliente e poi rimane lì.
  • AVCaptureFocusModeContinuousAutoFocus – La fotocamera viene rifocus ogni volta che rileva una condizione di messa a fuoco insufficiente.

I controlli esistenti hanno fornito anche un punto di interesse impostabile tramite laFocusPointOfInterest proprietà , in modo che l'utente possa toccare per concentrarsi su una determinata area. L'applicazione può anche tenere traccia del movimento dell'obiettivo monitorando la IsAdjustingFocus proprietà.

Inoltre, la restrizione dell'intervallo AutoFocusRangeRestriction è stata fornita dalla proprietà come:

  • AVCaptureAutoFocusRangeRestrictionNear – Limita l'autofocus alle profondità vicine. Utile in situazioni come l'analisi di un codice a matrice o un codice a barre.
  • AVCaptureAutoFocusRangeRestrictionFar – Limita l'autofocus a profondità distanti. Utile nelle situazioni in cui gli oggetti noti come irrilevanti si trovano nel campo della visualizzazione (ad esempio, una cornice finestra).

Infine, è presente la SmoothAutoFocus proprietà che rallenta l'algoritmo di attivazione automatica e lo esegue in incrementi più piccoli per evitare lo spostamento di artefatti durante la registrazione del video.

Nuovi controlli dello stato attivo in iOS 8

Oltre alle funzionalità già fornite da iOS 7 e versioni successive, le funzionalità seguenti sono ora disponibili per controllare lo stato attivo in iOS 8:

  • Controllo manuale completo della posizione dell'obiettivo durante il blocco dello stato attivo.
  • Osservazione chiave-valore della posizione dell'obiettivo in qualsiasi modalità messa a fuoco.

Per implementare le funzionalità precedenti, la AVCaptureDevice classe è stata modificata per includere una proprietà di sola LensPosition lettura usata per ottenere la posizione corrente dell'obiettivo della fotocamera.

Per controllare manualmente la posizione dell'obiettivo, il dispositivo di acquisizione deve essere in modalità messa a fuoco bloccata. Esempio:

CaptureDevice.FocusMode = AVCaptureFocusMode.Locked;

Il SetFocusModeLocked metodo del dispositivo di acquisizione viene usato per regolare la posizione dell'obiettivo della fotocamera. È possibile fornire una routine di callback facoltativa per ricevere una notifica quando la modifica diventa effettiva. Esempio:

ThisApp.CaptureDevice.LockForConfiguration(out Error);
ThisApp.CaptureDevice.SetFocusModeLocked(Position.Value,null);
ThisApp.CaptureDevice.UnlockForConfiguration();

Come illustrato nel codice precedente, il dispositivo di acquisizione deve essere bloccato per la configurazione prima che sia possibile apportare una modifica in Posizione lente. I valori validi per La posizione dell'obiettivo sono compresi tra 0,0 e 1,0.

Esempio di messa a fuoco manuale

Con il codice di installazione generale dell'acquisizione AV sul posto, un UIViewController può essere aggiunto allo Storyboard dell'applicazione e configurato come segue:

Un UIViewController può essere aggiunto alle applicazioni Storyboard e configurato come illustrato di seguito per l'esempio di stato attivo manuale.

La vista contiene gli elementi principali seguenti:

  • Oggetto UIImageView che visualizzerà il feed video.
  • Oggetto UISegmentedControl che cambierà la modalità messa a fuoco da Automatico a Bloccato.
  • Oggetto UISlider che mostrerà e aggiornerà la posizione corrente dell'obiettivo.

Eseguire le operazioni seguenti per collegare il controller di visualizzazione per il controllo dello stato attivo manuale:

  1. Aggiungere le istruzioni using seguenti:

    using System;
    using Foundation;
    using UIKit;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Linq;
    using AVFoundation;
    using CoreVideo;
    using CoreMedia;
    using CoreGraphics;
    using CoreFoundation;
    using System.Timers;
    
  2. Aggiungere le variabili private seguenti:

    #region Private Variables
    private NSError Error;
    private bool Automatic = true;
    #endregion
    
  3. Aggiungere le proprietà calcolate seguenti:

    #region Computed Properties
    public AppDelegate ThisApp {
        get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
    }
    public Timer SampleTimer { get; set; }
    #endregion
    
  4. Eseguire l'override del ViewDidLoad metodo e aggiungere il codice seguente:

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
    
        // Hide no camera label
        NoCamera.Hidden = ThisApp.CameraAvailable;
    
        // Attach to camera view
        ThisApp.Recorder.DisplayView = CameraView;
    
        // Create a timer to monitor and update the UI
        SampleTimer = new Timer (5000);
        SampleTimer.Elapsed += (sender, e) => {
            // Update position slider
            Position.BeginInvokeOnMainThread(() =>{
                Position.Value = ThisApp.Input.Device.LensPosition;
            });
        };
    
        // Watch for value changes
        Segments.ValueChanged += (object sender, EventArgs e) => {
    
            // Lock device for change
            ThisApp.CaptureDevice.LockForConfiguration(out Error);
    
            // Take action based on the segment selected
            switch(Segments.SelectedSegment) {
            case 0:
                // Activate auto focus and start monitoring position
                Position.Enabled = false;
                ThisApp.CaptureDevice.FocusMode = AVCaptureFocusMode.ContinuousAutoFocus;
                SampleTimer.Start();
                Automatic = true;
                break;
            case 1:
                // Stop auto focus and allow the user to control the camera
                SampleTimer.Stop();
                ThisApp.CaptureDevice.FocusMode = AVCaptureFocusMode.Locked;
                Automatic = false;
                Position.Enabled = true;
                break;
            }
    
            // Unlock device
            ThisApp.CaptureDevice.UnlockForConfiguration();
        };
    
        // Monitor position changes
        Position.ValueChanged += (object sender, EventArgs e) => {
    
            // If we are in the automatic mode, ignore changes
            if (Automatic) return;
    
            // Update Focus position
            ThisApp.CaptureDevice.LockForConfiguration(out Error);
            ThisApp.CaptureDevice.SetFocusModeLocked(Position.Value,null);
            ThisApp.CaptureDevice.UnlockForConfiguration();
        };
    }
    
  5. Eseguire l'override del ViewDidAppear metodo e aggiungere quanto segue per avviare la registrazione al caricamento della visualizzazione:

    public override void ViewDidAppear (bool animated)
    {
        base.ViewDidAppear (animated);
    
        // Start udating the display
        if (ThisApp.CameraAvailable) {
            // Remap to this camera view
            ThisApp.Recorder.DisplayView = CameraView;
    
            ThisApp.Session.StartRunning ();
            SampleTimer.Start ();
        }
    }
    
  6. Con la fotocamera in modalità Auto, il dispositivo di scorrimento si muove automaticamente quando la fotocamera regola lo stato attivo:

    Il dispositivo di scorrimento verrà spostato automaticamente quando la fotocamera regola lo stato attivo in questa app di esempio

  7. Toccare il segmento Bloccato e trascinare il dispositivo di scorrimento della posizione per regolare manualmente la posizione dell'obiettivo:

    Regolazione manuale della posizione dell'obiettivo

  8. Arrestare l'applicazione.

Il codice precedente ha mostrato come monitorare la posizione dell'obiettivo quando la fotocamera è in modalità automatica o usare un dispositivo di scorrimento per controllare la posizione dell'obiettivo quando è in modalità bloccato.

Esposizione manuale

L'esposizione si riferisce alla luminosità di un'immagine rispetto alla luminosità della sorgente ed è determinata dalla quantità di luce che colpisce il sensore, per quanto tempo e dal livello di guadagno del sensore (mapping ISO). Fornendo un controllo manuale sull'esposizione, un'applicazione può fornire maggiore libertà all'utente finale e consentire loro di ottenere un aspetto stilizzato.

Usando i controlli di esposizione manuale, l'utente può acquisire un'immagine da non realisticamente brillante a scura e moody:

Un esempio di immagine che mostra l'esposizione da unrealisticamente brillante a scuro e moody

Anche in questo caso, questa operazione può essere eseguita automaticamente usando il controllo programmatico per le applicazioni scientifiche o tramite controlli manuali forniti dall'interfaccia utente delle applicazioni. In entrambi i casi, le nuove API di esposizione di iOS 8 offrono un controllo granulare sulle impostazioni di esposizione della fotocamera.

Funzionamento dell'esposizione

Prima di discutere i dettagli del controllo dell'esposizione in un'applicazione IOS 8. Di seguito viene illustrato il funzionamento dell'esposizione:

Funzionamento dell'esposizione

I tre elementi di base che interagiscono per controllare l'esposizione sono:

  • Velocità otturatore: periodo di tempo in cui l'otturatore è aperto per consentire la luce sul sensore della fotocamera. Più breve è il tempo di apertura dell'otturatore, minore è la luce e l'immagine più nitida è (minore sfocatura del movimento). Più l'otturatore è aperto, maggiore è la luce è lasciato in e più sfocatura del movimento che si verifica.
  • ISO Mapping – Questo è un termine preso in prestito dalla fotografia cinematografica e si riferisce alla sensibilità delle sostanze chimiche nel film alla luce. I valori ISO bassi nel film hanno una riproduzione del colore meno granulare e più fine; valori ISO bassi nei sensori digitali hanno meno rumore del sensore, ma meno luminosità. Maggiore è il valore ISO, più luminoso è l'immagine, ma con più rumore del sensore. "ISO" su un sensore digitale è una misura di guadagno elettronico, non una caratteristica fisica.
  • Aperture lente : questa è la dimensione dell'apertura dell'obiettivo. In tutti i dispositivi iOS l'apertura dell'obiettivo è fissa, quindi gli unici due valori che possono essere usati per regolare l'esposizione sono Velocità otturatore e ISO.

Funzionamento dell'esposizione automatica continua

Prima di apprendere il funzionamento dell'esposizione manuale, è consigliabile comprendere il funzionamento dell'esposizione automatica continua in un dispositivo iOS.

Funzionamento dell'esposizione automatica continua in un dispositivo iOS

Primo è il blocco di esposizione automatica, ha il compito di calcolare l'esposizione ideale ed è costantemente alimentato statistiche di misurazione. Usa queste informazioni per calcolare la combinazione ottimale di ISO e Velocità otturatore per ottenere la scena ben illuminata. Questo ciclo viene definito ciclo AE.

Funzionamento dell'esposizione bloccata

Si esaminerà ora il funzionamento dell'esposizione bloccata nei dispositivi iOS.

Funzionamento dell'esposizione bloccata nei dispositivi iOS

Anche in questo caso, si dispone del blocco di esposizione automatica che sta tentando di calcolare i valori ottimali di iOS e Durata. In questa modalità, tuttavia, il blocco AE viene disconnesso dal motore statistiche di misurazione.

Controlli di esposizione esistenti

iOS 7 e versioni successive forniscono i controlli Esposizione esistenti seguenti tramite la ExposureMode proprietà :

  • AVCaptureExposureModeLocked : campiona la scena una sola volta e usa tali valori in tutta la scena.
  • AVCaptureExposureModeContinuousAutoExposure – Campiona la scena continuamente per assicurarsi che sia ben illuminata.

Può ExposurePointOfInterest essere usato per toccare per esporre la scena selezionando un oggetto di destinazione da esporre e l'applicazione può monitorare la proprietà per vedere quando viene modificata l'esposizione AdjustingExposure .

Nuovi controlli di esposizione in iOS 8

Oltre alle funzionalità già fornite da iOS 7 e versioni successive, sono ora disponibili le funzionalità seguenti per controllare l'esposizione in iOS 8:

  • Esposizione personalizzata completamente manuale.
  • Ottenere, impostare e chiave-valore osservare IOS e Velocità otturatore (durata).

Per implementare le funzionalità precedenti, è stata aggiunta una nuova AVCaptureExposureModeCustom modalità. Quando la fotocamera in è la modalità personalizzata, è possibile usare il codice seguente per regolare la durata dell'esposizione e l'ISO:

CaptureDevice.LockForConfiguration(out Error);
CaptureDevice.LockExposure(DurationValue,ISOValue,null);
CaptureDevice.UnlockForConfiguration();

Nelle modalità Auto e Locked l'applicazione può modificare la distorsione della routine di esposizione automatica usando il codice seguente:

CaptureDevice.LockForConfiguration(out Error);
CaptureDevice.SetExposureTargetBias(Value,null);
CaptureDevice.UnlockForConfiguration();

Gli intervalli di impostazioni minimo e massimo dipendono dal dispositivo su cui è in esecuzione l'applicazione, quindi non devono mai essere hardcoded. Usare invece le proprietà seguenti per ottenere gli intervalli di valori minimo e massimo:

  • CaptureDevice.MinExposureTargetBias
  • CaptureDevice.MaxExposureTargetBias
  • CaptureDevice.ActiveFormat.MinISO
  • CaptureDevice.ActiveFormat.MaxISO
  • CaptureDevice.ActiveFormat.MinExposureDuration
  • CaptureDevice.ActiveFormat.MaxExposureDuration

Come illustrato nel codice precedente, il dispositivo di acquisizione deve essere bloccato per la configurazione prima di apportare una modifica dell'esposizione.

Esempio di esposizione manuale

Con il codice di installazione generale dell'acquisizione AV sul posto, un UIViewController può essere aggiunto allo Storyboard dell'applicazione e configurato come segue:

Un UIViewController può essere aggiunto alle applicazioni Storyboard e configurato come illustrato di seguito per l'esempio di esposizione manuale.

La vista contiene gli elementi principali seguenti:

  • Oggetto UIImageView che visualizzerà il feed video.
  • Oggetto UISegmentedControl che cambierà la modalità messa a fuoco da Automatico a Bloccato.
  • Quattro UISlider controlli che visualizzeranno e aggiorneranno Offset, Duration, ISO e Bias.

Eseguire le operazioni seguenti per collegare il controller di visualizzazione per il controllo dell'esposizione manuale:

  1. Aggiungere le istruzioni using seguenti:

    using System;
    using Foundation;
    using UIKit;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Linq;
    using AVFoundation;
    using CoreVideo;
    using CoreMedia;
    using CoreGraphics;
    using CoreFoundation;
    using System.Timers;
    
  2. Aggiungere le variabili private seguenti:

    #region Private Variables
    private NSError Error;
    private bool Automatic = true;
    private nfloat ExposureDurationPower = 5;
    private nfloat ExposureMinimumDuration = 1.0f/1000.0f;
    #endregion
    
  3. Aggiungere le proprietà calcolate seguenti:

    #region Computed Properties
    public AppDelegate ThisApp {
        get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
    }
    public Timer SampleTimer { get; set; }
    #endregion
    
  4. Eseguire l'override del ViewDidLoad metodo e aggiungere il codice seguente:

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
    
        // Hide no camera label
        NoCamera.Hidden = ThisApp.CameraAvailable;
    
        // Attach to camera view
        ThisApp.Recorder.DisplayView = CameraView;
    
        // Set min and max values
        Offset.MinValue = ThisApp.CaptureDevice.MinExposureTargetBias;
        Offset.MaxValue = ThisApp.CaptureDevice.MaxExposureTargetBias;
    
        Duration.MinValue = 0.0f;
        Duration.MaxValue = 1.0f;
    
        ISO.MinValue = ThisApp.CaptureDevice.ActiveFormat.MinISO;
        ISO.MaxValue = ThisApp.CaptureDevice.ActiveFormat.MaxISO;
    
        Bias.MinValue = ThisApp.CaptureDevice.MinExposureTargetBias;
        Bias.MaxValue = ThisApp.CaptureDevice.MaxExposureTargetBias;
    
        // Create a timer to monitor and update the UI
        SampleTimer = new Timer (5000);
        SampleTimer.Elapsed += (sender, e) => {
            // Update position slider
            Offset.BeginInvokeOnMainThread(() =>{
                Offset.Value = ThisApp.Input.Device.ExposureTargetOffset;
            });
    
            Duration.BeginInvokeOnMainThread(() =>{
                var newDurationSeconds = CMTimeGetSeconds(ThisApp.Input.Device.ExposureDuration);
                var minDurationSeconds = Math.Max(CMTimeGetSeconds(ThisApp.CaptureDevice.ActiveFormat.MinExposureDuration), ExposureMinimumDuration);
                var maxDurationSeconds = CMTimeGetSeconds(ThisApp.CaptureDevice.ActiveFormat.MaxExposureDuration);
                var p = (newDurationSeconds - minDurationSeconds) / (maxDurationSeconds - minDurationSeconds);
                Duration.Value = (float)Math.Pow(p, 1.0f/ExposureDurationPower);
            });
    
            ISO.BeginInvokeOnMainThread(() => {
                ISO.Value = ThisApp.Input.Device.ISO;
            });
    
            Bias.BeginInvokeOnMainThread(() => {
                Bias.Value = ThisApp.Input.Device.ExposureTargetBias;
            });
        };
    
        // Watch for value changes
        Segments.ValueChanged += (object sender, EventArgs e) => {
    
            // Lock device for change
            ThisApp.CaptureDevice.LockForConfiguration(out Error);
    
            // Take action based on the segment selected
            switch(Segments.SelectedSegment) {
            case 0:
                // Activate auto exposure and start monitoring position
                Duration.Enabled = false;
                ISO.Enabled = false;
                ThisApp.CaptureDevice.ExposureMode = AVCaptureExposureMode.ContinuousAutoExposure;
                SampleTimer.Start();
                Automatic = true;
                break;
            case 1:
                // Lock exposure and allow the user to control the camera
                SampleTimer.Stop();
                ThisApp.CaptureDevice.ExposureMode = AVCaptureExposureMode.Locked;
                Automatic = false;
                Duration.Enabled = false;
                ISO.Enabled = false;
                break;
            case 2:
                // Custom exposure and allow the user to control the camera
                SampleTimer.Stop();
                ThisApp.CaptureDevice.ExposureMode = AVCaptureExposureMode.Custom;
                Automatic = false;
                Duration.Enabled = true;
                ISO.Enabled = true;
                break;
            }
    
            // Unlock device
            ThisApp.CaptureDevice.UnlockForConfiguration();
        };
    
        // Monitor position changes
        Duration.ValueChanged += (object sender, EventArgs e) => {
    
            // If we are in the automatic mode, ignore changes
            if (Automatic) return;
    
            // Calculate value
            var p = Math.Pow(Duration.Value,ExposureDurationPower);
            var minDurationSeconds = Math.Max(CMTimeGetSeconds(ThisApp.CaptureDevice.ActiveFormat.MinExposureDuration),ExposureMinimumDuration);
            var maxDurationSeconds = CMTimeGetSeconds(ThisApp.CaptureDevice.ActiveFormat.MaxExposureDuration);
            var newDurationSeconds = p * (maxDurationSeconds - minDurationSeconds) +minDurationSeconds;
    
            // Update Focus position
            ThisApp.CaptureDevice.LockForConfiguration(out Error);
            ThisApp.CaptureDevice.LockExposure(CMTime.FromSeconds(p,1000*1000*1000),ThisApp.CaptureDevice.ISO,null);
            ThisApp.CaptureDevice.UnlockForConfiguration();
        };
    
        ISO.ValueChanged += (object sender, EventArgs e) => {
    
            // If we are in the automatic mode, ignore changes
            if (Automatic) return;
    
            // Update Focus position
            ThisApp.CaptureDevice.LockForConfiguration(out Error);
            ThisApp.CaptureDevice.LockExposure(ThisApp.CaptureDevice.ExposureDuration,ISO.Value,null);
            ThisApp.CaptureDevice.UnlockForConfiguration();
        };
    
        Bias.ValueChanged += (object sender, EventArgs e) => {
    
            // If we are in the automatic mode, ignore changes
            // if (Automatic) return;
    
            // Update Focus position
            ThisApp.CaptureDevice.LockForConfiguration(out Error);
            ThisApp.CaptureDevice.SetExposureTargetBias(Bias.Value,null);
            ThisApp.CaptureDevice.UnlockForConfiguration();
        };
    }
    
  5. Eseguire l'override del ViewDidAppear metodo e aggiungere quanto segue per avviare la registrazione al caricamento della visualizzazione:

    public override void ViewDidAppear (bool animated)
    {
        base.ViewDidAppear (animated);
    
        // Start udating the display
        if (ThisApp.CameraAvailable) {
            // Remap to this camera view
            ThisApp.Recorder.DisplayView = CameraView;
    
            ThisApp.Session.StartRunning ();
            SampleTimer.Start ();
        }
    }
    
  6. Con la fotocamera in modalità Automatica, i dispositivi di scorrimento si muoveranno automaticamente man mano che la fotocamera regola l'esposizione:

    I dispositivi di scorrimento verranno spostati automaticamente man mano che la fotocamera regola l'esposizione

  7. Toccare il segmento Bloccato e trascinare il dispositivo di scorrimento Bias per regolare manualmente la distorsione dell'esposizione automatica:

    Regolazione manuale della distorsione dell'esposizione automatica

  8. Toccare il segmento Personalizzato e trascinare i dispositivi di scorrimento Durata e ISO per controllare manualmente l'esposizione:

    Trascinare i dispositivi di scorrimento Durata e ISO per controllare manualmente l'esposizione

  9. Arrestare l'applicazione.

Il codice precedente ha illustrato come monitorare le impostazioni di esposizione quando la fotocamera è in modalità automatica e come usare i dispositivi di scorrimento per controllare l'esposizione quando si trova nelle modalità Bloccata o Personalizzata.

Bilanciamento del bianco manuale

I controlli di bilanciamento del bianco consentono agli utenti di regolare il bilanciamento del colosr in un'immagine per renderli più realistici. Diverse fonti di luce hanno temperature di colore diverse e le impostazioni della fotocamera usate per acquisire un'immagine devono essere regolate per compensare queste differenze. Anche in questo caso, consentendo all'utente di controllare il bilanciamento del bianco può apportare modifiche professionali che le routine automatiche non sono in grado di ottenere effetti artistici.

Immagine di esempio che mostra le regolazioni manuali di Bilanciamento del bianco

Ad esempio, la luce del giorno ha una casta blu, mentre le luci incandescenti del failover hanno una tinta arancione più calda e gialla. (Confusamente, i colori "cool" hanno temperature di colore più elevate rispetto ai colori "caldi". Le temperature dei colori sono una misura fisica, non una misura percettiva.

La mente umana è molto buona per compensare le differenze nella temperatura del colore, ma questo è qualcosa che una fotocamera non può fare. La fotocamera funziona aumentando il colore sullo spettro opposto per regolare le differenze di colore.

La nuova API di esposizione di iOS 8 consente all'applicazione di assumere il controllo del processo e fornire un controllo granulare sulle impostazioni di bilanciamento del bianco della fotocamera.

Funzionamento del bilanciamento del bianco

Prima di discutere i dettagli del controllo del bilanciamento del bianco in un'applicazione IOS 8. Di seguito viene illustrato il funzionamento del bilanciamento del bianco:

Nello studio della percezione dei colori, lo spazio dei colori RGB CIE 1931 e lo spazio colore XYZ CIE 1931 sono i primi spazi di colore definiti matematicamente. Sono stati creati dalla Commissione internazionale per l'illuminazione (CIE) nel 1931.

Cie 1931 RGB color space and CIE 1931 XYZ color space

Il grafico precedente mostra tutti i colori visibili all'occhio umano, dal blu profondo al verde brillante al rosso brillante. Qualsiasi punto del diagramma può essere tracciato con un valore X e Y, come illustrato nel grafico precedente.

Come visibile nel grafico, esistono valori X e Y che possono essere tracciati sul grafico che si trovano al di fuori dell'intervallo di visione umana e di conseguenza questi colori non possono essere riprodotti da una fotocamera.

La curva più piccola del grafico precedente è denominata Planckian Locus, che esprime la temperatura del colore (in gradi kelvin), con numeri più alti sul lato blu (più caldo) e numeri inferiori sul lato rosso (più freddo). Sono utili per situazioni di illuminazione tipiche.

In condizioni di illuminazione mista, le regolazioni di bilanciamento del bianco dovranno deviare dal Locus planckiano per apportare le modifiche necessarie. In queste situazioni, la regolazione dovrà essere spostata sul lato verde o rosso/magenta della scala CIE.

I dispositivi iOS compensano i cast di colori aumentando il guadagno di colore opposto. Ad esempio, se una scena ha troppo blu, il guadagno rosso verrà incrementato per compensare. Questi valori di guadagno vengono calibrati per dispositivi specifici in modo che siano dipendenti dal dispositivo.

Controlli di bilanciamento del bianco esistenti

iOS 7 e versioni successive hanno fornito i controlli white balance esistenti seguenti tramite WhiteBalanceMode la proprietà :

  • AVCapture WhiteBalance ModeLocked : campiona la scena una sola volta e usa questi valori in tutta la scena.
  • AVCapture WhiteBalance ModeContinuousAutoExposure – Campiona continuamente la scena per garantire che sia ben bilanciata.

E l'applicazione può monitorare la AdjustingWhiteBalance proprietà per vedere quando viene modificata l'esposizione.

Nuovi controlli di bilanciamento del bianco in iOS 8

Oltre alle funzionalità già fornite da iOS 7 e versioni successive, sono ora disponibili le funzionalità seguenti per controllare Il bilanciamento del bianco in iOS 8:

  • Controllo completamente manuale dei guadagni RGB del dispositivo.
  • Ottenere, impostare e chiave-valore Osservare i guadagni RGB del dispositivo.
  • Supporto per il bilanciamento del bianco con una scheda grigia.
  • Routine di conversione da e verso spazi di colore indipendenti dal dispositivo.

Per implementare le funzionalità precedenti, la AVCaptureWhiteBalanceGain struttura è stata aggiunta con i membri seguenti:

  • RedGain
  • GreenGain
  • BlueGain

Il guadagno massimo di bilanciamento del bianco è attualmente quattro (4) e può essere pronto dalla MaxWhiteBalanceGain proprietà. Quindi l'intervallo legale va da uno (1) a MaxWhiteBalanceGain (4) attualmente.

La DeviceWhiteBalanceGains proprietà può essere utilizzata per osservare i valori correnti. Usa SetWhiteBalanceModeLockedWithDeviceWhiteBalanceGains per regolare i guadagni di saldo quando la fotocamera è in modalità di bilanciamento del bianco bloccato.

Routine di conversione

Le routine di conversione sono state aggiunte a iOS 8 per facilitare la conversione da e verso spazi di colore indipendenti dal dispositivo. Per implementare le routine di conversione, la AVCaptureWhiteBalanceChromaticityValues struttura è stata aggiunta con i membri seguenti:

  • X - è un valore compreso tra 0 e 1.
  • Y - è un valore compreso tra 0 e 1.

È stata aggiunta anche una AVCaptureWhiteBalanceTemperatureAndTintValues struttura con i membri seguenti:

  • Temperature - è un valore a virgola mobile in gradi Kelvin.
  • Tint - è un offset dal verde o magenta da 0 a 150 con valori positivi verso la direzione verde e negativo verso il magenta.

Utilizzare i metodi e CaptureDevice.GetDeviceWhiteBalanceGainsper eseguire la CaptureDevice.GetTemperatureAndTintValuesconversione tra temperatura e tinta, cromaticità e RGB ottengono spazi di colore.

Nota

Le routine di conversione sono più accurate, più il valore da convertire è nel Locus planckiano.

Supporto per schede grigie

Apple usa il termine Gray World per fare riferimento al supporto della scheda grigia integrato in iOS 8. Consente all'utente di concentrarsi su una scheda grigia fisica che copre almeno il 50% del centro del fotogramma e usa tale elemento per regolare il bilanciamento del bianco. Lo scopo della scheda grigia è ottenere il bianco che appare neutro.

Questa operazione può essere implementata in un'applicazione richiedendo all'utente di posizionare una scheda grigia fisica davanti alla fotocamera, monitorando la GrayWorldDeviceWhiteBalanceGains proprietà e attendendo che i valori si stabilisano.

L'applicazione blocca quindi i guadagni di White Balance per il SetWhiteBalanceModeLockedWithDeviceWhiteBalanceGains metodo usando i valori della GrayWorldDeviceWhiteBalanceGains proprietà per applicare le modifiche.

Il dispositivo di acquisizione deve essere bloccato per la configurazione prima che sia possibile apportare una modifica in White Balance.

Esempio di bilanciamento del bianco manuale

Con il codice di installazione generale dell'acquisizione AV sul posto, un UIViewController può essere aggiunto allo Storyboard dell'applicazione e configurato come segue:

Un uiViewController può essere aggiunto alle applicazioni Storyboard e configurato come illustrato di seguito per l'esempio di bilanciamento del bianco manuale.

La vista contiene gli elementi principali seguenti:

  • Oggetto UIImageView che visualizzerà il feed video.
  • Oggetto UISegmentedControl che cambierà la modalità messa a fuoco da Automatico a Bloccato.
  • Due UISlider controlli che mostreranno e aggiorneranno temperatura e tinta.
  • Oggetto UIButton utilizzato per campionare uno spazio Gray Card (Gray World) e impostare il bilanciamento del bianco usando tali valori.

Eseguire le operazioni seguenti per collegare il controller di visualizzazione per il controllo di bilanciamento del bianco manuale:

  1. Aggiungere le istruzioni using seguenti:

    using System;
    using Foundation;
    using UIKit;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Linq;
    using AVFoundation;
    using CoreVideo;
    using CoreMedia;
    using CoreGraphics;
    using CoreFoundation;
    using System.Timers;
    
  2. Aggiungere le variabili private seguenti:

    #region Private Variables
    private NSError Error;
    private bool Automatic = true;
    #endregion
    
  3. Aggiungere le proprietà calcolate seguenti:

    #region Computed Properties
    public AppDelegate ThisApp {
        get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
    }
    public Timer SampleTimer { get; set; }
    #endregion
    
  4. Aggiungere il metodo privato seguente per impostare il nuovo bilanciamento del bianco Temperature e Tinta:

    #region Private Methods
    void SetTemperatureAndTint() {
        // Grab current temp and tint
        var TempAndTint = new AVCaptureWhiteBalanceTemperatureAndTintValues (Temperature.Value, Tint.Value);
    
        // Convert Color space
        var gains = ThisApp.CaptureDevice.GetDeviceWhiteBalanceGains (TempAndTint);
    
        // Set the new values
        if (ThisApp.CaptureDevice.LockForConfiguration (out Error)) {
            gains = NomralizeGains (gains);
            ThisApp.CaptureDevice.SetWhiteBalanceModeLockedWithDeviceWhiteBalanceGains (gains, null);
            ThisApp.CaptureDevice.UnlockForConfiguration ();
        }
    }
    
    AVCaptureWhiteBalanceGains NomralizeGains (AVCaptureWhiteBalanceGains gains)
    {
        gains.RedGain = Math.Max (1, gains.RedGain);
        gains.BlueGain = Math.Max (1, gains.BlueGain);
        gains.GreenGain = Math.Max (1, gains.GreenGain);
    
        float maxGain = ThisApp.CaptureDevice.MaxWhiteBalanceGain;
        gains.RedGain = Math.Min (maxGain, gains.RedGain);
        gains.BlueGain = Math.Min (maxGain, gains.BlueGain);
        gains.GreenGain = Math.Min (maxGain, gains.GreenGain);
    
        return gains;
    }
    #endregion
    
  5. Eseguire l'override del ViewDidLoad metodo e aggiungere il codice seguente:

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
    
        // Hide no camera label
        NoCamera.Hidden = ThisApp.CameraAvailable;
    
        // Attach to camera view
        ThisApp.Recorder.DisplayView = CameraView;
    
        // Set min and max values
        Temperature.MinValue = 1000f;
        Temperature.MaxValue = 10000f;
    
        Tint.MinValue = -150f;
        Tint.MaxValue = 150f;
    
        // Create a timer to monitor and update the UI
        SampleTimer = new Timer (5000);
        SampleTimer.Elapsed += (sender, e) => {
            // Convert color space
            var TempAndTint = ThisApp.CaptureDevice.GetTemperatureAndTintValues (ThisApp.CaptureDevice.DeviceWhiteBalanceGains);
    
            // Update slider positions
            Temperature.BeginInvokeOnMainThread (() => {
                Temperature.Value = TempAndTint.Temperature;
            });
    
            Tint.BeginInvokeOnMainThread (() => {
                Tint.Value = TempAndTint.Tint;
            });
        };
    
        // Watch for value changes
        Segments.ValueChanged += (sender, e) => {
            // Lock device for change
            if (ThisApp.CaptureDevice.LockForConfiguration (out Error)) {
    
                // Take action based on the segment selected
                switch (Segments.SelectedSegment) {
                case 0:
                // Activate auto focus and start monitoring position
                    Temperature.Enabled = false;
                    Tint.Enabled = false;
                    ThisApp.CaptureDevice.WhiteBalanceMode = AVCaptureWhiteBalanceMode.ContinuousAutoWhiteBalance;
                    SampleTimer.Start ();
                    Automatic = true;
                    break;
                case 1:
                // Stop auto focus and allow the user to control the camera
                    SampleTimer.Stop ();
                    ThisApp.CaptureDevice.WhiteBalanceMode = AVCaptureWhiteBalanceMode.Locked;
                    Automatic = false;
                    Temperature.Enabled = true;
                    Tint.Enabled = true;
                    break;
                }
    
                // Unlock device
                ThisApp.CaptureDevice.UnlockForConfiguration ();
            }
        };
    
        // Monitor position changes
        Temperature.TouchUpInside += (sender, e) => {
    
            // If we are in the automatic mode, ignore changes
            if (Automatic)
                return;
    
            // Update white balance
            SetTemperatureAndTint ();
        };
    
        Tint.TouchUpInside += (sender, e) => {
    
            // If we are in the automatic mode, ignore changes
            if (Automatic)
                return;
    
            // Update white balance
            SetTemperatureAndTint ();
        };
    
        GrayCardButton.TouchUpInside += (sender, e) => {
    
            // If we are in the automatic mode, ignore changes
            if (Automatic)
                return;
    
            // Get gray card values
            var gains = ThisApp.CaptureDevice.GrayWorldDeviceWhiteBalanceGains;
    
            // Set the new values
            if (ThisApp.CaptureDevice.LockForConfiguration (out Error)) {
                ThisApp.CaptureDevice.SetWhiteBalanceModeLockedWithDeviceWhiteBalanceGains (gains, null);
                ThisApp.CaptureDevice.UnlockForConfiguration ();
            }
        };
    }
    
  6. Eseguire l'override del ViewDidAppear metodo e aggiungere quanto segue per avviare la registrazione al caricamento della visualizzazione:

    public override void ViewDidAppear (bool animated)
    {
        base.ViewDidAppear (animated);
    
        // Start udating the display
        if (ThisApp.CameraAvailable) {
            // Remap to this camera view
            ThisApp.Recorder.DisplayView = CameraView;
    
            ThisApp.Session.StartRunning ();
            SampleTimer.Start ();
        }
    }
    
  7. Salvare le modifiche apportate al codice ed eseguire l'applicazione.

  8. Con la fotocamera in modalità Automatica, i dispositivi di scorrimento si muoveranno automaticamente man mano che la fotocamera regola il bilanciamento del bianco:

    I dispositivi di scorrimento verranno spostati automaticamente man mano che la fotocamera regola il bilanciamento del bianco

  9. Toccare il segmento Bloccato e trascinare i dispositivi di scorrimento Temp e Tint per regolare manualmente il bilanciamento del bianco:

    Trascinare i dispositivi di scorrimento Temp e Tint per regolare manualmente il bilanciamento del bianco

  10. Con il segmento Bloccato ancora selezionato, posizionare una scheda grigia fisica davanti alla fotocamera e toccare il pulsante Scheda grigia per regolare il bilanciamento del bianco su Gray World:

    Toccare il pulsante Scheda grigia per regolare il bilanciamento del bianco nel mondo grigio

  11. Arrestare l'applicazione.

Il codice precedente ha illustrato come monitorare le impostazioni di bilanciamento del bianco quando la fotocamera è in modalità automatica o usare i dispositivi di scorrimento per controllare il bilanciamento del bianco quando è in modalità bloccata.

Acquisizione tra parentesi quadre

L'acquisizione con parentesi quadre si basa sulle impostazioni dei controlli Fotocamera manuali presentati in precedenza e consente all'applicazione di acquisire un momento nel tempo, in diversi modi.

Semplicemente dichiarato, l'acquisizione tra parentesi quadre è un burst di immagini ancora scattate con un'ampia gamma di impostazioni, dall'immagine all'immagine.

Funzionamento dell'acquisizione tra parentesi quadre

Usando l'acquisizione tra parentesi in iOS 8, un'applicazione può impostare una serie di controlli manuali Fotocamera, eseguire un singolo comando e fare in modo che la scena corrente restituisca una serie di immagini per ognuno dei set di impostazioni manuali.

Nozioni di base sulle acquisizioni tra parentesi quadre

Anche in questo caso, l'acquisizione tra parentesi quadre è un burst di immagini ancora scattate con diverse impostazioni, dall'immagine all'immagine. I tipi di acquisizione tra parentesi quadre disponibili sono:

  • Parentesi di esposizione automatica: in cui tutte le immagini hanno una quantità di distorsione varia.
  • Parentesi di esposizione manuale: in cui tutte le immagini hanno una velocità di otturatore (durata) e una quantità ISO varia.
  • Parentesi burst semplice: una serie di immagini ancora scattate in rapida successione.

Nuovi controlli di acquisizione tra parentesi quadre in iOS 8

Tutti i comandi di acquisizione tra parentesi quadre vengono implementati nella AVCaptureStillImageOutput classe . Usare il CaptureStillImageBracketmetodo per ottenere una serie di immagini con la matrice di impostazioni specificata.

Sono state implementate due nuove classi per gestire le impostazioni:

  • AVCaptureAutoExposureBracketedStillImageSettings – Ha una proprietà, ExposureTargetBias, usata per impostare la distorsione per una parentesi di esposizione automatica.
  • AVCaptureManualExposureBracketedStillImageSettings – Ha due proprietà, ExposureDuration e ISO, usato per impostare la velocità dell'otturatore e ISO per una parentesi di esposizione manuale.

Controlli di acquisizione tra parentesi quadre Do e Don'ts

Operazioni consentite

Di seguito è riportato un elenco di operazioni da eseguire quando si usano i controlli di acquisizione tra parentesi quadre in iOS 8:

  • Preparare l'app per la situazione di acquisizione peggiore dei casi chiamando il PrepareToCaptureStillImageBracket metodo .
  • Si supponga che i buffer di esempio provengano dallo stesso pool condiviso.
  • Per rilasciare la memoria allocata da una chiamata di preparazione precedente, chiamare PrepareToCaptureStillImageBracket di nuovo e inviarla una matrice di un oggetto.

Operazioni non consentite

Di seguito è riportato un elenco di operazioni che non devono essere eseguite quando si usano i controlli di acquisizione tra parentesi quadre in iOS 8:

  • Non combinare i tipi di impostazioni di acquisizione tra parentesi quadre in un'unica acquisizione.
  • Non richiedere più di MaxBracketedCaptureStillImageCount immagini in un'unica acquisizione.

Dettagli acquisizione tra parentesi quadre

Quando si lavora con l'acquisizione con parentesi quadre in iOS 8, è necessario prendere in considerazione i dettagli seguenti:

  • Le impostazioni tra parentesi quadre sostituiscono temporaneamente le AVCaptureDevice impostazioni.
  • Le impostazioni di stabilizzazione flash e ancora immagine vengono ignorate.
  • Tutte le immagini devono usare lo stesso formato di output (jpeg, png e così via)
  • L'anteprima video può eliminare fotogrammi.
  • L'acquisizione tra parentesi quadre è supportata in tutti i dispositivi compatibili con iOS 8.

Tenendo presente queste informazioni, si esaminerà un esempio di uso dell'acquisizione tra parentesi quadre in iOS 8.

Esempio di acquisizione tra parentesi quadre

Con il codice di installazione generale dell'acquisizione AV sul posto, un UIViewController può essere aggiunto allo Storyboard dell'applicazione e configurato come segue:

Un UIViewController può essere aggiunto alle applicazioni Storyboard e configurato come illustrato nell'esempio di acquisizione tra parentesi quadre.

La vista contiene gli elementi principali seguenti:

  • Oggetto UIImageView che visualizzerà il feed video.
  • Tre UIImageViews che visualizzeranno i risultati dell'acquisizione.
  • Oggetto UIScrollView per ospitare il feed video e le visualizzazioni dei risultati.
  • Oggetto UIButton usato per acquisire un'acquisizione con parentesi quadre con alcune impostazioni predefinite.

Eseguire le operazioni seguenti per collegare il controller di visualizzazione per l'acquisizione tra parentesi quadre:

  1. Aggiungere le istruzioni using seguenti:

    using System;
    using System.Drawing;
    using Foundation;
    using UIKit;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Linq;
    using AVFoundation;
    using CoreVideo;
    using CoreMedia;
    using CoreGraphics;
    using CoreFoundation;
    using CoreImage;
    
  2. Aggiungere le variabili private seguenti:

    #region Private Variables
    private NSError Error;
    private List<UIImageView> Output = new List<UIImageView>();
    private nint OutputIndex = 0;
    #endregion
    
  3. Aggiungere le proprietà calcolate seguenti:

    #region Computed Properties
    public AppDelegate ThisApp {
        get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
    }
    #endregion
    
  4. Aggiungere il metodo privato seguente per compilare le visualizzazioni dell'immagine di output necessarie:

    #region Private Methods
    private UIImageView BuildOutputView(nint n) {
    
        // Create a new image view controller
        var imageView = new UIImageView (new CGRect (CameraView.Frame.Width * n, 0, CameraView.Frame.Width, CameraView.Frame.Height));
    
        // Load a temp image
        imageView.Image = UIImage.FromFile ("Default-568h@2x.png");
    
        // Add a label
        UILabel label = new UILabel (new CGRect (0, 20, CameraView.Frame.Width, 24));
        label.TextColor = UIColor.White;
        label.Text = string.Format ("Bracketed Image {0}", n);
        imageView.AddSubview (label);
    
        // Add to scrolling view
        ScrollView.AddSubview (imageView);
    
        // Return new image view
        return imageView;
    }
    #endregion
    
  5. Eseguire l'override del ViewDidLoad metodo e aggiungere il codice seguente:

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
    
        // Hide no camera label
        NoCamera.Hidden = ThisApp.CameraAvailable;
    
        // Attach to camera view
        ThisApp.Recorder.DisplayView = CameraView;
    
        // Setup scrolling area
        ScrollView.ContentSize = new SizeF (CameraView.Frame.Width * 4, CameraView.Frame.Height);
    
        // Add output views
        Output.Add (BuildOutputView (1));
        Output.Add (BuildOutputView (2));
        Output.Add (BuildOutputView (3));
    
        // Create preset settings
        var Settings = new AVCaptureBracketedStillImageSettings[] {
            AVCaptureAutoExposureBracketedStillImageSettings.Create(-2.0f),
            AVCaptureAutoExposureBracketedStillImageSettings.Create(0.0f),
            AVCaptureAutoExposureBracketedStillImageSettings.Create(2.0f)
        };
    
        // Wireup capture button
        CaptureButton.TouchUpInside += (sender, e) => {
            // Reset output index
            OutputIndex = 0;
    
            // Tell the camera that we are getting ready to do a bracketed capture
            ThisApp.StillImageOutput.PrepareToCaptureStillImageBracket(ThisApp.StillImageOutput.Connections[0],Settings,async (bool ready, NSError err) => {
                // Was there an error, if so report it
                if (err!=null) {
                    Console.WriteLine("Error: {0}",err.LocalizedDescription);
                }
            });
    
            // Ask the camera to snap a bracketed capture
            ThisApp.StillImageOutput.CaptureStillImageBracket(ThisApp.StillImageOutput.Connections[0],Settings, (sampleBuffer, settings, err) =>{
                // Convert raw image stream into a Core Image Image
                var imageData = AVCaptureStillImageOutput.JpegStillToNSData(sampleBuffer);
                var image = CIImage.FromData(imageData);
    
                // Display the resulting image
                Output[OutputIndex++].Image = UIImage.FromImage(image);
    
                // IMPORTANT: You must release the buffer because AVFoundation has a fixed number
                // of buffers and will stop delivering frames if it runs out.
                sampleBuffer.Dispose();
            });
        };
    }
    
  6. Eseguire l'override del ViewDidAppear metodo e aggiungere il codice seguente:

    public override void ViewDidAppear (bool animated)
    {
        base.ViewDidAppear (animated);
    
        // Start udating the display
        if (ThisApp.CameraAvailable) {
            // Remap to this camera view
            ThisApp.Recorder.DisplayView = CameraView;
    
            ThisApp.Session.StartRunning ();
        }
    }
    
    
  7. Salvare le modifiche apportate al codice ed eseguire l'applicazione.

  8. Incorniciare una scena e toccare il pulsante Acquisisci parentesi quadre:

    Inquadrare una scena e toccare il pulsante Acquisisci parentesi quadre

  9. Scorri verso destra verso sinistra per visualizzare le tre immagini scattate dall'acquisizione tra parentesi quadre:

    Scorri verso destra verso sinistra per visualizzare le tre immagini scattate dall'acquisizione tra parentesi quadre

  10. Arrestare l'applicazione.

Il codice precedente ha illustrato come configurare e acquisire un'acquisizione con parentesi di esposizione automatica in iOS 8.

Riepilogo

In questo articolo è stata illustrata un'introduzione al nuovo manuale dei controlli Fotocamera forniti da iOS 8 e sono state illustrate le nozioni di base di ciò che fanno e come funzionano. Sono stati forniti esempi di messa a fuoco manuale, esposizione manuale e bilanciamento del bianco manuale. Infine, è stato fornito un esempio che accetta un'acquisizione con parentesi quadre usando i controlli Fotocamera manuali illustrati in precedenza