Partager via


Contrôles de caméra manuelle dans Xamarin.iOS

Les contrôles de caméra manuelle, fournis par iOS AVFoundation Framework 8, permettent à une application mobile de prendre un contrôle total sur l’appareil photo d’un appareil iOS. Ce niveau de contrôle affiné peut être utilisé pour créer des applications de caméra de niveau professionnel et fournir des compositions d’artistes en modifiant les paramètres de la caméra tout en prenant une image ou une vidéo.

Ces contrôles peuvent également être utiles lors du développement d’applications scientifiques ou industrielles, où les résultats sont moins orientés vers la justesse ou la beauté de l’image, et sont orientés plus vers la mise en évidence d’une caractéristique ou d’un élément de l’image en cours de prise.

Objets de capture AVFoundation

Que vous preniez des images vidéo ou toujours à l’aide de l’appareil photo sur un appareil iOS, le processus utilisé pour capturer ces images est en grande partie le même. Cela est vrai pour les applications qui utilisent les contrôles d’appareil photo automatisés par défaut ou ceux qui tirent parti des nouveaux contrôles de caméra manuelle :

Vue d’ensemble des objets de capture AVFoundation

L’entrée est extraite d’une AVCaptureDeviceInputAVCaptureSession entrée en un moyen d’un AVCaptureConnection. Le résultat est soit une sortie en tant qu’image toujours, soit en tant que flux vidéo. L’ensemble du processus est contrôlé par un AVCaptureDevice.

Contrôles manuels fournis

À l’aide des nouvelles API fournies par iOS 8, l’application peut prendre le contrôle des fonctionnalités de caméra suivantes :

  • Focus manuel : en permettant à l’utilisateur final de prendre le contrôle du focus directement, une application peut fournir plus de contrôle sur l’image prise.
  • Exposition manuelle : en fournissant un contrôle manuel sur l’exposition, une application peut fournir plus de liberté aux utilisateurs et leur permettre d’obtenir un look stylisé.
  • Balance des blancs manuels : l’équilibre des blancs est utilisé pour ajuster la couleur dans une image, souvent pour le rendre réaliste. Différentes sources de lumière ont des températures de couleur différentes, et les paramètres de la caméra utilisés pour capturer une image sont ajustés pour compenser ces différences. Là encore, en autorisant le contrôle utilisateur sur l’équilibre blanc, les utilisateurs peuvent effectuer des ajustements qui ne peuvent pas être effectués automatiquement.

iOS 8 fournit des extensions et des améliorations apportées aux API iOS existantes pour fournir ce contrôle précis sur le processus de capture d’images.

Spécifications

Les étapes suivantes sont requises pour effectuer les étapes présentées dans cet article :

  • Xcode 7+ et iOS 8 ou ultérieur : les API Xcode 7 et iOS 8 ou ultérieures d’Apple doivent être installées et configurées sur l’ordinateur du développeur.
  • Visual Studio pour Mac : la dernière version de Visual Studio pour Mac doit être installée et configurée sur l’appareil utilisateur.
  • Appareil iOS 8 : appareil iOS exécutant la dernière version d’iOS 8. Les fonctionnalités de la caméra ne peuvent pas être testées dans le simulateur iOS.

Configuration générale de la capture AV

Lors de l’enregistrement de la vidéo sur un appareil iOS, il existe un code d’installation général qui est toujours requis. Cette section couvre la configuration minimale requise pour enregistrer la vidéo à partir de la caméra de l’appareil iOS et afficher cette vidéo en temps réel dans un UIImageView.

Exemple de délégué de mémoire tampon de sortie

L’une des premières choses nécessaires sera un délégué pour surveiller la mémoire tampon d’exemple de sortie et afficher une image extraite de la mémoire tampon vers une UIImageView interface utilisateur de l’application.

La routine suivante surveille l’exemple de mémoire tampon et met à jour l’interface utilisateur :

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

Avec cette routine en place, vous AppDelegate pouvez le modifier pour ouvrir une session de capture AV pour enregistrer un flux vidéo en direct.

Création d’une session de capture AV

La session AV Capture est utilisée pour contrôler l’enregistrement de vidéos en direct à partir de la caméra de l’appareil iOS et est nécessaire pour obtenir la vidéo dans une application iOS. Étant donné que l’exemple d’application ManualCameraControl utilise la session de capture à plusieurs endroits différents, il sera configuré dans l’application et mis à la AppDelegate disposition de l’ensemble de l’application.

