Core Image en Xamarin.iOS

Core Image es un nuevo marco incluido en iOS 5 para proporcionar una funcionalidad de mejora de vídeos en directo y procesamiento de imágenes. En este artículo se presentan estas características con ejemplos de Xamarin.iOS.

Core Image es un nuevo marco incluido en iOS 5 que proporciona una serie de filtros y efectos integrados para aplicar a imágenes y vídeos, incluida la detección de caras.

En este documento se incluyen ejemplos sencillos de:

  • Detección de caras.
  • Aplicación de filtros a una imagen
  • Enumeración de los filtros disponibles.

Estos ejemplos deberían ayudarle a empezar a incorporar características de Core Image en las aplicaciones de Xamarin.iOS.

Requisitos

Debe usar la última versión de Xcode.

Detección facial

La característica de detección de caras de Core Image se limita a hace lo que dice: intenta identificar caras en una foto y devuelve las coordenadas de las caras que reconoce. Esta información se puede usar para contar el número de personas de una imagen, dibujar indicadores en la imagen (p. ej., para "etiquetar" personas en una fotografía) o cualquier otra cosa que se le ocurra.

Este código de CoreImage\SampleCode.cs muestra cómo crear y usar la detección de caras en una imagen insertada:

var image = new UIImage("photoFace.JPG");
var context = CIContext.FromOptions(null);
var detector = CIDetector.CreateFaceDetector (context, true);
var ciImage = CIImage.FromCGImage(image.CGImage);
CIFeature[] features = detector.FeaturesInImage(ciImage);

La matriz de características se rellenará con objetos CIFaceFeature (si se han detectado caras). Hay una CIFaceFeature para cada cara. CIFaceFeature tiene las siguientes propiedades:

  • HasMouthPosition: si se ha detectado una boca para esta cara.
  • HasLeftEyePosition: si se ha detectado el ojo izquierdo para esta cara.
  • HasRightEyePosition: si se ha detectado el ojo derecho para esta cara.
  • MouthPosition: coordenadas de la boca para esta cara.
  • LeftEyePosition: coordenadas del ojo izquierdo para esta cara.
  • RightEyePosition: coordenadas del ojo derecho para esta cara.

Las coordenadas de todas estas propiedades tienen su origen en la parte inferior izquierda, a diferencia de UIKit, que usa la parte superior izquierda como origen. Al usar las coordenadas en CIFaceFeature, asegúrese de "voltearlas". Esta vista de imagen personalizada muy básica en CoreImage\CoreImageViewController.cs muestra cómo dibujar triángulos "indicadores de caras" en la imagen (tenga en cuenta el método FlipForBottomOrigin):

public class FaceDetectImageView : UIView
{
    public Xamarin.iOS.CoreImage.CIFeature[] Features;
    public UIImage Image;
    public FaceDetectImageView (RectangleF rect) : base(rect) {}
    CGPath path;
    public override void Draw (RectangleF rect) {
        base.Draw (rect);
        if (Image != null)
            Image.Draw(rect);

        using (var context = UIGraphics.GetCurrentContext()) {
            context.SetLineWidth(4);
            UIColor.Red.SetStroke ();
            UIColor.Clear.SetFill ();
            if (Features != null) {
                foreach (var feature in Features) { // for each face
                    var facefeature = (CIFaceFeature)feature;
                    path = new CGPath ();
                    path.AddLines(new PointF[]{ // assumes all 3 features found
                        FlipForBottomOrigin(facefeature.LeftEyePosition, 200),
                        FlipForBottomOrigin(facefeature.RightEyePosition, 200),
                        FlipForBottomOrigin(facefeature.MouthPosition, 200)
                    });
                    path.CloseSubpath();
                    context.AddPath(path);
                    context.DrawPath(CGPathDrawingMode.FillStroke);
                }
            }
        }
    }
    /// <summary>
    /// Face recognition coordinates have their origin in the bottom-left
    /// but we are drawing with the origin in the top-left, so "flip" the point
    /// </summary>
    PointF FlipForBottomOrigin (PointF point, int height)
    {
        return new PointF(point.X, height - point.Y);
    }
}

A continuación, en el archivo SampleCode.cs, la imagen y las características se asignan antes de que se vuelva a dibujar la imagen:

faceView.Image = image;
faceView.Features = features;
faceView.SetNeedsDisplay();

En la captura de pantalla se muestra la salida de ejemplo: las ubicaciones de las características faciales detectadas se muestran en UITextView y se dibujan en la imagen de origen mediante CoreGraphics.

