Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Esta página descreve algumas possíveis implementações para transformar imagens antes de as avaliar numa CNTK modelo que foi treinada com dados alimentados com o ImageReader. Um exemplo de trabalho é fornecido como parte do programa de exemplo CSEvalClient , em particular refere-se ao EvaluateImageClassificationModel método.
Descrição Geral
O plugin imageReader CNTK permite a alimentação de dados de imagem ao CNTK modelo para treino, teste e avaliação. O ImageReader tem algumas capacidades configuráveis que, quando ativados, executam algumas transformações on-the-fly para os dados de imagem. Estas possíveis transformações são:
- Corte
- Redimensionar
- Aplicação da Média
- Intensidade
- Cor
- Layout (HWC vs CHW)
Avaliação de imagem com CNTK.exe e o Leitor de Imagem
Neste caso, as transformações de imagem podem ser especificadas no ficheiro de configuração, e o Imagereader realizará as transformações definidas.
Avaliação programática de imagem através de EvalDll (EvalWrapper)
Neste caso, as transformações de imagem necessárias têm de ser realizadas programáticamente antes de a imagem ser passada para o Evalwrapper.
Esta secção fornece algumas implementações possíveis para a realização de algumas destas transformações antes da avaliação.
Por exemplo, uma classe estática chamada CntkBitmapExtensions poderia conter os métodos de extensão apresentados 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;
}
Neste caso, uma possível invocação poderia ser:
var testBitmap = new Bitmap(Bitmap.FromFile(@"C:\rocket.bmp")).Resize(224, 224, true);
Este 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
Existem 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 pela cuDNN na GPU.
Note que o layout do ficheiro real pode ser diferente. Estamos a olhar para a representação da memória, não para o conteúdo do ficheiro.
Nota, as descrições acima referem-se à notação de fila-grande comumente utilizada onde a dimensão móvel mais rápida vem em último lugar. CNTK geralmente usa notação de coluna-grande que usa a dimensão móvel mais rápida primeiro e onde o abaixo seria expresso como "CWH" e "WHC", respectivamente.
Isto significa que assumindo um bitmap com formato HWC de 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 da 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 extraisse os dados de imagem de um Bitmapchw para o layout chw poderia 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 de layout da memória, permitindo-nos focar na transformação em si.
Este método pode agora ser usado na nossa transformação de imagem antes da avaliação. Assumindo o mesmo mapa bit que em Resize, poderíamos extrair os seus dados no layout chw com a seguinte invocação:
var features = testBitmap.ExtractCHW();
O features vetor pode agora ser usado como uma entrada de camada na classificação de imagem modelo. Um exemplo de trabalho é fornecido como parte do CSEvalClient programa de exemplo, em particular refere-se ao EvaluateImageClassificationModel método.