Procédez comme suit pour modifier l’application AppDelegate et ajouter le code nécessaire :

  1. Double-cliquez sur le AppDelegate.cs fichier dans la Explorateur de solutions pour l’ouvrir pour modification.

  2. Ajoutez les instructions using suivantes au début du fichier :

    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. Ajoutez les variables privées et les propriétés calculées suivantes à la 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. Remplacez la méthode terminée et remplacez-la par :

    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. Enregistrez les modifications du fichier.

Avec ce code en place, les contrôles de caméra manuelle peuvent être facilement implémentés pour l’expérimentation et le test.

Focus manuel

En permettant à l’utilisateur final de prendre des contrôles du focus directement, une application peut fournir un contrôle plus artistique sur l’image prise.

Par exemple, un photographe professionnel peut adoucir le focus d’une image pour obtenir un effet Bokeh. Vous pouvez également créer un effet d’extraction de focus.

Pour les scientifiques ou un rédacteur d’applications médicales, l’application peut souhaiter déplacer par programmation l’objectif pour les expériences. De la façon dont la nouvelle API permet à l’utilisateur final ou à l’application de prendre le contrôle du focus au moment où l’image est prise.

Fonctionnement du focus

Avant de discuter des détails du contrôle du focus dans une application IOS 8. Examinons rapidement le fonctionnement du focus sur un appareil iOS :

Fonctionnement du focus dans un appareil iOS

La lumière entre dans l’objectif de l’appareil photo sur l’appareil iOS et se concentre sur un capteur d’image. La distance de l’objectif à partir des contrôles du capteur où le point focal (zone où l’image apparaîtra la plus nette) est, en relation avec le capteur. Plus l’objectif est loin du capteur, les objets de distance semblent les plus nettes et les plus proches, les objets proches semblent les plus nettes.

Dans un appareil iOS, l’objectif est déplacé plus près, ou plus loin, du capteur par des aimants et des ressorts. Par conséquent, le positionnement exact de l’objectif est impossible, car il varie de l’appareil à l’appareil et peut être affecté par des paramètres tels que l’orientation de l’appareil ou l’âge de l’appareil et du printemps.

Termes importants du focus

En cas de focus, il existe quelques termes que le développeur doit connaître :

  • Profondeur du champ : distance entre les objets les plus proches et les plus éloignés dans le focus.
  • Macro - Il s’agit de la fin proche du spectre de focus et est la distance la plus proche à laquelle l’objectif peut se concentrer.
  • Infini : il s’agit de l’extrémité éloignée du spectre de focus et est la distance la plus éloignée à laquelle l’objectif peut se concentrer.
  • Distance hyperfocale : il s’agit du point dans le spectre de focus où l’objet le plus éloigné du cadre est juste à la fin du focus. En d’autres termes, il s’agit de la position focale qui optimise la profondeur du champ.
  • Position de l’objectif : c’est ce qui contrôle tous les autres termes ci-dessus. Il s’agit de la distance de l’objectif du capteur et, par conséquent, du contrôleur de focus.

Avec ces termes et ces connaissances à l’esprit, les nouveaux contrôles de focus manuel peuvent être implémentés avec succès dans une application iOS 8.

Contrôles focus existants

iOS 7 et versions antérieures fournissaient des contrôles Focus existants via FocusModela propriété comme suit :

  • AVCaptureFocusModeLocked : le focus est verrouillé à un seul point de focus.
  • AVCaptureFocusModeAutoFocus - La caméra balaye l’objectif à travers tous les points focals jusqu’à ce qu’il trouve un focus aigu, puis reste là.
  • AVCaptureFocusModeContinuousAutoFocus : la caméra se recentre chaque fois qu’elle détecte une condition hors focus.

Les contrôles existants ont également fourni un point d’intérêt settable via laFocusPointOfInterest propriété, afin que l’utilisateur puisse appuyer pour se concentrer sur une zone particulière. L’application peut également suivre le mouvement des lentilles en surveillant la IsAdjustingFocus propriété.

En outre, la restriction de plage a été fournie par la AutoFocusRangeRestriction propriété comme suit :

  • AVCaptureAutoFocusRangeRestrictionNear : limite l’afactive aux profondeurs voisines. Utile dans des situations telles que l’analyse d’un code QR ou d’un code-barres.
  • AVCaptureAutoFocusRangeRestrictionFar : limite l’afactive aux profondeurs distantes. Utile dans les situations où les objets connus comme non pertinents se trouvent dans le champ d’affichage (par exemple, un cadre de fenêtre).

