你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
本页介绍在评估图像之前转换图像的一些可能实现,该模型是使用使用 ImageReader 馈送的数据训练的CNTK模型。 作为 CSEvalClient 示例程序的一部分提供工作示例,特别是引用该方法EvaluateImageClassificationModel。
概述
CNTK ImageReader 插件支持将图像数据馈送到用于训练、测试和评估的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。 第一种是CNTK中使用的默认格式。 第二个 CHW 是 GPU 中 cuDNN 使用的格式。
请注意,实际 文件 布局 可能 有所不同。 我们正在查看内存表示形式,而不是文件内容
请注意,上述说明是指最常用的 行主 表示法,其中移动速度最快的维度是最后一个。 CNTK通常使用列主表示法,该表示法首先使用最快的移动维度,其中下面分别表示为“CWH”和“WHC”。
这意味着,假设使用 RGB 字节的 HWC 格式为 10x10 的位图,内存空间将对应于:
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 负责某些内存布局细微差别,使我们能够专注于转换本身。
在评估之前,可以在图像转换中使用此方法。 假设与 Resize 中的位图相同,我们可以使用以下调用在 CHW 布局中提取其数据:
var features = testBitmap.ExtractCHW();
features现在可将矢量用作图像分类模型中的层输入。 作为示例程序的一部分 CSEvalClient 提供工作示例,特别是引用该方法 EvaluateImageClassificationModel 。