Compartir a través de


CNTK Evaluar transformaciones de imagen

En esta página se describen algunas implementaciones posibles para transformar imágenes antes de evaluarlas en un modelo de CNTK que se entrenó con datos alimentados con ImageReader. Se proporciona un ejemplo de trabajo como parte del programa de ejemplo CSEvalClient , en particular, hacer referencia al EvaluateImageClassificationModel método .

Información general

El complemento CNTK ImageReader permite alimentar los datos de imagen al modelo de CNTK para el entrenamiento, las pruebas y la evaluación. ImageReader tiene algunas funcionalidades configurables que, cuando se habilitan, realizan algunas transformaciones sobre la marcha en los datos de la imagen. Estas posibles transformaciones son:

  • Recorte
  • Cambiar de tamaño
  • Aplicación de la media
  • Intensidad
  • Color
  • Diseño (HWC frente a CHW)

Evaluación de imágenes con CNTK.exe y lector de imágenes

En este caso, las transformaciones de imagen se pueden especificar en el archivo de configuración y Imagereader realizará las transformaciones definidas.

Evaluación de imágenes mediante programación a través de EvalDll(EvalWrapper)

En este caso, las transformaciones de imagen necesarias deben realizarse mediante programación antes de que la imagen se pase a Evalwrapper.

En esta sección se proporcionan algunas implementaciones posibles para realizar algunas de estas transformaciones antes de la evaluación.

Por ejemplo, una clase estática denominada CntkBitmapExtensions podría contener los métodos de extensión que se muestran a continuación.

Cambiar de tamaño

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

En este caso, una posible invocación podría ser:

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

Este comando cambiaría el tamaño de la C:\rocket.bmp imagen a un tamaño de 224 x 224 píxeles manteniendo una imagen de alta calidad.

Conversión de diseño de HWC a CHW

Hay principalmente dos tipos de diseño usados en CNTK: HWC y CHW. El primero, HWC es el formato predeterminado que se usa en CNTK. El segundo, CHW, es el formato que usa cuDNN en la GPU.

Tenga en cuenta que el diseño de archivo real puede ser diferente. Estamos examinando la representación de memoria, no el contenido del archivo.

Tenga en cuenta que las descripciones anteriores hacen referencia a la notación principal de fila usada habitualmente en la que la dimensión móvil más rápida es la última. CNTK normalmente usa la notación principal de columna que usa primero la dimensión móvil más rápida y donde la siguiente se expresaría como "CWH" y "WHC", respectivamente.

Esto significa que, suponiendo que un mapa de bits con formato HWC de tamaño 10x10 con bytes RGB, el espacio de memoria correspondería 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 ...

En el caso de CHW, el diseño sería:

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 posible método de extensión que extraiga los datos de imagen de un Bitmapdiseño CHW podría ser:

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

El Bitmap.GetPixel método se encarga de algunos de los matices del diseño de memoria, lo que nos permite centrarnos en la propia transformación.

Este método ahora se puede usar en nuestra transformación de imagen antes de la evaluación. Suponiendo que el mismo mapa de bits que en Resize, podríamos extraer sus datos en el diseño CHW con la siguiente invocación:

var features = testBitmap.ExtractCHW();

El features vector ahora se puede usar como entrada de capa en el modelo de clasificación de imágenes. Se proporciona un ejemplo de trabajo como parte del CSEvalClient programa de ejemplo, en particular, hacer referencia al EvaluateImageClassificationModel método .