Enfin, il existe la SmoothAutoFocus propriété qui ralentit l’algorithme de focus automatique et les effectue par incréments plus petits pour éviter de déplacer des artefacts lors de l’enregistrement de la vidéo.

Nouveaux contrôles Focus dans iOS 8

Outre les fonctionnalités déjà fournies par iOS 7 et versions ultérieures, les fonctionnalités suivantes sont désormais disponibles pour contrôler le focus dans iOS 8 :

  • Contrôle manuel complet de la position de l’objectif lors du verrouillage du focus.
  • Observation clé-valeur de la position de l’objectif en tout mode focus.

Pour implémenter les fonctionnalités ci-dessus, la AVCaptureDevice classe a été modifiée pour inclure une propriété en lecture seule LensPosition utilisée pour obtenir la position actuelle de l’objectif de caméra.

Pour contrôler manuellement la position de l’objectif, l’appareil de capture doit être en mode Focus verrouillé. Exemple :

CaptureDevice.FocusMode = AVCaptureFocusMode.Locked;

La SetFocusModeLocked méthode de l’appareil de capture est utilisée pour ajuster la position de l’objectif de la caméra. Une routine de rappel facultative peut être envoyée pour recevoir une notification lorsque la modification prend effet. Exemple :

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

Comme indiqué dans le code ci-dessus, l’appareil de capture doit être verrouillé pour la configuration avant qu’une modification de la position de l’objectif puisse être effectuée. Les valeurs de position de l’objectif valide sont comprises entre 0,0 et 1,0.

Exemple de focus manuel

Avec le code général de configuration de capture AV en place, vous pouvez ajouter un UIViewController storyboard à l’application et le configurer comme suit :

Un UIViewController peut être ajouté aux applications Storyboard et configuré comme illustré ici pour l’exemple de focus manuel.

La vue contient les éléments principaux suivants :

  • Qui UIImageView affiche le flux vidéo.
  • Qui UISegmentedControl va changer le mode Focus de Automatique à Verrouillé.
  • Qui UISlider affichera et mettra à jour la position actuelle de l’objectif.

Procédez comme suit pour connecter le contrôleur de vue pour le contrôle de focus manuel :

  1. Ajoutez les instructions using suivantes :

    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. Ajoutez les variables privées suivantes :

    #region Private Variables
    private NSError Error;
    private bool Automatic = true;
    #endregion
    
  3. Ajoutez les propriétés calculées suivantes :

    #region Computed Properties
    public AppDelegate ThisApp {
        get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
    }
    public Timer SampleTimer { get; set; }
    #endregion
    
  4. Remplacez la ViewDidLoad méthode et ajoutez le code suivant :

    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. Remplacez la ViewDidAppear méthode et ajoutez ce qui suit pour démarrer l’enregistrement lorsque l’affichage se charge :

    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. Avec l’appareil photo en mode Automatique, le curseur se déplace automatiquement à mesure que l’appareil photo ajuste le focus :

    Le curseur se déplace automatiquement à mesure que la caméra ajuste le focus dans cet exemple d’application

  7. Appuyez sur le segment Verrouillé et faites glisser le curseur de position pour ajuster la position de l’objectif manuellement :

    Ajustement manuel de la position de l’objectif

  8. Arrêtez l’application.

Le code ci-dessus montre comment surveiller la position de l’objectif lorsque l’appareil photo est en mode automatique ou utiliser un curseur pour contrôler la position de l’objectif lorsqu’elle est en mode verrouillé.

Exposition manuelle

L’exposition fait référence à la luminosité d’une image par rapport à la luminosité source et est déterminée par la quantité de lumière qui atteint le capteur, pendant combien de temps et par le niveau de gain du capteur (mappage ISO). En fournissant un contrôle manuel sur l’exposition, une application peut fournir une plus grande liberté à l’utilisateur final et lui permettre d’obtenir un look stylisé.

À l’aide des contrôles d’exposition manuelle, l’utilisateur peut prendre une image d’une image irréalistement lumineuse à l’obscurité et à l’humeur :

Exemple d’image montrant l’exposition d’une lumière irréaliste à l’obscurité et à l’humeur

Là encore, cette opération peut être effectuée automatiquement à l’aide du contrôle programmatique pour les applications scientifiques ou via des contrôles manuels fournis par l’interface utilisateur des applications. De toute façon, les nouvelles API d’exposition iOS 8 fournissent un contrôle précis sur les paramètres d’exposition de l’appareil photo.

Fonctionnement de l’exposition

Avant de discuter des détails du contrôle de l’exposition dans une application IOS 8. Examinons rapidement le fonctionnement de l’exposition :

