CNTK avaliar transformações de imagem
Esta página descreve algumas implementações possíveis para transformar imagens antes de avaliá-las em um modelo de CNTK que foi treinado com dados alimentados com o ImageReader. Um exemplo de trabalho é fornecido como parte do programa de exemplo CSEvalClient , em particular, consulte o EvaluateImageClassificationModel
método.
Visão geral
O plug-in CNTK ImageReader permite alimentar dados de imagem para o modelo CNTK para treinamento, teste e avaliação. O ImageReader tem alguns recursos configuráveis que, quando habilitados, executam algumas transformações on-the-fly para os dados da imagem. Essas transformações possíveis são:
- Corte
- Redimensionar
- Aplicando a média
- Intensidade
- Cor
- Layout (HWC vs CHW)
Avaliação de imagem com CNTK.exe e o Leitor de Imagem
Nesse caso, as transformações de imagem podem ser especificadas no arquivo de configuração e o Imagereader executará as transformações definidas.
Avaliação de imagem programática por meio de EvalDll(EvalWrapper)
Nesse caso, as transformações de imagem necessárias precisam ser executadas programaticamente antes que a imagem seja passada para o Evalwrapper.
Esta seção fornece algumas implementações possíveis para executar algumas dessas transformações antes da avaliação.
Por exemplo, uma classe estática chamada CntkBitmapExtensions pode conter os métodos de extensão mostrados abaixo.
Redimensionar
/// <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;
}
Nesse caso, uma possível invocação pode ser:
var testBitmap = new Bitmap(Bitmap.FromFile(@"C:\rocket.bmp")).Resize(224, 224, true);
Esse comando redimensionaria a C:\rocket.bmp
imagem para um tamanho de 224 x 224 pixels mantendo uma imagem de alta qualidade.
Conversão de layout de HWC para CHW
Há principalmente dois tipos de layout usados em CNTK: HWC e CHW. O primeiro, HWC, é o formato padrão usado em CNTK. O segundo, CHW, é o formato usado por cuDNN na GPU.
Observe que o layout real do arquivopode ser diferente. Estamos examinando a representação de memória, não o conteúdo do arquivo
Observe que as descrições acima referem-se à notação de linha principal comumente usada em que a dimensão de movimentação mais rápida é a última. CNTK geralmente usa notação de coluna principal que usa a dimensão móvel mais rápida primeiro e onde o abaixo seria expresso como "CWH" e "WHC", respectivamente.
Isso significa que, supondo um bitmap com o formato HWC do tamanho 10x10 usando bytes RGB, o espaço de memória corresponderia 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 ...
No caso do CHW, o layout seria:
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
Um possível método de extensão que extrai Bitmap
dados de imagem para o layout chw pode 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;
}
O Bitmap.GetPixel
método cuida de algumas das nuances do layout de memória, permitindo que nos concentremos na transformação em si.
Esse método agora pode ser usado em nossa transformação de imagem antes da avaliação. Supondo o mesmo bitmap que no Redimensionamento, poderíamos extrair seus dados no layout do CHW com a seguinte invocação:
var features = testBitmap.ExtractCHW();
O features
vetor agora pode ser usado como uma entrada de camada no modelo de classificação de imagem. Um exemplo de trabalho é fornecido como parte do CSEvalClient
programa de exemplo, em particular, consulte o EvaluateImageClassificationModel
método.