CNTK вычисление преобразований изображений
На этой странице описываются некоторые возможные реализации для преобразования изображений перед их оценкой в модели CNTK, которая была обучена с данными, поступающими с помощью ImageReader. Рабочий пример предоставляется как часть примера программы CSEvalClient , в частности, относится к методу EvaluateImageClassificationModel
.
Обзор
Подключаемый модуль ImageReader CNTK позволяет передавать данные изображений в модель CNTK для обучения, тестирования и оценки. ImageReader имеет некоторые настраиваемые возможности, которые при включении выполняют некоторые преобразования во время полета к данным изображения. Ниже перечислены возможные преобразования.
- Обрезка
- Изменить размер
- Применение среднего значения
- Интенсивность
- Цвет
- Макет (HWC и CHW)
Оценка изображений с помощью CNTK.exe и средства чтения изображений
В этом случае преобразования изображений можно указать в файле конфигурации, а Imagereader выполнит определенные преобразования.
Программная оценка образа с помощью EvalDll(EvalWrapper)
В этом случае необходимо выполнить необходимые преобразования изображений программным способом, прежде чем образ передается в Evalwrapper.
В этом разделе приводятся некоторые возможные реализации для выполнения некоторых из этих преобразований до оценки.
Например, статический класс cntkBitmapExtensions может содержать методы расширения, показанные ниже.
Изменить размер
/// <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;
}
В этом случае возможное вызов может быть следующим:
var testBitmap = new Bitmap(Bitmap.FromFile(@"C:\rocket.bmp")).Resize(224, 224, true);
Эта команда изменит C:\rocket.bmp
размер изображения на 224 x 224 пикселя, поддерживая высокое качество изображения.
Преобразование макета из HWC в CHW
В CNTK используются два типа макета: HWC и CHW. Во-первых, HWC — это формат по умолчанию, используемый в CNTK. Во-вторых, CHW, — это формат, используемый cuDNN в GPU.
Обратите внимание, что фактический макет файламожет отличаться. Мы рассматриваем представление памяти, а не содержимое файла
Обратите внимание, что описанные выше описания относятся к часто используемой нотации с основной строкой , где самое быстрое движущееся измерение приходит в последний раз. CNTK обычно использует нотацию с основным столбцом, которая использует самое быстрое движущееся измерение первым и где ниже будет выражено как "CWH" и "WHC", соответственно.
Это означает, что при условии, что растровое изображение с форматом HWC размером 10 x 10 x 10 с использованием RGB-байтов пространство памяти будет соответствовать следующим требованиям:
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 ...
В случае с chW макет будет следующим:
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
Возможный метод расширения, извлекающий Bitmap
данные изображения в макет CHW, может быть следующим:
/// <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;
}
Этот Bitmap.GetPixel
метод заботится о некоторых нюансах макета памяти, что позволяет сосредоточиться на самом преобразовании.
Этот метод теперь можно использовать в преобразовании изображений перед вычислением. Предположим, что то же растровое изображение, что и в режиме изменения размера, мы можем извлечь свои данные в макете CHW со следующим вызовом:
var features = testBitmap.ExtractCHW();
Теперь вектор features
можно использовать в качестве входных данных слоя в модель классификации изображений. Рабочий пример предоставляется как часть CSEvalClient
примера программы, в частности, относится к методу EvaluateImageClassificationModel
.