Fonctionnement de l’exposition

Les trois éléments de base qui se réunissent pour contrôler l’exposition sont les suivants :

  • Vitesse d’obturation : il s’agit de la durée pendant laquelle l’obturateur est ouvert pour laisser la lumière sur le capteur de l’appareil photo. Plus la durée de l’obturation est ouverte, moins la lumière est lâchée et plus l’image est nette (moins flou de mouvement). Plus l’obturateur est ouvert, plus la lumière est lâchée et plus le flou de mouvement se produit.
  • Mappage ISO : il s’agit d’un terme emprunté à la photographie de film et fait référence à la sensibilité des produits chimiques dans le film à la lumière. Les valeurs ISO faibles du film ont moins de grain et de reproduction de couleur plus fine ; les valeurs ISO faibles sur les capteurs numériques ont moins de bruit de capteur, mais moins de luminosité. Plus la valeur ISO est élevée, plus l’image est brillante, mais avec plus de bruit de capteur. « ISO » sur un capteur numérique est une mesure du gain électronique, et non d’une caractéristique physique.
  • Ouverture de lentille : il s’agit de la taille de l’ouverture de l’objectif. Sur tous les appareils iOS, l’ouverture de l’objectif est fixe, de sorte que les deux seules valeurs qui peuvent être utilisées pour ajuster l’exposition sont la vitesse d’obturation et ISO.

Fonctionnement de l’exposition automatique continue

Avant d’apprendre comment fonctionne l’exposition manuelle, il est judicieux de comprendre comment l’exposition automatique continue fonctionne dans un appareil iOS.

Fonctionnement de l’exposition automatique continue dans un appareil iOS

Tout d’abord, le bloc d’exposition automatique a le travail de calcul de l’exposition idéale et est continuellement alimenté statistiques de contrôle. Il utilise ces informations pour calculer le mélange optimal d’ISO et de vitesse d’obturation pour obtenir la scène bien éclairée. Ce cycle est appelé boucle AE.

Fonctionnement de l’exposition verrouillée

Examinons ensuite le fonctionnement de l’exposition verrouillée sur les appareils iOS.

Fonctionnement de l’exposition verrouillée sur les appareils iOS

Là encore, vous disposez du bloc d’exposition automatique qui tente de calculer les valeurs optimales d’iOS et de durée. Toutefois, dans ce mode, le bloc AE est déconnecté du moteur Metering Stats.

Contrôles d’exposition existants

iOS 7 et versions ultérieures, fournissez les contrôles d’exposition existants suivants via la ExposureMode propriété :

  • AVCaptureExposureModeLocked : échantillonne la scène une fois et utilise ces valeurs dans toute la scène.
  • AVCaptureExposureModeContinuousAutoExposure – Échantillonne la scène en continu pour s’assurer qu’elle est bien allumée.

Vous ExposurePointOfInterest pouvez l’utiliser pour appuyer pour exposer la scène en sélectionnant un objet cible à exposer, et l’application peut surveiller la AdjustingExposure propriété pour voir quand l’exposition est ajustée.

Nouveaux contrôles d’exposition dans iOS 8

Outre les fonctionnalités déjà fournies par iOS 7 et versions ultérieures, les fonctionnalités suivantes sont désormais disponibles pour contrôler l’exposition dans iOS 8 :

  • Exposition personnalisée entièrement manuelle.
  • Obtenez, définissez et clé-valeur observez les E/S et la vitesse d’obturation (durée).

Pour implémenter les fonctionnalités ci-dessus, un nouveau AVCaptureExposureModeCustom mode a été ajouté. Lorsque l’appareil photo est en mode personnalisé, le code suivant peut être utilisé pour ajuster la durée d’exposition et l’ISO :

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

Dans les modes Auto et Locked, l’application peut ajuster le biais de la routine d’exposition automatique à l’aide du code suivant :

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

Les plages de paramètres minimales et maximales dépendent de l’appareil sur lequel l’application s’exécute, de sorte qu’elles ne doivent jamais être codées en dur. Utilisez plutôt les propriétés suivantes pour obtenir les plages de valeurs minimales et maximales :

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

Comme indiqué dans le code ci-dessus, l’appareil de capture doit être verrouillé pour la configuration avant qu’une modification de l’exposition puisse être apportée.

Exemple d’exposition manuelle

Avec le code général de configuration de capture AV en place, vous pouvez ajouter un UIViewController storyboard à l’application et le configurer comme suit :