Debido al funcionamiento del reconocimiento facial, en ocasiones detectará cosas además de caras humanas (¡como estos monos de juguete!).

Filters

Hay más de 50 filtros integrados diferentes y el marco puede extenderse, lo que permite la implementación de nuevos filtros.

Usar filtros

La aplicación de un filtro a una imagen se divide en cuatro pasos distintos: cargar la imagen, crear el filtro, aplicar el filtro y guardar (o mostrar) el resultado.

En primer lugar, cargue una imagen en un objeto CIImage.

var uiimage = UIImage.FromFile ("photo.JPG");
var ciimage = new CIImage (uiimage);

En segundo lugar, cree la clase de filtro y establezca sus propiedades.

var sepia = new CISepiaTone();
sepia.Image = ciimage;
sepia.Intensity = 0.8f;

En tercer lugar, acceda a la propiedad OutputImage y llame al método CreateCGImage para representar el resultado final.

CIImage output = sepia.OutputImage;
var context = CIContext.FromOptions(null);
var cgimage = context.CreateCGImage (output, output.Extent);

Por último, asigne la imagen a una vista para ver el resultado. En una aplicación real, la imagen resultante podría guardarse en el sistema de archivos, el álbum de fotos, un tweet o un correo electrónico.

var ui = UIImage.FromImage (cgimage);
imgview.Image = ui;

En estas capturas de pantalla se muestra el resultado de los filtros CISepia y CIHueAdjust que se muestran en el código de ejemplo CoreImage.zip.

Consulte la receta Ajustar el contraste y el brillo de una imagen para ver un ejemplo del filtro CIColorControls.

var uiimage = UIImage.FromFile("photo.JPG");
var ciimage = new CIImage(uiimage);
var hueAdjust = new CIHueAdjust();   // first filter
hueAdjust.Image = ciimage;
hueAdjust.Angle = 2.094f;
var sepia = new CISepiaTone();       // second filter
sepia.Image = hueAdjust.OutputImage; // output from last filter, input to this one
sepia.Intensity = 0.3f;
CIFilter color = new CIColorControls() { // third filter
    Saturation = 2,
    Brightness = 1,
    Contrast = 3,
    Image = sepia.OutputImage    // output from last filter, input to this one
};
var output = color.OutputImage;
var context = CIContext.FromOptions(null);
// ONLY when CreateCGImage is called do all the effects get rendered
var cgimage = context.CreateCGImage (output, output.Extent);
var ui = UIImage.FromImage (cgimage);
imgview.Image = ui;
var context = CIContext.FromOptions (null);
var context = CIContext.FromOptions(new CIContextOptions() {
    UseSoftwareRenderer = true  // CPU
});
var cgimage = context.CreateCGImage (output, output.Extent);
var ui = UIImage.FromImage (cgimage);
imgview.Image = ui;

Enumeración de filtros y sus propiedades

Este código de CoreImage\SampleCode.cs genera la lista completa de filtros integrados y sus parámetros.

var filters = CIFilter.FilterNamesInCategories(new string[0]);
foreach (var filter in filters){
   display.Text += filter +"\n";
   var f = CIFilter.FromName (filter);
   foreach (var key in f.InputKeys){
     var attributes = (NSDictionary)f.Attributes[new NSString(key)];
     var attributeClass = attributes[new NSString("CIAttributeClass")];
     display.Text += "   " + key;
     display.Text += "   " + attributeClass + "\n";
   }
}

La referencia de clase CIFilter describe los 50 filtros integrados y sus propiedades. Al usar el código anterior, puede consultar las clases de filtro, incluidos los valores predeterminados de los parámetros y los valores permitidos máximos y mínimos (que podrían usarse para validar entradas antes de aplicar un filtro).

La salida Mostrar categorías tiene este aspecto en el simulador: puede desplazarse por la lista para ver todos los filtros y sus parámetros.

The List Categories output looks like this on the simulator

Cada filtro enumerado se ha expuesto como una clase en Xamarin.iOS, por lo que también puede explorar la API de Xamarin.iOS.CoreImage en el explorador de ensamblados o mediante el uso de autocompletar en Visual Studio para Mac o Visual Studio.

Resumen

En este artículo se ha mostrado cómo usar algunas de las nuevas características del marco Core Image de iOS 5, como la detección de caras y la aplicación de filtros a una imagen. Hay docenas de filtros de imagen diferentes disponibles en el marco para su uso.