Partager via


CNTK évaluer les transformations d’image

Cette page décrit certaines implémentations possibles pour transformer des images avant de les évaluer sur un modèle CNTK formé avec des données alimentées avec ImageReader. Un exemple de travail est fourni dans le cadre de l’exemple de programme CSEvalClient , en particulier faire référence à la EvaluateImageClassificationModel méthode.

Vue d’ensemble

Le plug-in ImageReader CNTK permet d’alimenter les données d’image vers le modèle CNTK pour l’entraînement, le test et l’évaluation. ImageReader dispose de fonctionnalités configurables qui, lorsqu’elle est activée, effectuent des transformations à la volée vers les données d’image. Ces transformations possibles sont les suivantes :

  • Rognage
  • Redimensionner
  • Application de la moyenne
  • Intensité
  • Couleur
  • Disposition (HWC et CHW)

Évaluation d’image avec CNTK.exe et lecteur d’images

Dans ce cas, les transformations d’image peuvent être spécifiées dans le fichier de configuration, et Imagereader effectue les transformations définies.

Évaluation d’image par programmation via EvalDll(EvalWrapper)

Dans ce cas, les transformations d’image requises doivent être effectuées par programmation avant que l’image ne soit transmise à l’Evalwrapper.

Cette section fournit certaines implémentations possibles pour effectuer certaines de ces transformations avant l’évaluation.

Par exemple, une classe statique nommée CntkBitmapExtensions peut contenir les méthodes d’extension indiquées ci-dessous.

Redimensionner

    /// <summary>
    /// Resizes an image
    /// </summary>
    /// <param name="image">The image to resize</param>
    /// <param name="width">New width in pixels</param>
    /// <param name="height">New height in pixesl</param>
    /// <param name="useHighQuality">Resize quality</param>
    /// <returns>The resized image</returns>
    public static Bitmap Resize(this Bitmap image, int width, int height, bool useHighQuality)
    {
        var rect = new Rectangle(0, 0, width, height);
        var newImg = new Bitmap(width, height);

        newImg.SetResolution(image.HorizontalResolution, image.VerticalResolution);

        using (var g = Graphics.FromImage(newImg))
        {
            g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
            if (useHighQuality)
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
            }
            else
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default;
                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.Default;
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default;
                g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Default;
            }

            var attributes = new ImageAttributes();
            attributes.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY);
            g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes);
        }

        return newImg;
    }

Dans ce cas, un appel possible peut être :

 var testBitmap = new Bitmap(Bitmap.FromFile(@"C:\rocket.bmp")).Resize(224, 224, true);

Cette commande redimensionne l’image C:\rocket.bmp à une taille de 224 x 224 pixels en conservant une image de haute qualité.

Conversion de disposition de HWC en CHW

Il existe principalement deux types de disposition utilisés dans CNTK : HWC et CHW. Le premier, HWC est le format par défaut utilisé dans CNTK. Le deuxième, CHW, est le format utilisé par cuDNN dans le GPU.

Notez que la disposition réelle dufichier peut être différente. Nous examinons la représentation de la mémoire, et non le contenu du fichier

Notez que les descriptions ci-dessus font référence à la notation principale de ligne couramment utilisée, où la dimension de déplacement la plus rapide vient en dernier. CNTK utilise généralement la notation principale de colonne qui utilise d’abord la dimension mobile la plus rapide et où les valeurs ci-dessous seraient exprimées respectivement sous la forme « CWH » et « WHC ».

Cela signifie qu’en supposant qu’une image bitmap avec le format HWC de taille 10x10 à l’aide d’octets RVB, l’espace mémoire correspond à :

Offset (byte) :  0  1  2  3  4  5  6  7  8 ...29 30 31 32 33 34 35 36 37 ...
Height Pos    :  0  0  0  0  0  0  0  0  0 ... 0  0  0  1  1  1  1  1  1 ...
Width Pos     :  0  0  0  1  1  1  2  2  2 ... 9  9  9  0  0  0  1  1  1 ...
Color Index   :  B  G  R  B  G  R  B  G  R ... B  G  R  B  G  R  B  G  R ...

Dans le cas de CHW, la disposition serait la suivante :

Offset (byte) :  0  1  2  3 ... 9 10 11 12 13 ...90 91 92 93 ... 99 100 ... 199 200 ... 299 
Color Index   :  B  B  B  B ... B  B  B  B  B ... B  B  B  B ...  B   G ...   G   R ...   R
Height Pos    :  0  0  0  0 ... 0  0  0  0  0 ... 9  9  9  9 ...  9   0 ...   9   0 ...   9
Width Pos     :  0  1  2  3 ... 9  0  1  2  3 ... 0  1  2  3 ...  9   0 ...   9   0 ...   9

Une méthode d’extension possible qui extrait les données d’image d’une Bitmapdisposition CHW peut être :

    /// <summary>
    /// Extracts image pixels in CHW
    /// </summary>
    /// <param name="image">The bitmap image to extract features from</param>
    /// <returns>A list of pixels in HWC order</returns>
    public static List<float> ExtractCHW(this Bitmap image)
    {
        var features = new List<float>(image.Width * image.Height * 3);
        for (int c = 0; c < 3; c++)
        {
            for (int h = 0; h < image.Height; h++)
            {
                for (int w = 0; w < image.Width; w++)
                {
                    var pixel = image.GetPixel(w, h);
                    float v = c == 0 ? pixel.B : c == 1 ? pixel.G : pixel.R;

                    features.Add(v);
                }
            }
        }

        return features;
    }

La Bitmap.GetPixel méthode s’occupe de certaines nuances de disposition de mémoire, ce qui nous permet de nous concentrer sur la transformation elle-même.

Cette méthode peut désormais être utilisée dans notre transformation d’image avant l’évaluation. En supposant que la même image bitmap que dans Resize, nous pourrions extraire ses données dans la disposition CHW avec l’appel suivant :

var features = testBitmap.ExtractCHW();

Le features vecteur peut désormais être utilisé comme entrée de couche dans le modèle de classification d’images. Un exemple de travail est fourni dans le cadre de l’exemple CSEvalClient de programme, en particulier faire référence à la EvaluateImageClassificationModel méthode.