Un UIViewController peut être ajouté aux applications Storyboard et configuré comme indiqué ici pour l’exemple d’exposition manuelle.

La vue contient les éléments principaux suivants :

  • Qui UIImageView affiche le flux vidéo.
  • Qui UISegmentedControl va changer le mode Focus de Automatique à Verrouillé.
  • Quatre UISlider contrôles qui affichent et mettent à jour le décalage, la durée, l’ISO et le biais.

Procédez comme suit pour connecter le contrôleur de vue pour le contrôle d’exposition manuelle :

  1. Ajoutez les instructions using suivantes :

    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. Ajoutez les variables privées suivantes :

    #region Private Variables
    private NSError Error;
    private bool Automatic = true;
    private nfloat ExposureDurationPower = 5;
    private nfloat ExposureMinimumDuration = 1.0f/1000.0f;
    #endregion
    
  3. Ajoutez les propriétés calculées suivantes :

    #region Computed Properties
    public AppDelegate ThisApp {
        get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
    }
    public Timer SampleTimer { get; set; }
    #endregion
    
  4. Remplacez la ViewDidLoad méthode et ajoutez le code suivant :

    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. Remplacez la ViewDidAppear méthode et ajoutez ce qui suit pour démarrer l’enregistrement lorsque l’affichage se charge :

    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. Avec l’appareil photo en mode Automatique, les curseurs se déplacent automatiquement à mesure que l’appareil photo ajuste l’exposition :

    Les curseurs se déplacent automatiquement à mesure que la caméra ajuste l’exposition

  7. Appuyez sur le segment Verrouillé et faites glisser le curseur Bias pour ajuster manuellement le biais de l’exposition automatique :

    Ajustement manuel du biais de l’exposition automatique

  8. Appuyez sur le segment personnalisé et faites glisser les curseurs Durée et ISO pour contrôler manuellement l’exposition :

    Faire glisser les curseurs Durée et ISO pour contrôler manuellement l’exposition

  9. Arrêtez l’application.

Le code ci-dessus montre comment surveiller les paramètres d’exposition lorsque l’appareil photo est en mode automatique et comment utiliser des curseurs pour contrôler l’exposition lorsqu’elle se trouve dans les modes Verrouillé ou Personnalisé.

Solde blanc manuel

Les contrôles d’équilibre blanc permettent aux utilisateurs d’ajuster l’équilibre de colosr dans une image pour les rendre plus réalistes. Différentes sources de lumière ont des températures de couleur différentes, et les paramètres de la caméra utilisés pour capturer une image doivent être ajustés pour compenser ces différences. Là encore, en permettant à l’utilisateur de contrôler l’équilibre blanc, il peut apporter des ajustements professionnels que les routines automatiques sont incapables d’obtenir des effets artistiques.

Exemple d’image montrant les ajustements manuels de l’équilibre blanc

Par exemple, la lumière du jour a un cast bleuâtre, tandis que les lumières à incandescence de bcène ont une teinte plus chaude et jaune-orange. (Les couleurs « froides » ont des températures de couleur plus élevées que les couleurs « chaudes ». Les températures de couleur sont une mesure physique, et non une mesure perceptive.)

L’esprit humain est très bon pour compenser les différences de température de couleur, mais c’est quelque chose qu’une caméra ne peut pas faire. L’appareil photo fonctionne en augmentant la couleur sur le spectre opposé pour s’ajuster aux différences de couleur.

La nouvelle API d’exposition iOS 8 permet à l’application de prendre le contrôle du processus et de fournir un contrôle précis sur les paramètres d’équilibre blanc de l’appareil photo.

Fonctionnement de l’équilibre blanc

Avant de discuter des détails du contrôle de l’équilibre blanc dans une application IOS 8. Examinons rapidement le fonctionnement de l’équilibre blanc :

Dans l’étude de la perception des couleurs, l’espace de couleur RVB CIE 1931 et l’espace de couleur XYZ CIE 1931 sont les premiers espaces de couleurs définis mathématiquement. Ils ont été créés par la Commission internationale de l’illumination (CIE) en 1931.

L’espace de couleurs RVB CIE 1931 et l’espace de couleur XYZ CIE 1931

Le graphique ci-dessus nous montre toutes les couleurs visibles à l’œil humain, du bleu profond au vert lumineux au rouge lumineux. Tout point du diagramme peut être tracé avec une valeur X et Y, comme indiqué sur le graphique ci-dessus.

Comme visible dans le graphique, il existe des valeurs X et Y qui peuvent être tracées sur le graphique qui se trouveraient en dehors de la plage de vision humaine, et par conséquent, ces couleurs ne peuvent pas être reproduites par une caméra.

