Condividi tramite


CNTK valutare le trasformazioni delle immagini

Questa pagina descrive alcune possibili implementazioni per la trasformazione delle immagini prima di valutarle in un modello di CNTK sottoposto a training con i dati inseriti con ImageReader. Un esempio funzionante viene fornito come parte del programma di esempio CSEvalClient , in particolare fare riferimento al EvaluateImageClassificationModel metodo .

Panoramica

Il plug-in CNTK ImageReader consente di inserire i dati delle immagini nel modello di CNTK per il training, il test e la valutazione. ImageReader include alcune funzionalità configurabili che, se abilitate, eseguono alcune trasformazioni on-the-fly nei dati dell'immagine. Queste possibili trasformazioni sono:

  • Ritaglio
  • Ridimensionamento
  • Applicazione della media
  • Intensità
  • Color
  • Layout (HWC e CHW)

Valutazione delle immagini con CNTK.exe e lettore di immagini

In questo caso le trasformazioni di immagine possono essere specificate nel file di configurazione e Imagereader eseguirà le trasformazioni definite.

Valutazione delle immagini a livello di codice tramite EvalDll(EvalWrapper)

In questo caso, è necessario eseguire le trasformazioni dell'immagine necessarie a livello di codice prima che l'immagine venga passata al Evalwrapper.

In questa sezione vengono fornite alcune implementazioni possibili per l'esecuzione di alcune di queste trasformazioni prima della valutazione.

Ad esempio, una classe statica denominata CntkBitmapExtensions può contenere i metodi di estensione illustrati di seguito.

Ridimensionamento

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

In questo caso una possibile chiamata potrebbe essere:

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

Questo comando ridimensiona l'immagine C:\rocket.bmp a una dimensione di 224 x 224 pixel mantenendo un'immagine di alta qualità.

Conversione del layout da HWC a CHW

Esistono principalmente due tipi di layout usati in CNTK: HWC e CHW. Il primo, HWC è il formato predefinito usato in CNTK. Il secondo, CHW, è il formato usato da cuDNN nella GPU.

Si noti che il layout effettivo del filepuò essere diverso. Si sta esaminando la rappresentazione di memoria, non il contenuto del file

Si noti che le descrizioni precedenti fanno riferimento alla notazione principale di riga comunemente usata in cui la dimensione in movimento più veloce arriva per ultima. CNTK in genere usa la notazione principale della colonna che usa la dimensione in movimento più veloce e dove il seguente viene espresso rispettivamente come "CWH" e "WHC".

Ciò significa che presupponendo una bitmap con formato HWC di dimensioni 10x10 usando byte RGB, lo spazio di memoria corrisponderebbe a:

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

Nel caso di CHW il layout sarebbe:

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

Un possibile metodo di estensione che estrae i dati di un'immagine Bitmapnel layout CHW può essere:

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

Il Bitmap.GetPixel metodo si occupa di alcune sfumature del layout di memoria, consentendo di concentrarsi sulla trasformazione stessa.

Questo metodo può ora essere usato nella trasformazione dell'immagine prima della valutazione. Supponendo che la stessa bitmap di Ridimensionare, è possibile estrarre i dati nel layout CHW con la chiamata seguente:

var features = testBitmap.ExtractCHW();

Il features vettore può ora essere usato come input di livello nel modello di classificazione delle immagini. Un esempio funzionante viene fornito come parte del CSEvalClient programma di esempio, in particolare fare riferimento al EvaluateImageClassificationModel metodo .