Udostępnij przez


CNTK ocenianie przekształceń obrazów

Na tej stronie opisano niektóre możliwe implementacje przekształcania obrazów przed ich oceną w modelu CNTK, który został wytrenowany przy użyciu danych karmionych przy użyciu elementu ImageReader. Przykład roboczy jest dostarczany jako część przykładowego programu CSEvalClient , w szczególności odnosi się do EvaluateImageClassificationModel metody .

Omówienie

Wtyczka CNTK ImageReader umożliwia przekazywanie danych obrazu do modelu CNTK na potrzeby trenowania, testowania i oceny. Element ImageReader ma pewne konfigurowalne możliwości, które po włączeniu można wykonać pewne przekształcenia na bieżąco w danych obrazu. Te możliwe przekształcenia to:

  • Przycinania
  • Zmiana rozmiaru
  • Stosowanie średniej
  • Intensywność
  • Kolor
  • Układ (HWC vs CHW)

Ocena obrazu za pomocą CNTK.exe i czytnika obrazów

W takim przypadku przekształcenia obrazu można określić w pliku konfiguracji, a element Imagereader wykona zdefiniowane przekształcenia.

Programowa ocena obrazu za pośrednictwem EvalDll(EvalWrapper)

W takim przypadku wymagane przekształcenia obrazu należy wykonać programowo przed przekazaniem obrazu do programu Evalwrapper.

Ta sekcja zawiera pewne możliwe implementacje do wykonywania niektórych z tych przekształceń przed oceną.

Na przykład klasa statyczna o nazwie CntkBitmapExtensions może zawierać metody rozszerzenia pokazane poniżej.

Zmiana rozmiaru

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

W takim przypadku możliwe wywołanie może być następujące:

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

To polecenie spowoduje zmianę rozmiaru C:\rocket.bmp obrazu na rozmiar 224 x 224 pikseli zachowujący wysoką jakość obrazu.

Konwersja układu z HWC na CHW

Istnieją przede wszystkim dwa typy układów używane w CNTK: HWC i CHW. Pierwszy, HWC jest domyślnym formatem używanym w CNTK. Drugi, CHW, jest format używany przez cuDNN w procesorze GPU.

Należy pamiętać, że rzeczywisty układ pliku może być inny. Patrzymy na reprezentację pamięci, a nie zawartość pliku

Należy pamiętać, że powyższe opisy odnoszą się do często używanej notacji głównej wierszy , w której ostatni jest najszybszy wymiar ruchomy. CNTK zwykle używa notacji głównej kolumny, która używa najpierw najszybszego wymiaru ruchomego i gdzie poniżej zostaną wyrażone odpowiednio jako "CWH" i "WHC".

Oznacza to, że przy założeniu, że mapa bitowa o formacie HWC o rozmiarze 10 x 10 x 10 przy użyciu bajtów RGB, przestrzeń pamięci odpowiadałaby:

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

W przypadku CHW układ będzie:

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

Możliwą metodą rozszerzenia wyodrębniającą Bitmapdane obrazu do układu CHW może być:

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

Metoda Bitmap.GetPixel zajmuje się niektórymi niuansami układu pamięci, co pozwala skupić się na samym przekształceniu.

Tej metody można teraz użyć w transformacji obrazu przed oceną. Zakładając, że ta sama mapa bitowa co w obszarze Zmiana rozmiaru, możemy wyodrębnić jej dane w układzie CHW z następującym wywołaniem:

var features = testBitmap.ExtractCHW();

Wektor features może być teraz używany jako dane wejściowe warstwy w modelu klasyfikacji obrazów. Przykład roboczy jest dostarczany w ramach przykładowego CSEvalClient programu, w szczególności odnosi się do EvaluateImageClassificationModel metody .