La courbe plus petite dans le graphique ci-dessus est appelée le Locus planckien, qui exprime la température de couleur (en degrés kelvin), avec des nombres plus élevés sur le côté bleu (plus chaud) et des nombres inférieurs sur le côté rouge (froid). Ils sont utiles pour les situations d’éclairage typiques.

Dans des conditions d’éclairage mixtes, les ajustements de l’équilibre blanc devront s’écarter du Locus planckien pour apporter les modifications nécessaires. Dans ces situations, l’ajustement doit être décalé vers le côté vert ou rouge/magenta de l’échelle CIE.

Les appareils iOS compensent les casts de couleurs en augmentant le gain de couleur opposé. Par exemple, si une scène a trop de bleu, le gain rouge sera augmenté pour compenser. Ces valeurs de gain sont étalonnées pour des appareils spécifiques afin qu’ils dépendent de l’appareil.

Contrôles d’équilibre blanc existants

iOS 7 et versions ultérieures fournissaient les contrôles d’équilibre blanc existants suivants via WhiteBalanceMode la propriété :

  • AVCapture WhiteBalance ModeLocked : échantillonne la scène une fois et utilise ces valeurs dans toute la scène.
  • AVCapture WhiteBalance ModeContinuousAutoExposure – Échantillonne la scène en continu pour s’assurer qu’elle est bien équilibrée.

Et l’application peut surveiller la AdjustingWhiteBalance propriété pour voir quand l’exposition est ajustée.

Nouveaux contrôles d’équilibre blanc dans iOS 8

Outre les fonctionnalités déjà fournies par iOS 7 et versions ultérieures, les fonctionnalités suivantes sont désormais disponibles pour contrôler l’équilibre des blancs dans iOS 8 :

  • Contrôle manuel des gains RVB de l’appareil.
  • Obtenez, définissez et clé-valeur observez les gains RVB de l’appareil.
  • Prise en charge de l’équilibre blanc à l’aide d’une carte grise.
  • Routines de conversion vers et depuis des espaces de couleurs indépendants de l’appareil.

Pour implémenter les fonctionnalités ci-dessus, la AVCaptureWhiteBalanceGain structure a été ajoutée avec les membres suivants :

  • RedGain
  • GreenGain
  • BlueGain

Le gain maximal de solde blanc est actuellement quatre (4) et peut être prêt à partir de la MaxWhiteBalanceGain propriété. La plage légale est donc comprise entre un (1) et MaxWhiteBalanceGain (4) actuellement.

La DeviceWhiteBalanceGains propriété peut être utilisée pour observer les valeurs actuelles. Permet SetWhiteBalanceModeLockedWithDeviceWhiteBalanceGains d’ajuster les gains d’équilibre lorsque l’appareil photo est en mode d’équilibre blanc verrouillé.

Conversion Routines

Les routines de conversion ont été ajoutées à iOS 8 pour faciliter la conversion en espaces de couleurs indépendants de l’appareil. Pour implémenter les routines de conversion, la AVCaptureWhiteBalanceChromaticityValues structure a été ajoutée avec les membres suivants :

  • X - est une valeur comprise entre 0 et 1.
  • Y - est une valeur comprise entre 0 et 1.

Une AVCaptureWhiteBalanceTemperatureAndTintValues structure a également été ajoutée avec les membres suivants :

  • Temperature - est une valeur à virgule flottante en degrés Kelvin.
  • Tint - est un décalage de vert ou de magenta de 0 à 150 avec des valeurs positives vers la direction verte et négative vers la magenta.

Utilisez les CaptureDevice.GetTemperatureAndTintValuesméthodes et les CaptureDevice.GetDeviceWhiteBalanceGainsméthodes permettant de convertir entre la température et la teinte, la chromatique et les espaces de couleurs RVB.

Remarque

Les routines de conversion sont plus précises, plus la valeur à convertir est la locus planckienne.

Prise en charge des cartes grises

Apple utilise le terme Gray World pour faire référence à la prise en charge de la carte grise intégrée à iOS 8. Il permet à l’utilisateur de se concentrer sur une carte grise physique qui couvre au moins 50 % du centre du cadre et l’utilise pour ajuster l’équilibre blanc. L’objectif de la carte grise est d’atteindre le blanc qui apparaît neutre.

Cela peut être implémenté dans une application en invitant l’utilisateur à placer un carte gris physique devant la caméra, en contrôlant la GrayWorldDeviceWhiteBalanceGains propriété et en attendant que les valeurs s’installent.

L’application verrouille ensuite les gains d’équilibre blanc pour la SetWhiteBalanceModeLockedWithDeviceWhiteBalanceGains méthode à l’aide des valeurs de la GrayWorldDeviceWhiteBalanceGains propriété pour appliquer les modifications.

L’appareil de capture doit être verrouillé pour la configuration avant qu’une modification de l’équilibre blanc puisse être effectuée.

Exemple d’équilibre blanc manuel

Avec le code général de configuration de capture AV en place, vous pouvez ajouter un UIViewController storyboard à l’application et le configurer comme suit :

Un UIViewController peut être ajouté aux applications Storyboard et configuré comme illustré ici pour l’exemple d’équilibrage manuel des blancs.

La vue contient les éléments principaux suivants :

  • Qui UIImageView affiche le flux vidéo.
  • Qui UISegmentedControl va changer le mode Focus de Automatique à Verrouillé.
  • Deux UISlider contrôles qui affichent et mettent à jour la température et la teinte.
  • Utilisé UIButton pour échantillonner un espace de carte grise (Monde gris) et définir l’équilibre des blancs à l’aide de ces valeurs.

Procédez comme suit pour connecter le contrôleur de vue pour le contrôle d’équilibre blanc manuel :

  1. Ajoutez les instructions using suivantes :

    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. Ajoutez les variables privées suivantes :

    #region Private Variables
    private NSError Error;
    private bool Automatic = true;
    #endregion
    
  3. Ajoutez les propriétés calculées suivantes :

    #region Computed Properties
    public AppDelegate ThisApp {
        get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
    }
    public Timer SampleTimer { get; set; }
    #endregion
    
  4. Ajoutez la méthode privée suivante pour définir la nouvelle température et la teinte de l’équilibre blanc :

    #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. Remplacez la ViewDidLoad méthode et ajoutez le code suivant :

    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. Remplacez la ViewDidAppear méthode et ajoutez ce qui suit pour démarrer l’enregistrement lorsque l’affichage se charge :

    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. Enregistrez les modifications apportées au code et exécutez l’application.

  8. Avec l’appareil photo en mode Automatique, les curseurs se déplacent automatiquement à mesure que la caméra ajuste l’équilibre blanc :

    Les curseurs se déplacent automatiquement à mesure que la caméra ajuste l’équilibre blanc

  9. Appuyez sur le segment Verrouillé et faites glisser les curseurs Temp et Teinte pour ajuster manuellement l’équilibre blanc :

    Faire glisser les curseurs Temp et Teinte pour ajuster manuellement l’équilibre blanc

  10. Avec le segment Verrouillé toujours sélectionné, placez un carte gris physique devant l’appareil photo et appuyez sur le bouton Carte grise pour ajuster l’équilibre blanc au monde gris :

    Appuyez sur le bouton Carte grise pour ajuster l’équilibre blanc au monde gris

  11. Arrêtez l’application.

Le code ci-dessus montre comment surveiller les paramètres de l’équilibre blanc lorsque l’appareil photo est en mode automatique ou utiliser des curseurs pour contrôler l’équilibre blanc lorsqu’il est en mode verrouillé.

Capture entre crochets

La capture entre crochets est basée sur les paramètres des contrôles de caméra manuelle présentés ci-dessus et permet à l’application de capturer un moment dans le temps, de différentes façons.

Tout simplement indiqué, La capture entre crochets est une rafale d’images toujours prises avec un large éventail de paramètres de l’image à l’image.

Fonctionnement de la capture entre crochets

À l’aide de la capture entre crochets dans iOS 8, une application peut prédéfinir une série de contrôles de caméra manuelle, émettre une seule commande et faire en sorte que la scène actuelle retourne une série d’images pour chacune des présélections manuelles.

Principes de base de la capture entre crochets

Là encore, La capture entre crochets est une rafale d’images toujours prises avec des paramètres variés de l’image à l’image. Les types de capture entre crochets disponibles sont les suivants :

  • Crochet d’exposition automatique : où toutes les images ont une quantité de biais variée.
  • Crochet d’exposition manuelle : où toutes les images ont une vitesse d’obturation variée (durée) et une quantité ISO.
  • Simple Burst Bracket : série d’images encore prises en succession rapide.

Nouveaux contrôles de capture entre crochets dans iOS 8

Toutes les commandes De capture entre crochets sont implémentées dans la AVCaptureStillImageOutput classe. Utilisez la CaptureStillImageBracketméthode pour obtenir une série d’images avec le tableau de paramètres donné.

Deux nouvelles classes ont été implémentées pour gérer les paramètres :

  • AVCaptureAutoExposureBracketedStillImageSettings – Il a une propriété, ExposureTargetBiasutilisée pour définir le biais d’un crochet d’exposition automatique.
  • AVCaptureManualExposureBracketedStillImageSettings – Il a deux propriétés et ExposureDurationISO, utilisé pour définir la vitesse d’obturation et ISO pour un crochet d’exposition manuel.

Contrôles de capture entre crochets Et ne pas

Pratiques conseillées

Voici une liste des éléments à effectuer lors de l’utilisation des contrôles De capture entre crochets dans iOS 8 :

  • Préparez l’application pour la situation de capture de pire cas en appelant la PrepareToCaptureStillImageBracket méthode.
  • Supposons que les exemples de mémoires tampons proviennent du même pool partagé.
  • Pour libérer la mémoire allouée par un appel de préparation précédent, appelez PrepareToCaptureStillImageBracket à nouveau et envoyez-la à un tableau d’un objet.

À ne pas faire

Voici une liste des éléments qui ne doivent pas être effectués lors de l’utilisation des contrôles De capture entre crochets dans iOS 8 :

  • Ne mélangez pas les types de paramètres de capture entre crochets dans une seule capture.
  • Ne demandez pas plus d’images MaxBracketedCaptureStillImageCount dans une seule capture.

Détails de la capture entre crochets

Les détails suivants doivent être pris en compte lors de l’utilisation de La capture entre crochets dans iOS 8 :

  • Les paramètres entre crochets remplacent temporairement les AVCaptureDevice paramètres.
  • Les paramètres de stabilisation de l’image flash et toujours sont ignorés.
  • Toutes les images doivent utiliser le même format de sortie (jpeg, png, etc.)
  • L’aperçu vidéo peut supprimer des images.
  • La capture entre crochets est prise en charge sur tous les appareils compatibles avec iOS 8.

Avec ces informations à l’esprit, examinons un exemple d’utilisation de La capture entre crochets dans iOS 8.

Exemple de capture entre crochets

Avec le code général de configuration de capture AV en place, vous pouvez ajouter un UIViewController storyboard à l’application et le configurer comme suit :

Un UIViewController peut être ajouté aux applications Storyboard et configuré, comme illustré ici l’exemple de capture entre crochets.

La vue contient les éléments principaux suivants :

  • Qui UIImageView affiche le flux vidéo.
  • Trois UIImageViews qui affichent les résultats de la capture.
  • Un UIScrollView pour héberger le flux vidéo et les vues de résultats.
  • Utilisé UIButton pour prendre une capture entre crochets avec certains paramètres prédéfinis.

Procédez comme suit pour connecter le contrôleur de vue pour la capture entre crochets :

  1. Ajoutez les instructions using suivantes :

    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. Ajoutez les variables privées suivantes :

    #region Private Variables
    private NSError Error;
    private List<UIImageView> Output = new List<UIImageView>();
    private nint OutputIndex = 0;
    #endregion
    
  3. Ajoutez les propriétés calculées suivantes :

    #region Computed Properties
    public AppDelegate ThisApp {
        get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
    }
    #endregion
    
  4. Ajoutez la méthode privée suivante pour générer les vues d’image de sortie requises :

    #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. Remplacez la ViewDidLoad méthode et ajoutez le code suivant :

    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. Remplacez la ViewDidAppear méthode et ajoutez le code suivant :

    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. Enregistrez les modifications apportées au code et exécutez l’application.

  8. Cadrez une scène, puis appuyez sur le bouton Crochet de capture :

    Cadrez une scène et appuyez sur le bouton Capturer les crochets

  9. Balayez vers la droite vers la gauche pour voir les trois images prises par la capture entre crochets :

    Balayez vers la droite vers la gauche pour voir les trois images prises par la capture entre crochets

  10. Arrêtez l’application.

Le code ci-dessus montre comment configurer et prendre une capture entre crochets d’exposition automatique dans iOS 8.

Résumé

Dans cet article, nous avons abordé une présentation des nouveaux contrôles d’appareil photo manuel fournis par iOS 8 et abordé les principes fondamentaux de ce qu’ils font et comment ils fonctionnent. Nous avons donné des exemples de focus manuel, d’exposition manuelle et d’équilibre blanc manuel. Enfin, nous avons donné un exemple de prise d’une capture entre crochets à l’aide des contrôles de caméra manuel précédemment abordés