diff --git a/docs/samples/Microsoft.ML.Samples/Dynamic/ImageAnalytics/ConvertToGrayScale.cs b/docs/samples/Microsoft.ML.Samples/Dynamic/ImageAnalytics/ConvertToGrayScale.cs new file mode 100644 index 0000000000..cf02de0860 --- /dev/null +++ b/docs/samples/Microsoft.ML.Samples/Dynamic/ImageAnalytics/ConvertToGrayScale.cs @@ -0,0 +1,57 @@ +using System.IO; +using Microsoft.ML.Data; + +namespace Microsoft.ML.Samples.Dynamic +{ + public class ConvertToGrayscaleExample + { + // Sample that loads images from the file system, and converts them to grayscale. + public static void ConvertToGrayscale() + { + var mlContext = new MLContext(); + + // Downloading a few images, and an images.tsv file, which contains a list of the files from the dotnet/machinelearning/test/data/images/. + // If you inspect the fileSystem, after running this line, an "images" folder will be created, containing 4 images, and a .tsv file + // enumerating the images. + var imagesDataFile = SamplesUtils.DatasetUtils.DownloadImages(); + + // Preview of the content of the images.tsv file + // + // imagePath imageType + // tomato.bmp tomato + // banana.jpg banana + // hotdog.jpg hotdog + // tomato.jpg tomato + + var data = mlContext.Data.CreateTextLoader(new TextLoader.Arguments() + { + Columns = new[] + { + new TextLoader.Column("ImagePath", DataKind.TX, 0), + new TextLoader.Column("Name", DataKind.TX, 1), + } + }).Read(imagesDataFile); + + var imagesFolder = Path.GetDirectoryName(imagesDataFile); + // Image loading pipeline. + var pipeline = mlContext.Transforms.LoadImages(imagesFolder, ("ImageObject", "ImagePath")) + .Append(mlContext.Transforms.ConvertToGrayscale(("Grayscale", "ImageObject"))); + + var transformedData = pipeline.Fit(data).Transform(data); + + // The transformedData IDataView contains the loaded images column, and the grayscaled column. + // Preview of the transformedData + var transformedDataPreview = transformedData.Preview(); + + // Preview of the content of the images.tsv file + // The actual images, in the Grayscale column are of type System.Drawing.Bitmap. + // + // ImagePath Name ImageObject Grayscale + // tomato.bmp tomato {System.Drawing.Bitmap} {System.Drawing.Bitmap} + // banana.jpg banana {System.Drawing.Bitmap} {System.Drawing.Bitmap} + // hotdog.jpg hotdog {System.Drawing.Bitmap} {System.Drawing.Bitmap} + // tomato.jpg tomato {System.Drawing.Bitmap} {System.Drawing.Bitmap} + + } + } +} diff --git a/docs/samples/Microsoft.ML.Samples/Dynamic/ImageAnalytics/ExtractPixels.cs b/docs/samples/Microsoft.ML.Samples/Dynamic/ImageAnalytics/ExtractPixels.cs new file mode 100644 index 0000000000..4c9d743acc --- /dev/null +++ b/docs/samples/Microsoft.ML.Samples/Dynamic/ImageAnalytics/ExtractPixels.cs @@ -0,0 +1,59 @@ +using System.IO; +using Microsoft.ML.Data; + +namespace Microsoft.ML.Samples.Dynamic +{ + public class ExtractPixelsExample + { + // Sample that loads the images from the file system, resizes them (ExtractPixels requires a resizing operation), and extracts the + // values of the pixels as a vector. + public static void ExtractPixels() + { + var mlContext = new MLContext(); + + // Downloading a few images, and an images.tsv file, which contains a list of the files from the dotnet/machinelearning/test/data/images/. + // If you inspect the fileSystem, after running this line, an "images" folder will be created, containing 4 images, and a .tsv file + // enumerating the images. + var imagesDataFile = SamplesUtils.DatasetUtils.DownloadImages(); + + // Preview of the content of the images.tsv file + // + // imagePath imageType + // tomato.bmp tomato + // banana.jpg banana + // hotdog.jpg hotdog + // tomato.jpg tomato + + var data = mlContext.Data.CreateTextLoader(new TextLoader.Arguments() + { + Columns = new[] + { + new TextLoader.Column("ImagePath", DataKind.TX, 0), + new TextLoader.Column("Name", DataKind.TX, 1), + } + }).Read(imagesDataFile); + + var imagesFolder = Path.GetDirectoryName(imagesDataFile); + // Image loading pipeline. + var pipeline = mlContext.Transforms.LoadImages(imagesFolder, ("ImageObject", "ImagePath")) + .Append(mlContext.Transforms.Resize("ImageObject",imageWidth: 100 , imageHeight: 100 )) + .Append(mlContext.Transforms.ExtractPixels("Pixels", "ImageObject")); + + + var transformedData = pipeline.Fit(data).Transform(data); + + // The transformedData IDataView contains the loaded images now + //Preview of the transformedData + var transformedDataPreview = transformedData.Preview(); + + // Preview of the content of the images.tsv file + // + // ImagePath Name ImageObject "Pixels" + // tomato.bmp tomato {System.Drawing.Bitmap} [ 255, 255, 255, ..... 232, 243, 226, ... + // banana.jpg banana {System.Drawing.Bitmap} [ 255, 255, 255, ..... 90, 54, 43, ... + // hotdog.jpg hotdog {System.Drawing.Bitmap} [ 255, 255, 255, ..... 132, 143, 126, ... + // tomato.jpg tomato {System.Drawing.Bitmap} [ 255, 255, 255, ..... 16, 21, 23, ... + + } + } +} diff --git a/docs/samples/Microsoft.ML.Samples/Dynamic/ImageAnalytics/LoadImage.cs b/docs/samples/Microsoft.ML.Samples/Dynamic/ImageAnalytics/LoadImage.cs new file mode 100644 index 0000000000..03b9a0c04d --- /dev/null +++ b/docs/samples/Microsoft.ML.Samples/Dynamic/ImageAnalytics/LoadImage.cs @@ -0,0 +1,55 @@ +using System.IO; +using Microsoft.ML.Data; + +namespace Microsoft.ML.Samples.Dynamic +{ + public class LoadImageExample + { + // Loads the images of the imagesFolder into an IDataView. + public static void LoadImage() + { + var mlContext = new MLContext(); + + // Downloading a few images, and an images.tsv file, which contains a list of the files from the dotnet/machinelearning/test/data/images/. + // If you inspect the fileSystem, after running this line, an "images" folder will be created, containing 4 images, and a .tsv file + // enumerating the images. + var imagesDataFile = SamplesUtils.DatasetUtils.DownloadImages(); + + // Preview of the content of the images.tsv file + // + // imagePath imageType + // tomato.bmp tomato + // banana.jpg banana + // hotdog.jpg hotdog + // tomato.jpg tomato + + var data = mlContext.Data.CreateTextLoader(new TextLoader.Arguments() + { + Columns = new[] + { + new TextLoader.Column("ImagePath", DataKind.TX, 0), + new TextLoader.Column("Name", DataKind.TX, 1), + } + }).Read(imagesDataFile); + + var imagesFolder = Path.GetDirectoryName(imagesDataFile); + // Image loading pipeline. + var pipeline = mlContext.Transforms.LoadImages(imagesFolder, ("ImageReal", "ImagePath")); + var transformedData = pipeline.Fit(data).Transform(data); + + // The transformedData IDataView contains the loaded images now + //Preview of the transformedData + var transformedDataPreview = transformedData.Preview(); + + // Preview of the content of the images.tsv file + // The actual images, in the ImageReal column are of type System.Drawing.Bitmap. + // + // ImagePath Name ImageReal + // tomato.bmp tomato {System.Drawing.Bitmap} + // banana.jpg banana {System.Drawing.Bitmap} + // hotdog.jpg hotdog {System.Drawing.Bitmap} + // tomato.jpg tomato {System.Drawing.Bitmap} + + } + } +} diff --git a/docs/samples/Microsoft.ML.Samples/Dynamic/ImageAnalytics/ResizeImage.cs b/docs/samples/Microsoft.ML.Samples/Dynamic/ImageAnalytics/ResizeImage.cs new file mode 100644 index 0000000000..35e61cba66 --- /dev/null +++ b/docs/samples/Microsoft.ML.Samples/Dynamic/ImageAnalytics/ResizeImage.cs @@ -0,0 +1,58 @@ +using System.IO; +using Microsoft.ML.Data; + +namespace Microsoft.ML.Samples.Dynamic +{ + public class ResizeImageExample + { + // Example on how to load the images from the file system, and resize them. + public static void ResizeImage() + { + var mlContext = new MLContext(); + + // Downloading a few images, and an images.tsv file, which contains a list of the files from the dotnet/machinelearning/test/data/images/. + // If you inspect the fileSystem, after running this line, an "images" folder will be created, containing 4 images, and a .tsv file + // enumerating the images. + var imagesDataFile = SamplesUtils.DatasetUtils.DownloadImages(); + + // Preview of the content of the images.tsv file + // + // imagePath imageType + // tomato.bmp tomato + // banana.jpg banana + // hotdog.jpg hotdog + // tomato.jpg tomato + + var data = mlContext.Data.CreateTextLoader(new TextLoader.Arguments() + { + Columns = new[] + { + new TextLoader.Column("ImagePath", DataKind.TX, 0), + new TextLoader.Column("Name", DataKind.TX, 1), + } + }).Read(imagesDataFile); + + var imagesFolder = Path.GetDirectoryName(imagesDataFile); + // Image loading pipeline. + var pipeline = mlContext.Transforms.LoadImages(imagesFolder, ("ImageReal", "ImagePath")) + .Append(mlContext.Transforms.Resize("ImageReal", imageWidth: 100, imageHeight: 100)); + + + var transformedData = pipeline.Fit(data).Transform(data); + + // The transformedData IDataView contains the loaded images now + //Preview of the transformedData + var transformedDataPreview = transformedData.Preview(); + + // Preview of the content of the images.tsv file + // The actual images, in the ImageReal column are of type System.Drawing.Bitmap. + // + // ImagePath Name ImageReal + // tomato.bmp tomato {System.Drawing.Bitmap} + // banana.jpg banana {System.Drawing.Bitmap} + // hotdog.jpg hotdog {System.Drawing.Bitmap} + // tomato.jpg tomato {System.Drawing.Bitmap} + + } + } +} diff --git a/docs/samples/Microsoft.ML.Samples/Dynamic/Transforms/Concatenate.cs b/docs/samples/Microsoft.ML.Samples/Dynamic/Transforms/Concatenate.cs index ca7985ece8..65898b463a 100644 --- a/docs/samples/Microsoft.ML.Samples/Dynamic/Transforms/Concatenate.cs +++ b/docs/samples/Microsoft.ML.Samples/Dynamic/Transforms/Concatenate.cs @@ -15,7 +15,7 @@ public static void ConcatTransform() var mlContext = new MLContext(); // Get a small dataset as an IEnumerable and them read it as ML.NET's data type. - IEnumerable data = SamplesUtils.DatasetUtils.GetInfertData(); + var data = SamplesUtils.DatasetUtils.GetInfertData(); var trainData = mlContext.Data.ReadFromEnumerable(data); // Preview of the data. diff --git a/docs/samples/Microsoft.ML.Samples/Program.cs b/docs/samples/Microsoft.ML.Samples/Program.cs index 81ad135f0c..9290fb7914 100644 --- a/docs/samples/Microsoft.ML.Samples/Program.cs +++ b/docs/samples/Microsoft.ML.Samples/Program.cs @@ -6,7 +6,7 @@ internal static class Program { static void Main(string[] args) { - WordEmbeddingTransform.ExtractEmbeddings(); + ExtractPixelsExample.ExtractPixels(); } } } diff --git a/src/Microsoft.ML.ImageAnalytics/EntryPoints/ImageAnalytics.cs b/src/Microsoft.ML.ImageAnalytics/EntryPoints/ImageAnalytics.cs index dc190933f2..522ebd0347 100644 --- a/src/Microsoft.ML.ImageAnalytics/EntryPoints/ImageAnalytics.cs +++ b/src/Microsoft.ML.ImageAnalytics/EntryPoints/ImageAnalytics.cs @@ -11,12 +11,12 @@ namespace Microsoft.ML.ImageAnalytics.EntryPoints { internal static class ImageAnalytics { - [TlcModule.EntryPoint(Name = "Transforms.ImageLoader", Desc = ImageLoaderTransformer.Summary, - UserName = ImageLoaderTransformer.UserName, ShortName = ImageLoaderTransformer.LoaderSignature)] - public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, ImageLoaderTransformer.Arguments input) + [TlcModule.EntryPoint(Name = "Transforms.ImageLoader", Desc = ImageLoadingTransformer.Summary, + UserName = ImageLoadingTransformer.UserName, ShortName = ImageLoadingTransformer.LoaderSignature)] + public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, ImageLoadingTransformer.Options input) { var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageLoaderTransform", input); - var xf = ImageLoaderTransformer.Create(h, input, input.Data); + var xf = ImageLoadingTransformer.Create(h, input, input.Data); return new CommonOutputs.TransformOutput() { Model = new TransformModelImpl(h, xf, input.Data), @@ -24,12 +24,12 @@ public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, Im }; } - [TlcModule.EntryPoint(Name = "Transforms.ImageResizer", Desc = ImageResizerTransformer.Summary, - UserName = ImageResizerTransformer.UserName, ShortName = ImageResizerTransformer.LoaderSignature)] - public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, ImageResizerTransformer.Arguments input) + [TlcModule.EntryPoint(Name = "Transforms.ImageResizer", Desc = ImageResizingTransformer.Summary, + UserName = ImageResizingTransformer.UserName, ShortName = ImageResizingTransformer.LoaderSignature)] + public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, ImageResizingTransformer.Arguments input) { var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageResizerTransform", input); - var xf = ImageResizerTransformer.Create(h, input, input.Data); + var xf = ImageResizingTransformer.Create(h, input, input.Data); return new CommonOutputs.TransformOutput() { Model = new TransformModelImpl(h, xf, input.Data), @@ -37,12 +37,12 @@ public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, I }; } - [TlcModule.EntryPoint(Name = "Transforms.ImagePixelExtractor", Desc = ImagePixelExtractorTransformer.Summary, - UserName = ImagePixelExtractorTransformer.UserName, ShortName = ImagePixelExtractorTransformer.LoaderSignature)] - public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment env, ImagePixelExtractorTransformer.Arguments input) + [TlcModule.EntryPoint(Name = "Transforms.ImagePixelExtractor", Desc = ImagePixelExtractingTransformer.Summary, + UserName = ImagePixelExtractingTransformer.UserName, ShortName = ImagePixelExtractingTransformer.LoaderSignature)] + public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment env, ImagePixelExtractingTransformer.Options input) { var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImagePixelExtractorTransform", input); - var xf = ImagePixelExtractorTransformer.Create(h, input, input.Data); + var xf = ImagePixelExtractingTransformer.Create(h, input, input.Data); return new CommonOutputs.TransformOutput() { Model = new TransformModelImpl(h, xf, input.Data), @@ -50,12 +50,12 @@ public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment }; } - [TlcModule.EntryPoint(Name = "Transforms.ImageGrayscale", Desc = ImageGrayscaleTransformer.Summary, - UserName = ImageGrayscaleTransformer.UserName, ShortName = ImageGrayscaleTransformer.LoaderSignature)] - public static CommonOutputs.TransformOutput ImageGrayscale(IHostEnvironment env, ImageGrayscaleTransformer.Arguments input) + [TlcModule.EntryPoint(Name = "Transforms.ImageGrayscale", Desc = ImageGrayscalingTransformer.Summary, + UserName = ImageGrayscalingTransformer.UserName, ShortName = ImageGrayscalingTransformer.LoaderSignature)] + public static CommonOutputs.TransformOutput ImageGrayscale(IHostEnvironment env, ImageGrayscalingTransformer.Options input) { var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageGrayscaleTransform", input); - var xf = ImageGrayscaleTransformer.Create(h, input, input.Data); + var xf = ImageGrayscalingTransformer.Create(h, input, input.Data); return new CommonOutputs.TransformOutput() { Model = new TransformModelImpl(h, xf, input.Data), diff --git a/src/Microsoft.ML.ImageAnalytics/ExtensionsCatalog.cs b/src/Microsoft.ML.ImageAnalytics/ExtensionsCatalog.cs index 192d12bd72..cc1b78aaba 100644 --- a/src/Microsoft.ML.ImageAnalytics/ExtensionsCatalog.cs +++ b/src/Microsoft.ML.ImageAnalytics/ExtensionsCatalog.cs @@ -9,65 +9,129 @@ namespace Microsoft.ML { public static class ImageEstimatorsCatalog { - /// - /// Converts the images to grayscale. - /// + /// /// The transform's catalog. - /// The name of the columns containing the image paths(first item of the tuple), and the name of the resulting output column (second item of the tuple). - public static ImageGrayscalingEstimator ConvertToGrayscale(this TransformsCatalog catalog, params (string outputColumnName, string inputColumnName)[] columns) - => new ImageGrayscalingEstimator(CatalogUtils.GetEnvironment(catalog), columns); + /// The name of the columns containing the name of the resulting output column (first item of the tuple), and the paths of the images to work on (second item of the tuple). + /// + /// + /// + /// + public static ImageGrayscalingEstimator ConvertToGrayscale(this TransformsCatalog catalog, params (string outputColumnName, string inputColumnName)[] columnPairs) + => new ImageGrayscalingEstimator(CatalogUtils.GetEnvironment(catalog), columnPairs); /// - /// Loads the images from a given folder. + /// Loads the images from the into memory. /// + /// + /// The image get loaded in memory as a type. + /// Loading is the first step of almost every pipeline that does image processing, and further analysis on images. + /// The images to load need to be in the formats supported by . + /// For end-to-end image processing pipelines, and scenarios in your applications, see the + /// examples in the machinelearning-samples github repository. + /// + /// /// The transform's catalog. /// The images folder. - /// The name of the columns containing the image paths(first item of the tuple), and the name of the resulting output column (second item of the tuple). - public static ImageLoadingEstimator LoadImages(this TransformsCatalog catalog, string imageFolder, params (string outputColumnName, string inputColumnName)[] columns) - => new ImageLoadingEstimator(CatalogUtils.GetEnvironment(catalog), imageFolder, columns); + /// The name of the columns containing the image paths(first item of the tuple), and the name of the resulting output column (second item of the tuple). + /// + /// + /// + /// + public static ImageLoadingEstimator LoadImages(this TransformsCatalog catalog, string imageFolder, params (string outputColumnName, string inputColumnName)[] columnPairs) + => new ImageLoadingEstimator(CatalogUtils.GetEnvironment(catalog), imageFolder, columnPairs); - /// - /// Loads the images from a given folder. - /// - /// The transform's catalog. - /// Name of the column resulting from the transformation of . - /// Name of column to transform. If set to , the value of the will be used as source. - /// The color schema as defined in . - /// - public static ImagePixelExtractingEstimator ExtractPixels(this TransformsCatalog catalog, string outputColumnName, string inputColumnName = null, - ImagePixelExtractorTransformer.ColorBits colors = ImagePixelExtractorTransformer.ColorBits.Rgb, bool interleave = false) - => new ImagePixelExtractingEstimator(CatalogUtils.GetEnvironment(catalog), outputColumnName, inputColumnName, colors, interleave); + /// + /// The transform's catalog. + /// Name of the column resulting from the transformation of . + /// Name of column to transform. If set to , the value of the will be used as source. + /// Specifies which to extract from the image. The order of colors is: Alpha, Red, Green Blue. + /// Wheather to interleave the pixels, meaning keep them in the `ARGB ARGB` order, or leave them separated in the planar form, where the colors are outputed one by one + /// alpha, red, green, blue for all the pixels of the image. + /// Scale color pixel value by this amount. + /// Offset color pixel value by this amount. + /// Output the array as float array. If false, output as byte array. + /// + /// + /// + /// + public static ImagePixelExtractingEstimator ExtractPixels(this TransformsCatalog catalog, + string outputColumnName, + string inputColumnName = null, + ImagePixelExtractingEstimator.ColorBits colors = ImagePixelExtractingEstimator.ColorBits.Rgb, + bool interleave = false, + float scale = ImagePixelExtractingTransformer.Defaults.Scale, + float offset = ImagePixelExtractingTransformer.Defaults.Offset, + bool asFloat = ImagePixelExtractingTransformer.Defaults.Convert) + => new ImagePixelExtractingEstimator(CatalogUtils.GetEnvironment(catalog), outputColumnName, inputColumnName, colors, interleave, scale, offset, asFloat); - /// - /// Loads the images from a given folder. - /// + /// /// The transform's catalog. /// The name of the columns containing the image paths, and per-column configurations. - public static ImagePixelExtractingEstimator ExtractPixels(this TransformsCatalog catalog, params ImagePixelExtractorTransformer.ColumnInfo[] columns) + public static ImagePixelExtractingEstimator ExtractPixels(this TransformsCatalog catalog, params ImagePixelExtractingEstimator.ColumnInfo[] columns) => new ImagePixelExtractingEstimator(CatalogUtils.GetEnvironment(catalog), columns); /// - /// Resizes an image. + /// Resizes the images to a new width and height. /// + /// + /// In image processing pipelines, often machine learning practitioner make use of + /// pre-trained DNN featurizers to extract features for usage in the machine learning algorithms. + /// Those pre-trained models have a defined width and height for their input images, so often, after getting loaded, the images will need to get resized before + /// further processing. + /// The new width and height can be specified in the and + /// + /// + /// /// The transform's catalog. /// Name of the input column. /// Name of the resulting output column. - /// The image width. - /// The image height. - /// The type of image resizing as specified in . - /// Where to place the anchor, to start cropping. Options defined in - /// - public static ImageResizingEstimator Resize(this TransformsCatalog catalog, string outputColumnName, int imageWidth, int imageHeight, - string inputColumnName = null, ImageResizerTransformer.ResizingKind resizing = ImageResizerTransformer.ResizingKind.IsoCrop, ImageResizerTransformer.Anchor cropAnchor = ImageResizerTransformer.Anchor.Center) + /// The transformed image width. + /// The transformed image height. + /// The type of image resizing as specified in . + /// Where to place the anchor, to start cropping. Options defined in + /// + /// + /// + /// + public static ImageResizingEstimator Resize(this TransformsCatalog catalog, + string outputColumnName, + int imageWidth, + int imageHeight, + string inputColumnName = null, + ImageResizingEstimator.ResizingKind resizing = ImageResizingEstimator.ResizingKind.IsoCrop, + ImageResizingEstimator.Anchor cropAnchor = ImageResizingEstimator.Anchor.Center) => new ImageResizingEstimator(CatalogUtils.GetEnvironment(catalog), outputColumnName, imageWidth, imageHeight, inputColumnName, resizing, cropAnchor); /// - /// Resizes an image. + /// Resizes the images to a new width and height. /// + /// + /// In image processing pipelines, often machine learning practitioner make use of + /// pre - trained DNN featurizers to extract features for usage in the machine learning algorithms. + /// Those pre-trained models have a defined width and height for their input images, so often, after getting loaded, the images will need to get resized before + /// further processing. + /// The new width and height, as well as other properties of resizing, like type of scaling (uniform, or non-uniform), and whether to pad the image, + /// or just crop it can be specified separately for each column loaded, through the . + /// + /// + /// /// The transform's catalog. /// The names of the columns to transform. - /// - public static ImageResizingEstimator Resize(this TransformsCatalog catalog, params ImageResizerTransformer.ColumnInfo[] columns) + /// + /// + /// + /// + public static ImageResizingEstimator Resize(this TransformsCatalog catalog, params ImageResizingEstimator.ColumnInfo[] columns) => new ImageResizingEstimator(CatalogUtils.GetEnvironment(catalog), columns); } } diff --git a/src/Microsoft.ML.ImageAnalytics/ImageGrayscaleTransform.cs b/src/Microsoft.ML.ImageAnalytics/ImageGrayscale.cs similarity index 66% rename from src/Microsoft.ML.ImageAnalytics/ImageGrayscaleTransform.cs rename to src/Microsoft.ML.ImageAnalytics/ImageGrayscale.cs index 8808584eec..cf5388d8da 100644 --- a/src/Microsoft.ML.ImageAnalytics/ImageGrayscaleTransform.cs +++ b/src/Microsoft.ML.ImageAnalytics/ImageGrayscale.cs @@ -18,29 +18,38 @@ using Microsoft.ML.Internal.Utilities; using Microsoft.ML.Model; -[assembly: LoadableClass(ImageGrayscaleTransformer.Summary, typeof(IDataTransform), typeof(ImageGrayscaleTransformer), typeof(ImageGrayscaleTransformer.Arguments), typeof(SignatureDataTransform), - ImageGrayscaleTransformer.UserName, "ImageGrayscaleTransform", "ImageGrayscale")] +[assembly: LoadableClass(ImageGrayscalingTransformer.Summary, typeof(IDataTransform), typeof(ImageGrayscalingTransformer), typeof(ImageGrayscalingTransformer.Options), typeof(SignatureDataTransform), + ImageGrayscalingTransformer.UserName, "ImageGrayscaleTransform", "ImageGrayscale")] -[assembly: LoadableClass(ImageGrayscaleTransformer.Summary, typeof(IDataTransform), typeof(ImageGrayscaleTransformer), null, typeof(SignatureLoadDataTransform), - ImageGrayscaleTransformer.UserName, ImageGrayscaleTransformer.LoaderSignature)] +[assembly: LoadableClass(ImageGrayscalingTransformer.Summary, typeof(IDataTransform), typeof(ImageGrayscalingTransformer), null, typeof(SignatureLoadDataTransform), + ImageGrayscalingTransformer.UserName, ImageGrayscalingTransformer.LoaderSignature)] -[assembly: LoadableClass(typeof(ImageGrayscaleTransformer), null, typeof(SignatureLoadModel), - ImageGrayscaleTransformer.UserName, ImageGrayscaleTransformer.LoaderSignature)] +[assembly: LoadableClass(typeof(ImageGrayscalingTransformer), null, typeof(SignatureLoadModel), + ImageGrayscalingTransformer.UserName, ImageGrayscalingTransformer.LoaderSignature)] -[assembly: LoadableClass(typeof(IRowMapper), typeof(ImageGrayscaleTransformer), null, typeof(SignatureLoadRowMapper), - ImageGrayscaleTransformer.UserName, ImageGrayscaleTransformer.LoaderSignature)] +[assembly: LoadableClass(typeof(IRowMapper), typeof(ImageGrayscalingTransformer), null, typeof(SignatureLoadRowMapper), + ImageGrayscalingTransformer.UserName, ImageGrayscalingTransformer.LoaderSignature)] namespace Microsoft.ML.ImageAnalytics { // REVIEW: Rewrite as LambdaTransform to simplify. // REVIEW: Should it be separate transform or part of ImageResizerTransform? /// - /// Transform which takes one or many columns of type in IDataView and - /// convert them to greyscale representation of the same image. + /// produced by fitting the to an . /// - public sealed class ImageGrayscaleTransformer : OneToOneTransformerBase + /// + /// Calling converts the image to grayscale. + /// The images might be converted to grayscale to reduce the complexity of the model. + /// The grayed out images contain less information to process than the colored images. + /// Another use case for converting to grayscale is to generate new images out of the existing ones, so you can have a larger dataset, + /// a technique known as data augmentation. + /// For end-to-end image processing pipelines, and scenarios in your applications, see the + /// examples in the machinelearning-samples github repository. + /// + /// + public sealed class ImageGrayscalingTransformer : OneToOneTransformerBase { - public sealed class Column : OneToOneColumn + internal sealed class Column : OneToOneColumn { internal static Column Parse(string str) { @@ -57,7 +66,7 @@ internal bool TryUnparse(StringBuilder sb) } } - public class Arguments : TransformInputBase + internal class Options : TransformInputBase { [Argument(ArgumentType.Multiple | ArgumentType.Required, HelpText = "New column definition(s) (optional form: name:src)", Name = "Column", ShortName = "col", SortOrder = 1)] public Column[] Columns; @@ -76,11 +85,14 @@ private static VersionInfo GetVersionInfo() verReadableCur: 0x00010001, verWeCanReadBack: 0x00010001, loaderSignature: LoaderSignature, - loaderAssemblyName: typeof(ImageGrayscaleTransformer).Assembly.FullName); + loaderAssemblyName: typeof(ImageGrayscalingTransformer).Assembly.FullName); } private const string RegistrationName = "ImageGrayscale"; + /// + /// The input and output column pairs passed to this . + /// public IReadOnlyCollection<(string outputColumnName, string inputColumnName)> Columns => ColumnPairs.AsReadOnly(); /// @@ -89,34 +101,34 @@ private static VersionInfo GetVersionInfo() /// The estimator's local . /// The name of the columns containing the image paths(first item of the tuple), and the name of the resulting output column (second item of the tuple). - public ImageGrayscaleTransformer(IHostEnvironment env, params (string outputColumnName, string inputColumnName)[] columns) + internal ImageGrayscalingTransformer(IHostEnvironment env, params (string outputColumnName, string inputColumnName)[] columns) : base(Contracts.CheckRef(env, nameof(env)).Register(RegistrationName), columns) { } // Factory method for SignatureDataTransform. - internal static IDataTransform Create(IHostEnvironment env, Arguments args, IDataView input) + internal static IDataTransform Create(IHostEnvironment env, Options args, IDataView input) { Contracts.CheckValue(env, nameof(env)); env.CheckValue(args, nameof(args)); env.CheckValue(input, nameof(input)); env.CheckValue(args.Columns, nameof(args.Columns)); - return new ImageGrayscaleTransformer(env, args.Columns.Select(x => (x.Name, x.Source ?? x.Name)).ToArray()) + return new ImageGrayscalingTransformer(env, args.Columns.Select(x => (x.Name, x.Source ?? x.Name)).ToArray()) .MakeDataTransform(input); } // Factory method for SignatureLoadModel. - private static ImageGrayscaleTransformer Create(IHostEnvironment env, ModelLoadContext ctx) + private static ImageGrayscalingTransformer Create(IHostEnvironment env, ModelLoadContext ctx) { Contracts.CheckValue(env, nameof(env)); var host = env.Register(RegistrationName); host.CheckValue(ctx, nameof(ctx)); ctx.CheckAtModel(GetVersionInfo()); - return new ImageGrayscaleTransformer(host, ctx); + return new ImageGrayscalingTransformer(host, ctx); } - private ImageGrayscaleTransformer(IHost host, ModelLoadContext ctx) + private ImageGrayscalingTransformer(IHost host, ModelLoadContext ctx) : base(host, ctx) { } @@ -161,9 +173,9 @@ protected override void CheckInputColumn(Schema inputSchema, int col, int srcCol private sealed class Mapper : OneToOneMapperBase { - private ImageGrayscaleTransformer _parent; + private ImageGrayscalingTransformer _parent; - public Mapper(ImageGrayscaleTransformer parent, Schema inputSchema) + public Mapper(ImageGrayscalingTransformer parent, Schema inputSchema) : base(parent.Host.Register(nameof(Mapper)), parent, inputSchema) { _parent = parent; @@ -217,9 +229,19 @@ protected override Delegate MakeGetter(Row input, int iinfo, Func act } /// - /// Converts the images to grayscale. + /// that converts the image to grayscale. /// - public sealed class ImageGrayscalingEstimator : TrivialEstimator + /// + /// Calling in this estimator, produces an . + /// The images might be converted to grayscale to reduce the complexity of the model. + /// The grayed out images contain less information to process than the colored images. + /// Another use case for converting to grayscale is to generate new images out of the existing ones, so you can have a larger dataset, + /// a technique known as data augmentation. + /// For end-to-end image processing pipelines, and scenarios in your applications, see the + /// examples in the machinelearning-samples github repository. + /// + /// + public sealed class ImageGrayscalingEstimator : TrivialEstimator { /// @@ -227,11 +249,16 @@ public sealed class ImageGrayscalingEstimator : TrivialEstimator /// The estimator's local . /// The name of the columns containing the image paths(first item of the tuple), and the name of the resulting output column (second item of the tuple). - public ImageGrayscalingEstimator(IHostEnvironment env, params (string outputColumnName, string inputColumnName)[] columns) - : base(Contracts.CheckRef(env, nameof(env)).Register(nameof(ImageGrayscalingEstimator)), new ImageGrayscaleTransformer(env, columns)) + [BestFriend] + internal ImageGrayscalingEstimator(IHostEnvironment env, params (string outputColumnName, string inputColumnName)[] columns) + : base(Contracts.CheckRef(env, nameof(env)).Register(nameof(ImageGrayscalingEstimator)), new ImageGrayscalingTransformer(env, columns)) { } + /// + /// Returns the of the schema which will be produced by the transformer. + /// Used for schema propagation and verification in a pipeline. + /// public override SchemaShape GetOutputSchema(SchemaShape inputSchema) { Host.CheckValue(inputSchema, nameof(inputSchema)); diff --git a/src/Microsoft.ML.ImageAnalytics/ImageLoaderTransform.cs b/src/Microsoft.ML.ImageAnalytics/ImageLoader.cs similarity index 67% rename from src/Microsoft.ML.ImageAnalytics/ImageLoaderTransform.cs rename to src/Microsoft.ML.ImageAnalytics/ImageLoader.cs index 9a5952fc9c..8829d1dd2f 100644 --- a/src/Microsoft.ML.ImageAnalytics/ImageLoaderTransform.cs +++ b/src/Microsoft.ML.ImageAnalytics/ImageLoader.cs @@ -18,24 +18,32 @@ using Microsoft.ML.Internal.Utilities; using Microsoft.ML.Model; -[assembly: LoadableClass(ImageLoaderTransformer.Summary, typeof(IDataTransform), typeof(ImageLoaderTransformer), typeof(ImageLoaderTransformer.Arguments), typeof(SignatureDataTransform), - ImageLoaderTransformer.UserName, "ImageLoaderTransform", "ImageLoader")] +[assembly: LoadableClass(ImageLoadingTransformer.Summary, typeof(IDataTransform), typeof(ImageLoadingTransformer), typeof(ImageLoadingTransformer.Options), typeof(SignatureDataTransform), + ImageLoadingTransformer.UserName, "ImageLoaderTransform", "ImageLoader")] -[assembly: LoadableClass(ImageLoaderTransformer.Summary, typeof(IDataTransform), typeof(ImageLoaderTransformer), null, typeof(SignatureLoadDataTransform), - ImageLoaderTransformer.UserName, ImageLoaderTransformer.LoaderSignature)] +[assembly: LoadableClass(ImageLoadingTransformer.Summary, typeof(IDataTransform), typeof(ImageLoadingTransformer), null, typeof(SignatureLoadDataTransform), + ImageLoadingTransformer.UserName, ImageLoadingTransformer.LoaderSignature)] -[assembly: LoadableClass(typeof(ImageLoaderTransformer), null, typeof(SignatureLoadModel), "", ImageLoaderTransformer.LoaderSignature)] +[assembly: LoadableClass(typeof(ImageLoadingTransformer), null, typeof(SignatureLoadModel), "", ImageLoadingTransformer.LoaderSignature)] -[assembly: LoadableClass(typeof(IRowMapper), typeof(ImageLoaderTransformer), null, typeof(SignatureLoadRowMapper), "", ImageLoaderTransformer.LoaderSignature)] +[assembly: LoadableClass(typeof(IRowMapper), typeof(ImageLoadingTransformer), null, typeof(SignatureLoadRowMapper), "", ImageLoadingTransformer.LoaderSignature)] namespace Microsoft.ML.ImageAnalytics { /// - /// Transform which takes one or many columns of type ReadOnlyMemory and loads them as + /// The produced by fitting an to an . /// - public sealed class ImageLoaderTransformer : OneToOneTransformerBase + /// + /// Calling that loads images from the disk. + /// Loading is the first step of almost every pipeline that does image processing, and further analysis on images. + /// The images to load need to be in the formats supported by . + /// For end-to-end image processing pipelines, and scenarios in your applications, see the + /// examples in the machinelearning-samples github repository. + /// + /// + public sealed class ImageLoadingTransformer : OneToOneTransformerBase { - public sealed class Column : OneToOneColumn + internal sealed class Column : OneToOneColumn { internal static Column Parse(string str) { @@ -54,7 +62,7 @@ internal bool TryUnparse(StringBuilder sb) } } - public sealed class Arguments : TransformInputBase + internal sealed class Options : TransformInputBase { [Argument(ArgumentType.Multiple | ArgumentType.Required, HelpText = "New column definition(s) (optional form: name:src)", Name = "Column", ShortName = "col", SortOrder = 1)] public Column[] Columns; @@ -67,40 +75,46 @@ public sealed class Arguments : TransformInputBase internal const string UserName = "Image Loader Transform"; internal const string LoaderSignature = "ImageLoaderTransform"; + /// + /// The folder to load the images from. + /// public readonly string ImageFolder; + /// + /// The columns passed to this . + /// public IReadOnlyCollection<(string outputColumnName, string inputColumnName)> Columns => ColumnPairs.AsReadOnly(); /// - /// Load images in memory. + /// Initializes a new instance of . /// /// The host environment. /// Folder where to look for images. /// Names of input and output columns. - public ImageLoaderTransformer(IHostEnvironment env, string imageFolder = null, params (string outputColumnName, string inputColumnName)[] columns) - : base(Contracts.CheckRef(env, nameof(env)).Register(nameof(ImageLoaderTransformer)), columns) + internal ImageLoadingTransformer(IHostEnvironment env, string imageFolder = null, params (string outputColumnName, string inputColumnName)[] columns) + : base(Contracts.CheckRef(env, nameof(env)).Register(nameof(ImageLoadingTransformer)), columns) { ImageFolder = imageFolder; } // Factory method for SignatureDataTransform. - internal static IDataTransform Create(IHostEnvironment env, Arguments args, IDataView data) + internal static IDataTransform Create(IHostEnvironment env, Options args, IDataView data) { - return new ImageLoaderTransformer(env, args.ImageFolder, args.Columns.Select(x => (x.Name, x.Source ?? x.Name)).ToArray()) + return new ImageLoadingTransformer(env, args.ImageFolder, args.Columns.Select(x => (x.Name, x.Source ?? x.Name)).ToArray()) .MakeDataTransform(data); } // Factory method for SignatureLoadModel. - private static ImageLoaderTransformer Create(IHostEnvironment env, ModelLoadContext ctx) + private static ImageLoadingTransformer Create(IHostEnvironment env, ModelLoadContext ctx) { Contracts.CheckValue(env, nameof(env)); env.CheckValue(ctx, nameof(ctx)); ctx.CheckAtModel(GetVersionInfo()); - return new ImageLoaderTransformer(env.Register(nameof(ImageLoaderTransformer)), ctx); + return new ImageLoadingTransformer(env.Register(nameof(ImageLoadingTransformer)), ctx); } - private ImageLoaderTransformer(IHost host, ModelLoadContext ctx) + private ImageLoadingTransformer(IHost host, ModelLoadContext ctx) : base(host, ctx) { // *** Binary format *** @@ -148,17 +162,17 @@ private static VersionInfo GetVersionInfo() verReadableCur: 0x00010002, verWeCanReadBack: 0x00010002, loaderSignature: LoaderSignature, - loaderAssemblyName: typeof(ImageLoaderTransformer).Assembly.FullName); + loaderAssemblyName: typeof(ImageLoadingTransformer).Assembly.FullName); } private protected override IRowMapper MakeRowMapper(Schema schema) => new Mapper(this, schema); private sealed class Mapper : OneToOneMapperBase { - private readonly ImageLoaderTransformer _parent; + private readonly ImageLoadingTransformer _parent; private readonly ImageType _imageType; - public Mapper(ImageLoaderTransformer parent, Schema inputSchema) + public Mapper(ImageLoadingTransformer parent, Schema inputSchema) : base(parent.Host.Register(nameof(Mapper)), parent, inputSchema) { _imageType = new ImageType(); @@ -217,9 +231,17 @@ protected override Schema.DetachedColumn[] GetOutputColumnsCore() } /// - /// Load images in memory. + /// that loads images from the disk. /// - public sealed class ImageLoadingEstimator : TrivialEstimator + /// + /// Calling in this estimator, produces an . + /// Loading is the first step of almost every pipeline that does image processing, and further analysis on images. + /// The images to load need to be in the formats supported by . + /// For end-to-end image processing pipelines, and scenarios in your applications, see the + /// examples in the machinelearning-samples github repository. + /// + /// + public sealed class ImageLoadingEstimator : TrivialEstimator { private readonly ImageType _imageType; @@ -229,17 +251,21 @@ public sealed class ImageLoadingEstimator : TrivialEstimatorThe host environment. /// Folder where to look for images. /// Names of input and output columns. - public ImageLoadingEstimator(IHostEnvironment env, string imageFolder, params (string outputColumnName, string inputColumnName)[] columns) - : this(env, new ImageLoaderTransformer(env, imageFolder, columns)) + internal ImageLoadingEstimator(IHostEnvironment env, string imageFolder, params (string outputColumnName, string inputColumnName)[] columns) + : this(env, new ImageLoadingTransformer(env, imageFolder, columns)) { } - private ImageLoadingEstimator(IHostEnvironment env, ImageLoaderTransformer transformer) + internal ImageLoadingEstimator(IHostEnvironment env, ImageLoadingTransformer transformer) : base(Contracts.CheckRef(env, nameof(env)).Register(nameof(ImageLoadingEstimator)), transformer) { _imageType = new ImageType(); } + /// + /// Returns the of the schema which will be produced by the transformer. + /// Used for schema propagation and verification in a pipeline. + /// public override SchemaShape GetOutputSchema(SchemaShape inputSchema) { Host.CheckValue(inputSchema, nameof(inputSchema)); diff --git a/src/Microsoft.ML.ImageAnalytics/ImagePixelExtractorTransform.cs b/src/Microsoft.ML.ImageAnalytics/ImagePixelExtractor.cs similarity index 76% rename from src/Microsoft.ML.ImageAnalytics/ImagePixelExtractorTransform.cs rename to src/Microsoft.ML.ImageAnalytics/ImagePixelExtractor.cs index e5fc313fca..a34fff871c 100644 --- a/src/Microsoft.ML.ImageAnalytics/ImagePixelExtractorTransform.cs +++ b/src/Microsoft.ML.ImageAnalytics/ImagePixelExtractor.cs @@ -18,26 +18,34 @@ using Microsoft.ML.Internal.Utilities; using Microsoft.ML.Model; -[assembly: LoadableClass(ImagePixelExtractorTransformer.Summary, typeof(IDataTransform), typeof(ImagePixelExtractorTransformer), typeof(ImagePixelExtractorTransformer.Arguments), typeof(SignatureDataTransform), - ImagePixelExtractorTransformer.UserName, "ImagePixelExtractorTransform", "ImagePixelExtractor")] +[assembly: LoadableClass(ImagePixelExtractingTransformer.Summary, typeof(IDataTransform), typeof(ImagePixelExtractingTransformer), typeof(ImagePixelExtractingTransformer.Options), typeof(SignatureDataTransform), + ImagePixelExtractingTransformer.UserName, "ImagePixelExtractorTransform", "ImagePixelExtractor")] -[assembly: LoadableClass(ImagePixelExtractorTransformer.Summary, typeof(IDataTransform), typeof(ImagePixelExtractorTransformer), null, typeof(SignatureLoadDataTransform), - ImagePixelExtractorTransformer.UserName, ImagePixelExtractorTransformer.LoaderSignature)] +[assembly: LoadableClass(ImagePixelExtractingTransformer.Summary, typeof(IDataTransform), typeof(ImagePixelExtractingTransformer), null, typeof(SignatureLoadDataTransform), + ImagePixelExtractingTransformer.UserName, ImagePixelExtractingTransformer.LoaderSignature)] -[assembly: LoadableClass(typeof(ImagePixelExtractorTransformer), null, typeof(SignatureLoadModel), - ImagePixelExtractorTransformer.UserName, ImagePixelExtractorTransformer.LoaderSignature)] +[assembly: LoadableClass(typeof(ImagePixelExtractingTransformer), null, typeof(SignatureLoadModel), + ImagePixelExtractingTransformer.UserName, ImagePixelExtractingTransformer.LoaderSignature)] -[assembly: LoadableClass(typeof(IRowMapper), typeof(ImagePixelExtractorTransformer), null, typeof(SignatureLoadRowMapper), - ImagePixelExtractorTransformer.UserName, ImagePixelExtractorTransformer.LoaderSignature)] +[assembly: LoadableClass(typeof(IRowMapper), typeof(ImagePixelExtractingTransformer), null, typeof(SignatureLoadRowMapper), + ImagePixelExtractingTransformer.UserName, ImagePixelExtractingTransformer.LoaderSignature)] namespace Microsoft.ML.ImageAnalytics { /// - /// Transformer which takes one or many columns of and convert them into vector representation. + /// produced by fitting the to an . /// - public sealed class ImagePixelExtractorTransformer : OneToOneTransformerBase + /// + /// During the transformation, the columns of are converted them into a vector representing the image pixels + /// than can be further used as features by the algorithms added to the pipeline. + /// + /// + /// + /// + public sealed class ImagePixelExtractingTransformer : OneToOneTransformerBase { - public class Column : OneToOneColumn + [BestFriend] + internal class Column : OneToOneColumn { [Argument(ArgumentType.AtMostOnce, HelpText = "Whether to use alpha channel", ShortName = "alpha")] public bool? UseAlpha; @@ -86,7 +94,8 @@ internal bool TryUnparse(StringBuilder sb) } } - public class Arguments : TransformInputBase + [BestFriend] + internal class Options : TransformInputBase { [Argument(ArgumentType.Multiple | ArgumentType.Required, HelpText = "New column definition(s) (optional form: name:src)", Name = "Column", ShortName = "col", SortOrder = 1)] public Column[] Columns; @@ -116,193 +125,15 @@ public class Arguments : TransformInputBase public Single? Scale; } - /// - /// Which color channels are extracted. Note that these values are serialized so should not be modified. - /// - [Flags] - public enum ColorBits : byte - { - Alpha = 0x01, - Red = 0x02, - Green = 0x04, - Blue = 0x08, - - Rgb = Red | Green | Blue, - All = Alpha | Red | Green | Blue - } - internal static class Defaults { - public const ColorBits Colors = ColorBits.Rgb; + public const ImagePixelExtractingEstimator.ColorBits Colors = ImagePixelExtractingEstimator.ColorBits.Rgb; public const bool Interleave = false; public const bool Convert = true; public const float Scale = 1f; public const float Offset = 0f; } - /// - /// Describes how the transformer handles one image pixel extraction column pair. - /// - public sealed class ColumnInfo - { - public readonly string Name; - public readonly string InputColumnName; - - public readonly ColorBits Colors; - public readonly byte Planes; - public readonly float Offset; - public readonly float Scale; - public readonly bool Interleave; - public readonly bool AsFloat; - - public bool Alpha => (Colors & ColorBits.Alpha) != 0; - public bool Red => (Colors & ColorBits.Red) != 0; - public bool Green => (Colors & ColorBits.Green) != 0; - public bool Blue => (Colors & ColorBits.Blue) != 0; - - internal ColumnInfo(Column item, Arguments args) - { - Contracts.CheckValue(item, nameof(item)); - Contracts.CheckValue(args, nameof(args)); - - Name = item.Name; - InputColumnName = item.Source ?? item.Name; - - if (item.UseAlpha ?? args.UseAlpha) { Colors |= ColorBits.Alpha; Planes++; } - if (item.UseRed ?? args.UseRed) { Colors |= ColorBits.Red; Planes++; } - if (item.UseGreen ?? args.UseGreen) { Colors |= ColorBits.Green; Planes++; } - if (item.UseBlue ?? args.UseBlue) { Colors |= ColorBits.Blue; Planes++; } - Contracts.CheckUserArg(Planes > 0, nameof(item.UseRed), "Need to use at least one color plane"); - - Interleave = item.InterleaveArgb ?? args.InterleaveArgb; - - AsFloat = item.Convert ?? args.Convert; - if (!AsFloat) - { - Offset = Defaults.Offset; - Scale = Defaults.Scale; - } - else - { - Offset = item.Offset ?? args.Offset ?? Defaults.Offset; - Scale = item.Scale ?? args.Scale ?? Defaults.Scale; - Contracts.CheckUserArg(FloatUtils.IsFinite(Offset), nameof(item.Offset)); - Contracts.CheckUserArg(FloatUtils.IsFiniteNonZero(Scale), nameof(item.Scale)); - } - } - - /// - /// Describes how the transformer handles one input-output column pair. - /// - /// Name of the column resulting from the transformation of . - /// Name of column to transform. If set to , the value of the will be used as source. - /// What colors to extract. - /// - /// Scale color pixel value by this amount. - /// Offset color pixel value by this amount. - /// Output array as float array. If false, output as byte array. - - public ColumnInfo(string name, string inputColumnName = null, - ColorBits colors = Defaults.Colors, - bool interleave = Defaults.Interleave, - float scale = Defaults.Scale, - float offset = Defaults.Offset, - bool asFloat = Defaults.Convert) - { - Contracts.CheckNonWhiteSpace(name, nameof(name)); - - Name = name; - InputColumnName = inputColumnName ?? name; - Colors = colors; - - if ((Colors & ColorBits.Alpha) == ColorBits.Alpha) Planes++; - if ((Colors & ColorBits.Red) == ColorBits.Red) Planes++; - if ((Colors & ColorBits.Green) == ColorBits.Green) Planes++; - if ((Colors & ColorBits.Blue) == ColorBits.Blue) Planes++; - Contracts.CheckParam(Planes > 0, nameof(colors), "Need to use at least one color plane"); - - Interleave = interleave; - - AsFloat = asFloat; - if (!AsFloat) - { - Offset = Defaults.Offset; - Scale = Defaults.Scale; - } - else - { - Offset = offset; - Scale = scale; - } - Contracts.CheckParam(FloatUtils.IsFinite(Offset), nameof(offset)); - Contracts.CheckParam(FloatUtils.IsFiniteNonZero(Scale), nameof(scale)); - } - - internal ColumnInfo(string name, string inputColumnName, ModelLoadContext ctx) - { - Contracts.AssertNonEmpty(name); - Contracts.AssertNonEmpty(inputColumnName); - Contracts.AssertValue(ctx); - - Name = name; - InputColumnName = inputColumnName; - - // *** Binary format *** - // byte: colors - // byte: convert - // Float: offset - // Float: scale - // byte: separateChannels - Colors = (ColorBits)ctx.Reader.ReadByte(); - Contracts.CheckDecode(Colors != 0); - Contracts.CheckDecode((Colors & ColorBits.All) == Colors); - - // Count the planes. - int planes = (int)Colors; - planes = (planes & 0x05) + ((planes >> 1) & 0x05); - planes = (planes & 0x03) + ((planes >> 2) & 0x03); - Planes = (byte)planes; - Contracts.Assert(0 < Planes & Planes <= 4); - - AsFloat = ctx.Reader.ReadBoolByte(); - Offset = ctx.Reader.ReadFloat(); - Contracts.CheckDecode(FloatUtils.IsFinite(Offset)); - Scale = ctx.Reader.ReadFloat(); - Contracts.CheckDecode(FloatUtils.IsFiniteNonZero(Scale)); - Contracts.CheckDecode(AsFloat || Offset == 0 && Scale == 1); - Interleave = ctx.Reader.ReadBoolByte(); - } - - public void Save(ModelSaveContext ctx) - { - Contracts.AssertValue(ctx); -#if DEBUG - // This code is used in deserialization - assert that it matches what we computed above. - int planes = (int)Colors; - planes = (planes & 0x05) + ((planes >> 1) & 0x05); - planes = (planes & 0x03) + ((planes >> 2) & 0x03); - Contracts.Assert(planes == Planes); -#endif - - // *** Binary format *** - // byte: colors - // byte: convert - // Float: offset - // Float: scale - // byte: separateChannels - Contracts.Assert(Colors != 0); - Contracts.Assert((Colors & ColorBits.All) == Colors); - ctx.Writer.Write((byte)Colors); - ctx.Writer.WriteBoolByte(AsFloat); - Contracts.Assert(FloatUtils.IsFinite(Offset)); - ctx.Writer.Write(Offset); - Contracts.Assert(FloatUtils.IsFiniteNonZero(Scale)); - Contracts.Assert(AsFloat || Offset == 0 && Scale == 1); - ctx.Writer.Write(Scale); - ctx.Writer.WriteBoolByte(Interleave); - } - } - internal const string Summary = "Extract color plane(s) from an image. Options include scaling, offset and conversion to floating point."; internal const string UserName = "Image Pixel Extractor Transform"; internal const string LoaderSignature = "ImagePixelExtractor"; @@ -316,14 +147,17 @@ private static VersionInfo GetVersionInfo() verReadableCur: 0x00010002, verWeCanReadBack: 0x00010002, loaderSignature: LoaderSignature, - loaderAssemblyName: typeof(ImagePixelExtractorTransformer).Assembly.FullName); + loaderAssemblyName: typeof(ImagePixelExtractingTransformer).Assembly.FullName); } private const string RegistrationName = "ImagePixelExtractor"; - private readonly ColumnInfo[] _columns; + private readonly ImagePixelExtractingEstimator.ColumnInfo[] _columns; - public IReadOnlyCollection Columns => _columns.AsReadOnly(); + /// + /// The columns passed to this . + /// + public IReadOnlyCollection Columns => _columns.AsReadOnly(); /// /// Extract pixels values from image and produce array of values. @@ -336,15 +170,15 @@ private static VersionInfo GetVersionInfo() /// Scale color pixel value by this amount. /// Offset color pixel value by this amount. /// Output array as float array. If false, output as byte array. - public ImagePixelExtractorTransformer(IHostEnvironment env, + internal ImagePixelExtractingTransformer(IHostEnvironment env, string outputColumnName, string inputColumnName = null, - ColorBits colors = ColorBits.Rgb, + ImagePixelExtractingEstimator.ColorBits colors = ImagePixelExtractingEstimator.ColorBits.Rgb, bool interleave = Defaults.Interleave, float scale = Defaults.Scale, float offset = Defaults.Offset, bool asFloat = Defaults.Convert) - : this(env, new ColumnInfo(outputColumnName, inputColumnName, colors, interleave, scale, offset, asFloat)) + : this(env, new ImagePixelExtractingEstimator.ColumnInfo(outputColumnName, inputColumnName, colors, interleave, scale, offset, asFloat)) { } @@ -353,20 +187,20 @@ public ImagePixelExtractorTransformer(IHostEnvironment env, /// /// The host environment. /// Describes the parameters of pixel extraction for each column pair. - public ImagePixelExtractorTransformer(IHostEnvironment env, params ColumnInfo[] columns) + internal ImagePixelExtractingTransformer(IHostEnvironment env, params ImagePixelExtractingEstimator.ColumnInfo[] columns) : base(Contracts.CheckRef(env, nameof(env)).Register(RegistrationName), GetColumnPairs(columns)) { _columns = columns.ToArray(); } - private static (string outputColumnName, string inputColumnName)[] GetColumnPairs(ColumnInfo[] columns) + private static (string outputColumnName, string inputColumnName)[] GetColumnPairs(ImagePixelExtractingEstimator.ColumnInfo[] columns) { Contracts.CheckValue(columns, nameof(columns)); return columns.Select(x => (x.Name, x.InputColumnName)).ToArray(); } // Factory method for SignatureDataTransform. - internal static IDataTransform Create(IHostEnvironment env, Arguments args, IDataView input) + internal static IDataTransform Create(IHostEnvironment env, Options args, IDataView input) { Contracts.CheckValue(env, nameof(env)); env.CheckValue(args, nameof(args)); @@ -374,29 +208,29 @@ internal static IDataTransform Create(IHostEnvironment env, Arguments args, IDat env.CheckValue(args.Columns, nameof(args.Columns)); - var columns = new ColumnInfo[args.Columns.Length]; + var columns = new ImagePixelExtractingEstimator.ColumnInfo[args.Columns.Length]; for (int i = 0; i < columns.Length; i++) { var item = args.Columns[i]; - columns[i] = new ColumnInfo(item, args); + columns[i] = new ImagePixelExtractingEstimator.ColumnInfo(item, args); } - var transformer = new ImagePixelExtractorTransformer(env, columns); + var transformer = new ImagePixelExtractingTransformer(env, columns); return new RowToRowMapperTransform(env, input, transformer.MakeRowMapper(input.Schema), transformer.MakeRowMapper); } // Factory method for SignatureLoadModel. - private static ImagePixelExtractorTransformer Create(IHostEnvironment env, ModelLoadContext ctx) + private static ImagePixelExtractingTransformer Create(IHostEnvironment env, ModelLoadContext ctx) { Contracts.CheckValue(env, nameof(env)); var host = env.Register(RegistrationName); host.CheckValue(ctx, nameof(ctx)); ctx.CheckAtModel(GetVersionInfo()); - return new ImagePixelExtractorTransformer(host, ctx); + return new ImagePixelExtractingTransformer(host, ctx); } - private ImagePixelExtractorTransformer(IHost host, ModelLoadContext ctx) + private ImagePixelExtractingTransformer(IHost host, ModelLoadContext ctx) : base(host, ctx) { // *** Binary format *** @@ -405,9 +239,9 @@ private ImagePixelExtractorTransformer(IHost host, ModelLoadContext ctx) // for each added column // ColumnInfo - _columns = new ColumnInfo[ColumnPairs.Length]; + _columns = new ImagePixelExtractingEstimator.ColumnInfo[ColumnPairs.Length]; for (int i = 0; i < _columns.Length; i++) - _columns[i] = new ColumnInfo(ColumnPairs[i].outputColumnName, ColumnPairs[i].inputColumnName, ctx); + _columns[i] = new ImagePixelExtractingEstimator.ColumnInfo(ColumnPairs[i].outputColumnName, ColumnPairs[i].inputColumnName, ctx); } // Factory method for SignatureLoadDataTransform. @@ -433,7 +267,7 @@ public override void Save(ModelSaveContext ctx) base.SaveColumns(ctx); - foreach (ColumnInfo info in _columns) + foreach (var info in _columns) info.Save(ctx); } @@ -453,10 +287,10 @@ protected override void CheckInputColumn(Schema inputSchema, int col, int srcCol private sealed class Mapper : OneToOneMapperBase { - private readonly ImagePixelExtractorTransformer _parent; + private readonly ImagePixelExtractingTransformer _parent; private readonly VectorType[] _types; - public Mapper(ImagePixelExtractorTransformer parent, Schema inputSchema) + public Mapper(ImagePixelExtractingTransformer parent, Schema inputSchema) : base(parent.Host.Register(nameof(Mapper)), parent, inputSchema) { _parent = parent; @@ -657,10 +491,210 @@ private VectorType[] ConstructTypes() } /// - /// Estimator which extract pixel values out of image and produce array of values. + /// that extracts the pixels of the image into a vector. + /// This vector can further be used as a feature to the algorithms. /// - public sealed class ImagePixelExtractingEstimator : TrivialEstimator + /// + /// Calling in this estimator, produces an . + /// + /// + /// + /// + public sealed class ImagePixelExtractingEstimator : TrivialEstimator { + /// + /// Which color channels are extracted. Note that these values are serialized so should not be modified. + /// + [Flags] + public enum ColorBits : byte + { + Alpha = 0x01, + Red = 0x02, + Green = 0x04, + Blue = 0x08, + + Rgb = Red | Green | Blue, + All = Alpha | Red | Green | Blue + } + + /// + /// Describes how the transformer handles one image pixel extraction column pair. + /// + public sealed class ColumnInfo + { + /// Name of the column resulting from the transformation of . + public readonly string Name; + + /// Name of column to transform. + public readonly string InputColumnName; + + /// What colors to extract. + public readonly ColorBits Colors; + + /// Offset color pixel value by this amount. + public readonly float Offset; + + /// Scale color pixel value by this amount. + public readonly float Scale; + + /// Whether to interleave the pixels, meaning keep them in the `ARGB ARGB` order, or leave them separated in the plannar form. + public readonly bool Interleave; + + /// Output the array as float array. If false, output as byte array. + public readonly bool AsFloat; + + internal readonly byte Planes; + internal bool Alpha => (Colors & ColorBits.Alpha) != 0; + + internal bool Red => (Colors & ColorBits.Red) != 0; + internal bool Green => (Colors & ColorBits.Green) != 0; + internal bool Blue => (Colors & ColorBits.Blue) != 0; + + internal ColumnInfo(ImagePixelExtractingTransformer.Column item, ImagePixelExtractingTransformer.Options args) + { + Contracts.CheckValue(item, nameof(item)); + Contracts.CheckValue(args, nameof(args)); + + Name = item.Name; + InputColumnName = item.Source ?? item.Name; + + if (item.UseAlpha ?? args.UseAlpha) { Colors |= ColorBits.Alpha; Planes++; } + if (item.UseRed ?? args.UseRed) { Colors |= ColorBits.Red; Planes++; } + if (item.UseGreen ?? args.UseGreen) { Colors |= ColorBits.Green; Planes++; } + if (item.UseBlue ?? args.UseBlue) { Colors |= ColorBits.Blue; Planes++; } + Contracts.CheckUserArg(Planes > 0, nameof(item.UseRed), "Need to use at least one color plane"); + + Interleave = item.InterleaveArgb ?? args.InterleaveArgb; + + AsFloat = item.Convert ?? args.Convert; + if (!AsFloat) + { + Offset = ImagePixelExtractingTransformer.Defaults.Offset; + Scale = ImagePixelExtractingTransformer.Defaults.Scale; + } + else + { + Offset = item.Offset ?? args.Offset ?? ImagePixelExtractingTransformer.Defaults.Offset; + Scale = item.Scale ?? args.Scale ?? ImagePixelExtractingTransformer.Defaults.Scale; + Contracts.CheckUserArg(FloatUtils.IsFinite(Offset), nameof(item.Offset)); + Contracts.CheckUserArg(FloatUtils.IsFiniteNonZero(Scale), nameof(item.Scale)); + } + } + + /// + /// Describes how the transformer handles one input-output column pair. + /// + /// Name of the column resulting from the transformation of . + /// Name of column to transform. If set to , the value of the will be used as source. + /// What colors to extract. + /// Whether to interleave the pixels, meaning keep them in the `ARGB ARGB` order, or leave them in the plannar form: of all red pixels, + /// then all green, then all blue. + /// Scale color pixel value by this amount. + /// Offset color pixel value by this amount. + /// Output array as float array. If false, output as byte array. + + public ColumnInfo(string name, + string inputColumnName = null, + ColorBits colors = ImagePixelExtractingTransformer.Defaults.Colors, + bool interleave = ImagePixelExtractingTransformer.Defaults.Interleave, + float scale = ImagePixelExtractingTransformer.Defaults.Scale, + float offset = ImagePixelExtractingTransformer.Defaults.Offset, + bool asFloat = ImagePixelExtractingTransformer.Defaults.Convert) + { + Contracts.CheckNonWhiteSpace(name, nameof(name)); + + Name = name; + InputColumnName = inputColumnName ?? name; + Colors = colors; + + if ((Colors & ColorBits.Alpha) == ColorBits.Alpha) Planes++; + if ((Colors & ColorBits.Red) == ColorBits.Red) Planes++; + if ((Colors & ColorBits.Green) == ColorBits.Green) Planes++; + if ((Colors & ColorBits.Blue) == ColorBits.Blue) Planes++; + Contracts.CheckParam(Planes > 0, nameof(colors), "Need to use at least one color plane"); + + Interleave = interleave; + + AsFloat = asFloat; + if (!AsFloat) + { + Offset = ImagePixelExtractingTransformer.Defaults.Offset; + Scale = ImagePixelExtractingTransformer.Defaults.Scale; + } + else + { + Offset = offset; + Scale = scale; + } + Contracts.CheckParam(FloatUtils.IsFinite(Offset), nameof(offset)); + Contracts.CheckParam(FloatUtils.IsFiniteNonZero(Scale), nameof(scale)); + } + + internal ColumnInfo(string name, string inputColumnName, ModelLoadContext ctx) + { + Contracts.AssertNonEmpty(name); + Contracts.AssertNonEmpty(inputColumnName); + Contracts.AssertValue(ctx); + + Name = name; + InputColumnName = inputColumnName; + + // *** Binary format *** + // byte: colors + // byte: convert + // Float: offset + // Float: scale + // byte: separateChannels + Colors = (ImagePixelExtractingEstimator.ColorBits)ctx.Reader.ReadByte(); + Contracts.CheckDecode(Colors != 0); + Contracts.CheckDecode((Colors & ImagePixelExtractingEstimator.ColorBits.All) == Colors); + + // Count the planes. + int planes = (int)Colors; + planes = (planes & 0x05) + ((planes >> 1) & 0x05); + planes = (planes & 0x03) + ((planes >> 2) & 0x03); + Planes = (byte)planes; + Contracts.Assert(0 < Planes & Planes <= 4); + + AsFloat = ctx.Reader.ReadBoolByte(); + Offset = ctx.Reader.ReadFloat(); + Contracts.CheckDecode(FloatUtils.IsFinite(Offset)); + Scale = ctx.Reader.ReadFloat(); + Contracts.CheckDecode(FloatUtils.IsFiniteNonZero(Scale)); + Contracts.CheckDecode(AsFloat || Offset == 0 && Scale == 1); + Interleave = ctx.Reader.ReadBoolByte(); + } + + internal void Save(ModelSaveContext ctx) + { + Contracts.AssertValue(ctx); +#if DEBUG + // This code is used in deserialization - assert that it matches what we computed above. + int planes = (int)Colors; + planes = (planes & 0x05) + ((planes >> 1) & 0x05); + planes = (planes & 0x03) + ((planes >> 2) & 0x03); + Contracts.Assert(planes == Planes); +#endif + + // *** Binary format *** + // byte: colors + // byte: convert + // Float: offset + // Float: scale + // byte: separateChannels + Contracts.Assert(Colors != 0); + Contracts.Assert((Colors & ImagePixelExtractingEstimator.ColorBits.All) == Colors); + ctx.Writer.Write((byte)Colors); + ctx.Writer.WriteBoolByte(AsFloat); + Contracts.Assert(FloatUtils.IsFinite(Offset)); + ctx.Writer.Write(Offset); + Contracts.Assert(FloatUtils.IsFiniteNonZero(Scale)); + Contracts.Assert(AsFloat || Offset == 0 && Scale == 1); + ctx.Writer.Write(Scale); + ctx.Writer.WriteBoolByte(Interleave); + } + } + /// /// Extract pixels values from image and produce array of values. /// @@ -668,17 +702,19 @@ public sealed class ImagePixelExtractingEstimator : TrivialEstimatorName of the column resulting from the transformation of . Null means is replaced. /// Name of the input column. /// What colors to extract. - /// + /// Whether to interleave the pixels, meaning keep them in the `RGB RGB` order, or leave them in the plannar form: of all red pixels, + /// than all green, than all blue. /// Scale color pixel value by this amount. /// Offset color pixel value by this amount. /// Output array as float array. If false, output as byte array. - public ImagePixelExtractingEstimator(IHostEnvironment env, + [BestFriend] + internal ImagePixelExtractingEstimator(IHostEnvironment env, string outputColumnName, string inputColumnName = null, - ImagePixelExtractorTransformer.ColorBits colors = ImagePixelExtractorTransformer.Defaults.Colors, - bool interleave = ImagePixelExtractorTransformer.Defaults.Interleave, float scale = ImagePixelExtractorTransformer.Defaults.Scale, - float offset = ImagePixelExtractorTransformer.Defaults.Offset, bool asFloat = ImagePixelExtractorTransformer.Defaults.Convert) - : base(Contracts.CheckRef(env, nameof(env)).Register(nameof(ImagePixelExtractingEstimator)), new ImagePixelExtractorTransformer(env, outputColumnName, inputColumnName, colors, interleave)) + ColorBits colors = ImagePixelExtractingTransformer.Defaults.Colors, + bool interleave = ImagePixelExtractingTransformer.Defaults.Interleave, float scale = ImagePixelExtractingTransformer.Defaults.Scale, + float offset = ImagePixelExtractingTransformer.Defaults.Offset, bool asFloat = ImagePixelExtractingTransformer.Defaults.Convert) + : base(Contracts.CheckRef(env, nameof(env)).Register(nameof(ImagePixelExtractingEstimator)), new ImagePixelExtractingTransformer(env, outputColumnName, inputColumnName, colors, interleave, scale, offset, asFloat)) { } @@ -687,11 +723,15 @@ public ImagePixelExtractingEstimator(IHostEnvironment env, /// /// The host environment. /// Describes the parameters of pixel extraction for each column pair. - public ImagePixelExtractingEstimator(IHostEnvironment env, params ImagePixelExtractorTransformer.ColumnInfo[] columns) - : base(Contracts.CheckRef(env, nameof(env)).Register(nameof(ImagePixelExtractingEstimator)), new ImagePixelExtractorTransformer(env, columns)) + internal ImagePixelExtractingEstimator(IHostEnvironment env, params ColumnInfo[] columns) + : base(Contracts.CheckRef(env, nameof(env)).Register(nameof(ImagePixelExtractingEstimator)), new ImagePixelExtractingTransformer(env, columns)) { } + /// + /// Returns the of the schema which will be produced by the transformer. + /// Used for schema propagation and verification in a pipeline. + /// public override SchemaShape GetOutputSchema(SchemaShape inputSchema) { Host.CheckValue(inputSchema, nameof(inputSchema)); diff --git a/src/Microsoft.ML.ImageAnalytics/ImageResizerTransform.cs b/src/Microsoft.ML.ImageAnalytics/ImageResizer.cs similarity index 67% rename from src/Microsoft.ML.ImageAnalytics/ImageResizerTransform.cs rename to src/Microsoft.ML.ImageAnalytics/ImageResizer.cs index 423991daad..665cfd516d 100644 --- a/src/Microsoft.ML.ImageAnalytics/ImageResizerTransform.cs +++ b/src/Microsoft.ML.ImageAnalytics/ImageResizer.cs @@ -18,57 +18,34 @@ using Microsoft.ML.Internal.Utilities; using Microsoft.ML.Model; -[assembly: LoadableClass(ImageResizerTransformer.Summary, typeof(IDataTransform), typeof(ImageResizerTransformer), typeof(ImageResizerTransformer.Arguments), - typeof(SignatureDataTransform), ImageResizerTransformer.UserName, "ImageResizerTransform", "ImageResizer")] +[assembly: LoadableClass(ImageResizingTransformer.Summary, typeof(IDataTransform), typeof(ImageResizingTransformer), typeof(ImageResizingTransformer.Arguments), + typeof(SignatureDataTransform), ImageResizingTransformer.UserName, "ImageResizerTransform", "ImageResizer")] -[assembly: LoadableClass(ImageResizerTransformer.Summary, typeof(IDataTransform), typeof(ImageResizerTransformer), null, typeof(SignatureLoadDataTransform), - ImageResizerTransformer.UserName, ImageResizerTransformer.LoaderSignature)] +[assembly: LoadableClass(ImageResizingTransformer.Summary, typeof(IDataTransform), typeof(ImageResizingTransformer), null, typeof(SignatureLoadDataTransform), + ImageResizingTransformer.UserName, ImageResizingTransformer.LoaderSignature)] -[assembly: LoadableClass(typeof(ImageResizerTransformer), null, typeof(SignatureLoadModel), - ImageResizerTransformer.UserName, ImageResizerTransformer.LoaderSignature)] +[assembly: LoadableClass(typeof(ImageResizingTransformer), null, typeof(SignatureLoadModel), + ImageResizingTransformer.UserName, ImageResizingTransformer.LoaderSignature)] -[assembly: LoadableClass(typeof(IRowMapper), typeof(ImageResizerTransformer), null, typeof(SignatureLoadRowMapper), - ImageResizerTransformer.UserName, ImageResizerTransformer.LoaderSignature)] +[assembly: LoadableClass(typeof(IRowMapper), typeof(ImageResizingTransformer), null, typeof(SignatureLoadRowMapper), + ImageResizingTransformer.UserName, ImageResizingTransformer.LoaderSignature)] namespace Microsoft.ML.ImageAnalytics { // REVIEW: Rewrite as LambdaTransform to simplify. /// - /// Transform which takes one or many columns of and resize them to provided height and width. + /// produced by fitting the to an . /// - public sealed class ImageResizerTransformer : OneToOneTransformerBase + /// + /// Calling resizes the images to a new height and width. + /// + /// + /// + /// + public sealed class ImageResizingTransformer : OneToOneTransformerBase { - public enum ResizingKind : byte - { - /// - /// Isotropic with padding. - /// - [TGUI(Label = "Isotropic with Padding")] - IsoPad = 0, - - /// - /// Isotropic with cropping. - /// - [TGUI(Label = "Isotropic with Cropping")] - IsoCrop = 1, - - /// - /// Ignore aspect ratio and squeeze/stretch into target dimensions. - /// - [TGUI(Label = "Ignore aspect ratio and squeeze/stretch into target dimensions")] - Fill = 2 - } - public enum Anchor : byte - { - Right = 0, - Left = 1, - Top = 2, - Bottom = 3, - Center = 4 - } - - public sealed class Column : OneToOneColumn + internal sealed class Column : OneToOneColumn { [Argument(ArgumentType.AtMostOnce, HelpText = "Width of the resized image", ShortName = "width")] public int? ImageWidth; @@ -77,10 +54,10 @@ public sealed class Column : OneToOneColumn public int? ImageHeight; [Argument(ArgumentType.AtMostOnce, HelpText = "Resizing method", ShortName = "scale")] - public ResizingKind? Resizing; + public ImageResizingEstimator.ResizingKind? Resizing; [Argument(ArgumentType.AtMostOnce, HelpText = "Anchor for cropping", ShortName = "anchor")] - public Anchor? CropAnchor; + public ImageResizingEstimator.Anchor? CropAnchor; internal static Column Parse(string str) { @@ -101,7 +78,7 @@ internal bool TryUnparse(StringBuilder sb) } } - public class Arguments : TransformInputBase + internal class Arguments : TransformInputBase { [Argument(ArgumentType.Multiple | ArgumentType.Required, HelpText = "New column definition(s) (optional form: name:src)", Name = "Column", ShortName = "col", SortOrder = 1)] public Column[] Columns; @@ -113,57 +90,15 @@ public class Arguments : TransformInputBase public int ImageHeight; [Argument(ArgumentType.AtMostOnce, HelpText = "Resizing method", ShortName = "scale")] - public ResizingKind Resizing = ResizingKind.IsoCrop; + public ImageResizingEstimator.ResizingKind Resizing = ImageResizingEstimator.ResizingKind.IsoCrop; [Argument(ArgumentType.AtMostOnce, HelpText = "Anchor for cropping", ShortName = "anchor")] - public Anchor CropAnchor = Anchor.Center; + public ImageResizingEstimator.Anchor CropAnchor = ImageResizingEstimator.Anchor.Center; } internal static class Defaults { - public const ResizingKind Resizing = ResizingKind.IsoCrop; - public const Anchor CropAnchor = Anchor.Center; - } - - /// - /// Describes how the transformer handles one image resize column pair. - /// - public sealed class ColumnInfo - { - public readonly string Name; - public readonly string InputColumnName; - - public readonly int Width; - public readonly int Height; - public readonly ResizingKind Resizing; - public readonly Anchor Anchor; - public readonly ColumnType Type; - - /// - /// Describes how the transformer handles one image resize column pair. - /// - /// Name of the column resulting from the transformation of . - /// Width of resized image. - /// Height of resized image. - /// Name of column to transform. If set to , the value of the will be used as source. - /// What to use. - /// If set to what anchor to use for cropping. - public ColumnInfo(string name, int width, int height, string inputColumnName = null, ResizingKind resizing = Defaults.Resizing, Anchor anchor = Defaults.CropAnchor) - { - Contracts.CheckNonEmpty(name, nameof(name)); - Contracts.CheckNonEmpty(inputColumnName, nameof(inputColumnName)); - Contracts.CheckUserArg(width > 0, nameof(Column.ImageWidth)); - Contracts.CheckUserArg(height > 0, nameof(Column.ImageHeight)); - Contracts.CheckUserArg(Enum.IsDefined(typeof(ResizingKind), resizing), nameof(Column.Resizing)); - Contracts.CheckUserArg(Enum.IsDefined(typeof(Anchor), anchor), nameof(Column.CropAnchor)); - - Name = name; - InputColumnName = inputColumnName; - Width = width; - Height = height; - Resizing = resizing; - Anchor = anchor; - Type = new ImageType(Height, Width); - } + public const ImageResizingEstimator.ResizingKind Resizing = ImageResizingEstimator.ResizingKind.IsoCrop; + public const ImageResizingEstimator.Anchor CropAnchor = ImageResizingEstimator.Anchor.Center; } internal const string Summary = "Scales an image to specified dimensions using one of the three scale types: isotropic with padding, " @@ -181,14 +116,17 @@ private static VersionInfo GetVersionInfo() verReadableCur: 0x00010003, verWeCanReadBack: 0x00010003, loaderSignature: LoaderSignature, - loaderAssemblyName: typeof(ImageResizerTransformer).Assembly.FullName); + loaderAssemblyName: typeof(ImageResizingTransformer).Assembly.FullName); } private const string RegistrationName = "ImageScaler"; - private readonly ColumnInfo[] _columns; + private readonly ImageResizingEstimator.ColumnInfo[] _columns; - public IReadOnlyCollection Columns => _columns.AsReadOnly(); + /// + /// The columns passed to this . + /// + public IReadOnlyCollection Columns => _columns.AsReadOnly(); /// /// Resize image. @@ -198,11 +136,13 @@ private static VersionInfo GetVersionInfo() /// Width of resized image. /// Height of resized image. /// Name of the input column. - /// What to use. - /// If set to what anchor to use for cropping. - public ImageResizerTransformer(IHostEnvironment env, string outputColumnName, - int imageWidth, int imageHeight, string inputColumnName = null, ResizingKind resizing = ResizingKind.IsoCrop, Anchor cropAnchor = Anchor.Center) - : this(env, new ColumnInfo(outputColumnName, imageWidth, imageHeight, inputColumnName, resizing, cropAnchor)) + /// What to use. + /// If set to what anchor to use for cropping. + internal ImageResizingTransformer(IHostEnvironment env, string outputColumnName, + int imageWidth, int imageHeight, string inputColumnName = null, + ImageResizingEstimator.ResizingKind resizing = ImageResizingEstimator.ResizingKind.IsoCrop, + ImageResizingEstimator.Anchor cropAnchor = ImageResizingEstimator.Anchor.Center) + : this(env, new ImageResizingEstimator.ColumnInfo(outputColumnName, imageWidth, imageHeight, inputColumnName, resizing, cropAnchor)) { } @@ -211,13 +151,13 @@ public ImageResizerTransformer(IHostEnvironment env, string outputColumnName, /// /// The host environment. /// Describes the parameters of image resizing for each column pair. - public ImageResizerTransformer(IHostEnvironment env, params ColumnInfo[] columns) + internal ImageResizingTransformer(IHostEnvironment env, params ImageResizingEstimator.ColumnInfo[] columns) : base(Contracts.CheckRef(env, nameof(env)).Register(RegistrationName), GetColumnPairs(columns)) { _columns = columns.ToArray(); } - private static (string outputColumnName, string inputColumnName)[] GetColumnPairs(ColumnInfo[] columns) + private static (string outputColumnName, string inputColumnName)[] GetColumnPairs(ImageResizingEstimator.ColumnInfo[] columns) { Contracts.CheckValue(columns, nameof(columns)); return columns.Select(x => (x.Name, x.InputColumnName)).ToArray(); @@ -232,11 +172,11 @@ internal static IDataTransform Create(IHostEnvironment env, Arguments args, IDat env.CheckValue(args.Columns, nameof(args.Columns)); - var cols = new ColumnInfo[args.Columns.Length]; + var cols = new ImageResizingEstimator.ColumnInfo[args.Columns.Length]; for (int i = 0; i < cols.Length; i++) { var item = args.Columns[i]; - cols[i] = new ColumnInfo( + cols[i] = new ImageResizingEstimator.ColumnInfo( item.Name, item.ImageWidth ?? args.ImageWidth, item.ImageHeight ?? args.ImageHeight, @@ -245,11 +185,11 @@ internal static IDataTransform Create(IHostEnvironment env, Arguments args, IDat item.CropAnchor ?? args.CropAnchor); } - return new ImageResizerTransformer(env, cols).MakeDataTransform(input); + return new ImageResizingTransformer(env, cols).MakeDataTransform(input); } // Factory method for SignatureLoadModel. - private static ImageResizerTransformer Create(IHostEnvironment env, ModelLoadContext ctx) + private static ImageResizingTransformer Create(IHostEnvironment env, ModelLoadContext ctx) { Contracts.CheckValue(env, nameof(env)); var host = env.Register(RegistrationName); @@ -257,10 +197,10 @@ private static ImageResizerTransformer Create(IHostEnvironment env, ModelLoadCon host.CheckValue(ctx, nameof(ctx)); ctx.CheckAtModel(GetVersionInfo()); - return new ImageResizerTransformer(host, ctx); + return new ImageResizingTransformer(host, ctx); } - private ImageResizerTransformer(IHost host, ModelLoadContext ctx) + private ImageResizingTransformer(IHost host, ModelLoadContext ctx) : base(host, ctx) { // *** Binary format *** @@ -272,18 +212,18 @@ private ImageResizerTransformer(IHost host, ModelLoadContext ctx) // byte: scaling kind // byte: anchor - _columns = new ColumnInfo[ColumnPairs.Length]; + _columns = new ImageResizingEstimator.ColumnInfo[ColumnPairs.Length]; for (int i = 0; i < ColumnPairs.Length; i++) { int width = ctx.Reader.ReadInt32(); Host.CheckDecode(width > 0); int height = ctx.Reader.ReadInt32(); Host.CheckDecode(height > 0); - var scale = (ResizingKind)ctx.Reader.ReadByte(); - Host.CheckDecode(Enum.IsDefined(typeof(ResizingKind), scale)); - var anchor = (Anchor)ctx.Reader.ReadByte(); - Host.CheckDecode(Enum.IsDefined(typeof(Anchor), anchor)); - _columns[i] = new ColumnInfo(ColumnPairs[i].outputColumnName, width, height, ColumnPairs[i].inputColumnName, scale, anchor); + var scale = (ImageResizingEstimator.ResizingKind)ctx.Reader.ReadByte(); + Host.CheckDecode(Enum.IsDefined(typeof(ImageResizingEstimator.ResizingKind), scale)); + var anchor = (ImageResizingEstimator.Anchor)ctx.Reader.ReadByte(); + Host.CheckDecode(Enum.IsDefined(typeof(ImageResizingEstimator.Anchor), anchor)); + _columns[i] = new ImageResizingEstimator.ColumnInfo(ColumnPairs[i].outputColumnName, width, height, ColumnPairs[i].inputColumnName, scale, anchor); } } @@ -317,9 +257,9 @@ public override void Save(ModelSaveContext ctx) { ctx.Writer.Write(col.Width); ctx.Writer.Write(col.Height); - Contracts.Assert((ResizingKind)(byte)col.Resizing == col.Resizing); + Contracts.Assert((ImageResizingEstimator.ResizingKind)(byte)col.Resizing == col.Resizing); ctx.Writer.Write((byte)col.Resizing); - Contracts.Assert((Anchor)(byte)col.Anchor == col.Anchor); + Contracts.Assert((ImageResizingEstimator.Anchor)(byte)col.Anchor == col.Anchor); ctx.Writer.Write((byte)col.Anchor); } } @@ -334,9 +274,9 @@ protected override void CheckInputColumn(Schema inputSchema, int col, int srcCol private sealed class Mapper : OneToOneMapperBase { - private readonly ImageResizerTransformer _parent; + private readonly ImageResizingTransformer _parent; - public Mapper(ImageResizerTransformer parent, Schema inputSchema) + public Mapper(ImageResizingTransformer parent, Schema inputSchema) : base(parent.Host.Register(nameof(Mapper)), parent, inputSchema) { _parent = parent; @@ -394,7 +334,7 @@ protected override Delegate MakeGetter(Row input, int iinfo, Func act widthAspect = (float)info.Width / sourceWidth; heightAspect = (float)info.Height / sourceHeight; - if (info.Resizing == ResizingKind.IsoPad) + if (info.Resizing == ImageResizingEstimator.ResizingKind.IsoPad) { widthAspect = (float)info.Width / sourceWidth; heightAspect = (float)info.Height / sourceHeight; @@ -412,17 +352,17 @@ protected override Delegate MakeGetter(Row input, int iinfo, Func act destWidth = (int)(sourceWidth * aspect); destHeight = (int)(sourceHeight * aspect); } - else if (info.Resizing == ResizingKind.IsoCrop) + else if (info.Resizing == ImageResizingEstimator.ResizingKind.IsoCrop) { if (heightAspect < widthAspect) { aspect = widthAspect; switch (info.Anchor) { - case Anchor.Top: + case ImageResizingEstimator.Anchor.Top: destY = 0; break; - case Anchor.Bottom: + case ImageResizingEstimator.Anchor.Bottom: destY = (int)(info.Height - (sourceHeight * aspect)); break; default: @@ -435,10 +375,10 @@ protected override Delegate MakeGetter(Row input, int iinfo, Func act aspect = heightAspect; switch (info.Anchor) { - case Anchor.Left: + case ImageResizingEstimator.Anchor.Left: destX = 0; break; - case Anchor.Right: + case ImageResizingEstimator.Anchor.Right: destX = (int)(info.Width - (sourceWidth * aspect)); break; default: @@ -450,7 +390,7 @@ protected override Delegate MakeGetter(Row input, int iinfo, Func act destWidth = (int)(sourceWidth * aspect); destHeight = (int)(sourceHeight * aspect); } - else if (info.Resizing == ResizingKind.Fill) + else if (info.Resizing == ImageResizingEstimator.ResizingKind.Fill) { destWidth = info.Width; destHeight = info.Height; @@ -472,10 +412,111 @@ protected override Delegate MakeGetter(Row input, int iinfo, Func act } /// - /// Estimator which resizes images. + /// that resizes the image to a new width and height. /// - public sealed class ImageResizingEstimator : TrivialEstimator + /// + /// Calling in this estimator, produces an . + /// + /// + /// + /// + public sealed class ImageResizingEstimator : TrivialEstimator { + /// + /// Specifies how to resize the images: by croping them or padding in the direction needed to fill up. + /// + public enum ResizingKind : byte + { + /// + /// Isotropic(uniform) with padding. + /// + [TGUI(Label = "Isotropic with Padding")] + IsoPad = 0, + + /// + /// Isotropic(uniform) with cropping. + /// + [TGUI(Label = "Isotropic with Cropping")] + IsoCrop = 1, + + /// + /// Ignore aspect ratio and squeeze/stretch into target dimensions. + /// + [TGUI(Label = "Ignore aspect ratio and squeeze/stretch into target dimensions")] + Fill = 2 + } + + /// + /// Indicates where to anchor for image cropping, for example set to is going to crop the image on all sides, + /// set to is going to crop the image at the top. + /// + public enum Anchor : byte + { + Right = 0, + Left = 1, + Top = 2, + Bottom = 3, + Center = 4 + } + + /// + /// Describes how the transformer handles one image resize column. + /// + public sealed class ColumnInfo + { + /// Name of the column resulting from the transformation of + public readonly string Name; + + /// Name of column to transform. + public readonly string InputColumnName; + + /// Width to resize the image to. + public readonly int Width; + + /// Height to resize the image to. + public readonly int Height; + + /// What to use (uniform, or non-uniform). + public readonly ResizingKind Resizing; + + /// If set to what anchor to use for cropping. + public readonly Anchor Anchor; + + /// The type of column, . + public readonly ColumnType Type; + + /// + /// Describes how the transformer handles one image resize column pair. + /// + /// Name of the column resulting from the transformation of . + /// Width of resized image. + /// Height of resized image. + /// Name of column to transform. If set to , the value of the will be used as source. + /// What to use. + /// If set to what anchor to use for cropping. + public ColumnInfo(string name, + int width, + int height, + string inputColumnName = null, + ResizingKind resizing = ImageResizingTransformer.Defaults.Resizing, + Anchor anchor = ImageResizingTransformer.Defaults.CropAnchor) + { + Contracts.CheckNonEmpty(name, nameof(name)); + Contracts.CheckUserArg(width > 0, nameof(width)); + Contracts.CheckUserArg(height > 0, nameof(height)); + Contracts.CheckUserArg(Enum.IsDefined(typeof(ResizingKind), resizing), nameof(resizing)); + Contracts.CheckUserArg(Enum.IsDefined(typeof(Anchor), anchor), nameof(anchor)); + + Name = name; + InputColumnName = inputColumnName ?? name; + Width = width; + Height = height; + Resizing = resizing; + Anchor = anchor; + Type = new ImageType(Height, Width); + } + } + /// /// Estimator which resizes images. /// @@ -484,16 +525,16 @@ public sealed class ImageResizingEstimator : TrivialEstimatorWidth of resized image. /// Height of resized image. /// Name of the input column. - /// What to use. - /// If set to what anchor to use for cropping. - public ImageResizingEstimator(IHostEnvironment env, + /// What to use. + /// If set to what anchor to use for cropping. + internal ImageResizingEstimator(IHostEnvironment env, string outputColumnName, int imageWidth, int imageHeight, string inputColumnName = null, - ImageResizerTransformer.ResizingKind resizing = ImageResizerTransformer.Defaults.Resizing, - ImageResizerTransformer.Anchor cropAnchor = ImageResizerTransformer.Defaults.CropAnchor) - : this(env, new ImageResizerTransformer(env, outputColumnName, imageWidth, imageHeight, inputColumnName, resizing, cropAnchor)) + ResizingKind resizing = ImageResizingTransformer.Defaults.Resizing, + Anchor cropAnchor = ImageResizingTransformer.Defaults.CropAnchor) + : this(env, new ImageResizingTransformer(env, outputColumnName, imageWidth, imageHeight, inputColumnName, resizing, cropAnchor)) { } @@ -502,16 +543,20 @@ public ImageResizingEstimator(IHostEnvironment env, /// /// The host environment. /// Describes the parameters of image resizing for each column pair. - public ImageResizingEstimator(IHostEnvironment env, params ImageResizerTransformer.ColumnInfo[] columns) - : this(env, new ImageResizerTransformer(env, columns)) + internal ImageResizingEstimator(IHostEnvironment env, params ColumnInfo[] columns) + : this(env, new ImageResizingTransformer(env, columns)) { } - private ImageResizingEstimator(IHostEnvironment env, ImageResizerTransformer transformer) + private ImageResizingEstimator(IHostEnvironment env, ImageResizingTransformer transformer) : base(Contracts.CheckRef(env, nameof(env)).Register(nameof(ImageResizingEstimator)), transformer) { } + /// + /// Returns the of the schema which will be produced by the transformer. + /// Used for schema propagation and verification in a pipeline. + /// public override SchemaShape GetOutputSchema(SchemaShape inputSchema) { Host.CheckValue(inputSchema, nameof(inputSchema)); diff --git a/src/Microsoft.ML.ImageAnalytics/Properties/AssemblyInfo.cs b/src/Microsoft.ML.ImageAnalytics/Properties/AssemblyInfo.cs index 443f2304db..02cc8e9483 100644 --- a/src/Microsoft.ML.ImageAnalytics/Properties/AssemblyInfo.cs +++ b/src/Microsoft.ML.ImageAnalytics/Properties/AssemblyInfo.cs @@ -6,5 +6,6 @@ using Microsoft.ML; [assembly: InternalsVisibleTo(assemblyName: "Microsoft.ML.StaticPipe" + PublicKey.Value)] +[assembly: InternalsVisibleTo(assemblyName: "Microsoft.ML.Tests" + PublicKey.TestValue)] [assembly: WantsToBeBestFriends] diff --git a/src/Microsoft.ML.ImageAnalytics/doc.xml b/src/Microsoft.ML.ImageAnalytics/doc.xml new file mode 100644 index 0000000000..6254c64363 --- /dev/null +++ b/src/Microsoft.ML.ImageAnalytics/doc.xml @@ -0,0 +1,62 @@ + + + + + + + Converts the images to grayscale. + + + + . + + For end-to-end image processing pipelines, and scenarios in your applications, see the + [examples in the machinelearning-samples github repository](https://github.com/dotnet/machinelearning-samples/tree/master/samples/csharp/getting-started). + ]]> + + + + + + + + Extracts the pixels from the input images and, converts them into a vector of numbers. This can be further used as feature by the algorithms added to the pipeline. + + + The ImagePixelExtractingEstimator extracts the pixels from the input images and, converts them into a vector of numbers. + This can be further used as feature by the algorithms added to the pipeline. + + ImagePixelExtractingEstimator expects a in the pipeline, before it is used. + For end-to-end image processing pipelines, and scenarios in your applications, see the + examples in the machinelearning-samples github repository. + + + + + + + + + Resizes the images to a new width and height. + + + In image processing pipelines, often machine learning practitioners make use of pre-trained DNN featurizers to + extract features for usage in the machine learning algorithms. + Those pre-trained models have a defined width and height for their input images, so often, after getting loaded, the images will need to get resized before + further processing. + + For end-to-end image processing pipelines, and scenarios in your applications, see the + examples in the machinelearning-samples github repository. + + + + + + + diff --git a/src/Microsoft.ML.SamplesUtils/SamplesDatasetUtils.cs b/src/Microsoft.ML.SamplesUtils/SamplesDatasetUtils.cs index 2c56b3ab40..3df23dff41 100644 --- a/src/Microsoft.ML.SamplesUtils/SamplesDatasetUtils.cs +++ b/src/Microsoft.ML.SamplesUtils/SamplesDatasetUtils.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Net; using Microsoft.ML.Data; @@ -35,6 +36,26 @@ public static string DownloadAdultDataset() public static string DownloadBreastCancerDataset() => Download("https://raw.githubusercontent.com/dotnet/machinelearning/76cb2cdf5cc8b6c88ca44b8969153836e589df04/test/data/breast-cancer.txt", "breast-cancer.txt"); + /// + /// Downloads 4 images, and a tsv file with their names from the dotnet/machinelearning repo. + /// + public static string DownloadImages() + { + string path = "images"; + + var dirInfo = Directory.CreateDirectory(path); + + string pathEscaped = $"{path}{Path.DirectorySeparatorChar}"; + + Download("https://raw.githubusercontent.com/dotnet/machinelearning/284e02cadf5342aa0c36f31d62fc6fa15bc06885/test/data/images/banana.jpg", $"{pathEscaped}banana.jpg"); + Download("https://raw.githubusercontent.com/dotnet/machinelearning/284e02cadf5342aa0c36f31d62fc6fa15bc06885/test/data/images/hotdog.jpg", $"{pathEscaped}hotdog.jpg"); + Download("https://raw.githubusercontent.com/dotnet/machinelearning/284e02cadf5342aa0c36f31d62fc6fa15bc06885/test/data/images/images.tsv", $"{pathEscaped}images.tsv"); + Download("https://raw.githubusercontent.com/dotnet/machinelearning/284e02cadf5342aa0c36f31d62fc6fa15bc06885/test/data/images/tomato.bmp", $"{pathEscaped}tomato.bmp"); + Download("https://raw.githubusercontent.com/dotnet/machinelearning/284e02cadf5342aa0c36f31d62fc6fa15bc06885/test/data/images/tomato.jpg", $"{pathEscaped}tomato.jpg"); + + return $"{path}{Path.DirectorySeparatorChar}images.tsv"; + } + private static string Download(string baseGitPath, string dataFile) { using (WebClient client = new WebClient()) diff --git a/src/Microsoft.ML.StaticPipe/ImageStaticPipe.cs b/src/Microsoft.ML.StaticPipe/ImageStaticPipe.cs index 12a3c97f46..962eccca11 100644 --- a/src/Microsoft.ML.StaticPipe/ImageStaticPipe.cs +++ b/src/Microsoft.ML.StaticPipe/ImageStaticPipe.cs @@ -71,14 +71,14 @@ public static Custom AsGrayscale(this Custom input) /// The now uniformly sized images /// public static Custom Resize(this Custom input, int width, int height, - ImageResizerTransformer.ResizingKind resizing = ImageResizerTransformer.ResizingKind.IsoCrop, - ImageResizerTransformer.Anchor cropAnchor = ImageResizerTransformer.Anchor.Center) + ImageResizingEstimator.ResizingKind resizing = ImageResizingEstimator.ResizingKind.IsoCrop, + ImageResizingEstimator.Anchor cropAnchor = ImageResizingEstimator.Anchor.Center) { Contracts.CheckValue(input, nameof(input)); Contracts.CheckParam(width > 0, nameof(width), "Must be positive"); Contracts.CheckParam(height > 0, nameof(height), "Must be positive"); - Contracts.CheckParam(Enum.IsDefined(typeof(ImageResizerTransformer.ResizingKind), resizing), nameof(resizing), "Undefined value detected"); - Contracts.CheckParam(Enum.IsDefined(typeof(ImageResizerTransformer.Anchor), cropAnchor), nameof(cropAnchor), "Undefined value detected"); + Contracts.CheckParam(Enum.IsDefined(typeof(ImageResizingEstimator.ResizingKind), resizing), nameof(resizing), "Undefined value detected"); + Contracts.CheckParam(Enum.IsDefined(typeof(ImageResizingEstimator.Anchor), cropAnchor), nameof(cropAnchor), "Undefined value detected"); return new ImageResizingStaticExtensions.OutPipelineColumn(input, width, height, resizing, cropAnchor); } @@ -94,14 +94,14 @@ public static Custom Resize(this Custom input, int wi /// The resized images /// public static Custom Resize(this Custom input, int width, int height, - ImageResizerTransformer.ResizingKind resizing = ImageResizerTransformer.ResizingKind.IsoCrop, - ImageResizerTransformer.Anchor cropAnchor = ImageResizerTransformer.Anchor.Center) + ImageResizingEstimator.ResizingKind resizing = ImageResizingEstimator.ResizingKind.IsoCrop, + ImageResizingEstimator.Anchor cropAnchor = ImageResizingEstimator.Anchor.Center) { Contracts.CheckValue(input, nameof(input)); Contracts.CheckParam(width > 0, nameof(width), "Must be positive"); Contracts.CheckParam(height > 0, nameof(height), "Must be positive"); - Contracts.CheckParam(Enum.IsDefined(typeof(ImageResizerTransformer.ResizingKind), resizing), nameof(resizing), "Undefined value detected"); - Contracts.CheckParam(Enum.IsDefined(typeof(ImageResizerTransformer.Anchor), cropAnchor), nameof(cropAnchor), "Undefined value detected"); + Contracts.CheckParam(Enum.IsDefined(typeof(ImageResizingEstimator.ResizingKind), resizing), nameof(resizing), "Undefined value detected"); + Contracts.CheckParam(Enum.IsDefined(typeof(ImageResizingEstimator.Anchor), cropAnchor), nameof(cropAnchor), "Undefined value detected"); return new ImageResizingStaticExtensions.OutPipelineColumn(input, width, height, resizing, cropAnchor); } @@ -124,7 +124,7 @@ public static Custom Resize(this Custom input, int width, int he public static Vector ExtractPixels(this Custom input, bool useAlpha = false, bool useRed = true, bool useGreen = true, bool useBlue = true, bool interleaveArgb = false, float scale = 1.0f, float offset = 0.0f) { - var colParams = new ImagePixelExtractorTransformer.Column + var colParams = new ImagePixelExtractingTransformer.Column { UseAlpha = useAlpha, UseRed = useRed, @@ -154,7 +154,7 @@ public static Vector ExtractPixels(this Custom input, bool useAlp public static Vector ExtractPixelsAsBytes(this Custom input, bool useAlpha = false, bool useRed = true, bool useGreen = true, bool useBlue = true, bool interleaveArgb = false) { - var colParams = new ImagePixelExtractorTransformer.Column + var colParams = new ImagePixelExtractingTransformer.Column { UseAlpha = useAlpha, UseRed = useRed, diff --git a/src/Microsoft.ML.StaticPipe/ImageTransformsStatic.cs b/src/Microsoft.ML.StaticPipe/ImageTransformsStatic.cs index b7edd9f3d9..26d46c8f43 100644 --- a/src/Microsoft.ML.StaticPipe/ImageTransformsStatic.cs +++ b/src/Microsoft.ML.StaticPipe/ImageTransformsStatic.cs @@ -28,8 +28,8 @@ public OutPipelineColumn(Scalar path, string relativeTo) /// Reconciler to an for the . /// /// - /// We must create a new reconciler per call, because the relative path of - /// is considered a transform-wide option, as it is not specified in . However, we still + /// We must create a new reconciler per call, because the relative path of + /// is considered a transform-wide option, as it is not specified in . However, we still /// implement so the analyzer can still equate two of these things if they happen to share the same /// path, so we can be a bit more efficient with respect to our estimator declarations. /// @@ -127,11 +127,11 @@ internal sealed class OutPipelineColumn : Custom private readonly PipelineColumn _input; private readonly int _width; private readonly int _height; - private readonly ImageResizerTransformer.ResizingKind _resizing; - private readonly ImageResizerTransformer.Anchor _cropAnchor; + private readonly ImageResizingEstimator.ResizingKind _resizing; + private readonly ImageResizingEstimator.Anchor _cropAnchor; public OutPipelineColumn(PipelineColumn input, int width, int height, - ImageResizerTransformer.ResizingKind resizing, ImageResizerTransformer.Anchor cropAnchor) + ImageResizingEstimator.ResizingKind resizing, ImageResizingEstimator.Anchor cropAnchor) : base(Reconciler.Inst, input) { Contracts.AssertValue(input); @@ -142,14 +142,14 @@ public OutPipelineColumn(PipelineColumn input, int width, int height, _cropAnchor = cropAnchor; } - private ImageResizerTransformer.ColumnInfo MakeColumnInfo(string outputColumnName, string inputColumnName) - => new ImageResizerTransformer.ColumnInfo(outputColumnName, _width, _height, inputColumnName, _resizing, _cropAnchor); + private ImageResizingEstimator.ColumnInfo MakeColumnInfo(string outputColumnName, string inputColumnName) + => new ImageResizingEstimator.ColumnInfo(outputColumnName, _width, _height, inputColumnName, _resizing, _cropAnchor); /// - /// Reconciler to an for the . + /// Reconciler to an for the . /// - /// - /// + /// + /// private sealed class Reconciler : EstimatorReconciler { public static Reconciler Inst = new Reconciler(); @@ -164,7 +164,7 @@ public override IEstimator Reconcile(IHostEnvironment env, IReadOnlyDictionary outputNames, IReadOnlyCollection usedNames) { - var cols = new ImageResizerTransformer.ColumnInfo[toOutput.Length]; + var cols = new ImageResizingEstimator.ColumnInfo[toOutput.Length]; for (int i = 0; i < toOutput.Length; ++i) { var outCol = (OutPipelineColumn)toOutput[i]; @@ -182,16 +182,16 @@ private interface IColInput { Custom Input { get; } - ImagePixelExtractorTransformer.ColumnInfo MakeColumnInfo(string outputColumnName, string inputColumnName); + ImagePixelExtractingEstimator.ColumnInfo MakeColumnInfo(string outputColumnName, string inputColumnName); } internal sealed class OutPipelineColumn : Vector, IColInput { public Custom Input { get; } - private static readonly ImagePixelExtractorTransformer.Arguments _defaultArgs = new ImagePixelExtractorTransformer.Arguments(); - private readonly ImagePixelExtractorTransformer.Column _colParam; + private static readonly ImagePixelExtractingTransformer.Options _defaultArgs = new ImagePixelExtractingTransformer.Options(); + private readonly ImagePixelExtractingTransformer.Column _colParam; - public OutPipelineColumn(Custom input, ImagePixelExtractorTransformer.Column col) + public OutPipelineColumn(Custom input, ImagePixelExtractingTransformer.Column col) : base(Reconciler.Inst, input) { Contracts.AssertValue(input); @@ -200,7 +200,7 @@ public OutPipelineColumn(Custom input, ImagePixelExtractorTransformer.Co _colParam = col; } - public ImagePixelExtractorTransformer.ColumnInfo MakeColumnInfo(string outputColumnName, string inputColumnName) + public ImagePixelExtractingEstimator.ColumnInfo MakeColumnInfo(string outputColumnName, string inputColumnName) { // In principle, the analyzer should only call the the reconciler once for these columns. Contracts.Assert(_colParam.Source == null); @@ -208,7 +208,7 @@ public ImagePixelExtractorTransformer.ColumnInfo MakeColumnInfo(string outputCol _colParam.Name = outputColumnName; _colParam.Source = inputColumnName; - return new ImagePixelExtractorTransformer.ColumnInfo(_colParam, _defaultArgs); + return new ImagePixelExtractingEstimator.ColumnInfo(_colParam, _defaultArgs); } } @@ -233,7 +233,7 @@ public override IEstimator Reconcile(IHostEnvironment env, IReadOnlyDictionary outputNames, IReadOnlyCollection usedNames) { - var cols = new ImagePixelExtractorTransformer.ColumnInfo[toOutput.Length]; + var cols = new ImagePixelExtractingEstimator.ColumnInfo[toOutput.Length]; for (int i = 0; i < toOutput.Length; ++i) { var outCol = (IColInput)toOutput[i]; diff --git a/test/BaselineOutput/Common/EntryPoints/core_ep-list.tsv b/test/BaselineOutput/Common/EntryPoints/core_ep-list.tsv index 8525c932d4..8db7a9ad8f 100644 --- a/test/BaselineOutput/Common/EntryPoints/core_ep-list.tsv +++ b/test/BaselineOutput/Common/EntryPoints/core_ep-list.tsv @@ -92,10 +92,10 @@ Transforms.FeatureSelectorByCount Selects the slots for which the count of non-d Transforms.FeatureSelectorByMutualInformation Selects the top k slots across all specified columns ordered by their mutual information with the label column. Microsoft.ML.Transforms.SelectFeatures MutualInformationSelect Microsoft.ML.Transforms.FeatureSelection.MutualInformationFeatureSelectingEstimator+Arguments Microsoft.ML.EntryPoints.CommonOutputs+TransformOutput Transforms.GlobalContrastNormalizer Performs a global contrast normalization on input values: Y = (s * X - M) / D, where s is a scale, M is mean and D is either L2 norm or standard deviation. Microsoft.ML.Transforms.Projections.LpNormalization GcNormalize Microsoft.ML.Transforms.Projections.LpNormalizingTransformer+GcnArguments Microsoft.ML.EntryPoints.CommonOutputs+TransformOutput Transforms.HashConverter Converts column values into hashes. This transform accepts both numeric and text inputs, both single and vector-valued columns. Microsoft.ML.Transforms.Conversions.HashJoin Apply Microsoft.ML.Transforms.Conversions.HashJoiningTransform+Arguments Microsoft.ML.EntryPoints.CommonOutputs+TransformOutput -Transforms.ImageGrayscale Convert image into grayscale. Microsoft.ML.ImageAnalytics.EntryPoints.ImageAnalytics ImageGrayscale Microsoft.ML.ImageAnalytics.ImageGrayscaleTransformer+Arguments Microsoft.ML.EntryPoints.CommonOutputs+TransformOutput -Transforms.ImageLoader Load images from files. Microsoft.ML.ImageAnalytics.EntryPoints.ImageAnalytics ImageLoader Microsoft.ML.ImageAnalytics.ImageLoaderTransformer+Arguments Microsoft.ML.EntryPoints.CommonOutputs+TransformOutput -Transforms.ImagePixelExtractor Extract color plane(s) from an image. Options include scaling, offset and conversion to floating point. Microsoft.ML.ImageAnalytics.EntryPoints.ImageAnalytics ImagePixelExtractor Microsoft.ML.ImageAnalytics.ImagePixelExtractorTransformer+Arguments Microsoft.ML.EntryPoints.CommonOutputs+TransformOutput -Transforms.ImageResizer Scales an image to specified dimensions using one of the three scale types: isotropic with padding, isotropic with cropping or anisotropic. In case of isotropic padding, transparent color is used to pad resulting image. Microsoft.ML.ImageAnalytics.EntryPoints.ImageAnalytics ImageResizer Microsoft.ML.ImageAnalytics.ImageResizerTransformer+Arguments Microsoft.ML.EntryPoints.CommonOutputs+TransformOutput +Transforms.ImageGrayscale Convert image into grayscale. Microsoft.ML.ImageAnalytics.EntryPoints.ImageAnalytics ImageGrayscale Microsoft.ML.ImageAnalytics.ImageGrayscalingTransformer+Options Microsoft.ML.EntryPoints.CommonOutputs+TransformOutput +Transforms.ImageLoader Load images from files. Microsoft.ML.ImageAnalytics.EntryPoints.ImageAnalytics ImageLoader Microsoft.ML.ImageAnalytics.ImageLoadingTransformer+Options Microsoft.ML.EntryPoints.CommonOutputs+TransformOutput +Transforms.ImagePixelExtractor Extract color plane(s) from an image. Options include scaling, offset and conversion to floating point. Microsoft.ML.ImageAnalytics.EntryPoints.ImageAnalytics ImagePixelExtractor Microsoft.ML.ImageAnalytics.ImagePixelExtractingTransformer+Options Microsoft.ML.EntryPoints.CommonOutputs+TransformOutput +Transforms.ImageResizer Scales an image to specified dimensions using one of the three scale types: isotropic with padding, isotropic with cropping or anisotropic. In case of isotropic padding, transparent color is used to pad resulting image. Microsoft.ML.ImageAnalytics.EntryPoints.ImageAnalytics ImageResizer Microsoft.ML.ImageAnalytics.ImageResizingTransformer+Arguments Microsoft.ML.EntryPoints.CommonOutputs+TransformOutput Transforms.KeyToTextConverter KeyToValueTransform utilizes KeyValues metadata to map key indices to the corresponding values in the KeyValues metadata. Microsoft.ML.Transforms.Categorical.Categorical KeyToText Microsoft.ML.Transforms.Conversions.KeyToValueMappingTransformer+Options Microsoft.ML.EntryPoints.CommonOutputs+TransformOutput Transforms.LabelColumnKeyBooleanConverter Transforms the label to either key or bool (if needed) to make it suitable for classification. Microsoft.ML.EntryPoints.FeatureCombiner PrepareClassificationLabel Microsoft.ML.EntryPoints.FeatureCombiner+ClassificationLabelInput Microsoft.ML.EntryPoints.CommonOutputs+TransformOutput Transforms.LabelIndicator Label remapper used by OVA Microsoft.ML.Transforms.LabelIndicatorTransform LabelIndicator Microsoft.ML.Transforms.LabelIndicatorTransform+Arguments Microsoft.ML.EntryPoints.CommonOutputs+TransformOutput diff --git a/test/Microsoft.ML.Core.Tests/UnitTests/TestEntryPoints.cs b/test/Microsoft.ML.Core.Tests/UnitTests/TestEntryPoints.cs index a75ac92051..1e30c9b833 100644 --- a/test/Microsoft.ML.Core.Tests/UnitTests/TestEntryPoints.cs +++ b/test/Microsoft.ML.Core.Tests/UnitTests/TestEntryPoints.cs @@ -349,7 +349,7 @@ public void EntryPointCatalogCheckDuplicateParams() { Env.ComponentCatalog.RegisterAssembly(typeof(LightGbmBinaryModelParameters).Assembly); Env.ComponentCatalog.RegisterAssembly(typeof(TensorFlowTransformer).Assembly); - Env.ComponentCatalog.RegisterAssembly(typeof(ImageLoaderTransformer).Assembly); + Env.ComponentCatalog.RegisterAssembly(typeof(ImageLoadingTransformer).Assembly); Env.ComponentCatalog.RegisterAssembly(typeof(SymSgdClassificationTrainer).Assembly); Env.ComponentCatalog.RegisterAssembly(typeof(SaveOnnxCommand).Assembly); Env.ComponentCatalog.RegisterAssembly(typeof(TimeSeriesProcessingEntryPoints).Assembly); diff --git a/test/Microsoft.ML.Tests/ImagesTests.cs b/test/Microsoft.ML.Tests/ImagesTests.cs index f1667df644..7e55522b99 100644 --- a/test/Microsoft.ML.Tests/ImagesTests.cs +++ b/test/Microsoft.ML.Tests/ImagesTests.cs @@ -84,8 +84,8 @@ public void TestEstimatorSaveLoad() model.SaveTo(env, fs); var model2 = TransformerChain.LoadFrom(env, file.OpenReadStream()); - var newCols = ((ImageLoaderTransformer)model2.First()).Columns; - var oldCols = ((ImageLoaderTransformer)model.First()).Columns; + var newCols = ((ImageLoadingTransformer)model2.First()).Columns; + var oldCols = ((ImageLoadingTransformer)model.First()).Columns; Assert.True(newCols .Zip(oldCols, (x, y) => x == y) .All(x => x)); @@ -107,8 +107,8 @@ public void TestSaveImages() new TextLoader.Column("Name", DataKind.TX, 1), } }, new MultiFileSource(dataFile)); - var images = new ImageLoaderTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); - var cropped = new ImageResizerTransformer(env, "ImageCropped", 100, 100, "ImageReal", ImageResizerTransformer.ResizingKind.IsoPad).Transform(images); + var images = new ImageLoadingTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); + var cropped = new ImageResizingTransformer(env, "ImageCropped", 100, 100, "ImageReal", ImageResizingEstimator.ResizingKind.IsoPad).Transform(images); cropped.Schema.TryGetColumnIndex("ImagePath", out int pathColumn); cropped.Schema.TryGetColumnIndex("ImageCropped", out int cropBitmapColumn); @@ -146,11 +146,11 @@ public void TestGreyscaleTransformImages() new TextLoader.Column("Name", DataKind.TX, 1), } }, new MultiFileSource(dataFile)); - var images = new ImageLoaderTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); + var images = new ImageLoadingTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); - var cropped = new ImageResizerTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); + var cropped = new ImageResizingTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); - IDataView grey = new ImageGrayscaleTransformer(env, ("ImageGrey", "ImageCropped")).Transform(cropped); + IDataView grey = new ImageGrayscalingTransformer(env, ("ImageGrey", "ImageCropped")).Transform(cropped); var fname = nameof(TestGreyscaleTransformImages) + "_model.zip"; var fh = env.CreateOutputFile(fname); @@ -197,10 +197,10 @@ public void TestBackAndForthConversionWithAlphaInterleave() new TextLoader.Column("Name", DataKind.TX, 1), } }, new MultiFileSource(dataFile)); - var images = new ImageLoaderTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); - var cropped = new ImageResizerTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); + var images = new ImageLoadingTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); + var cropped = new ImageResizingTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); - var pixels = new ImagePixelExtractorTransformer(env, "ImagePixels", "ImageCropped", ImagePixelExtractorTransformer.ColorBits.All, true, 2f / 255, 127.5f).Transform(cropped); + var pixels = new ImagePixelExtractingTransformer(env, "ImagePixels", "ImageCropped", ImagePixelExtractingEstimator.ColorBits.All, true, 2f / 255, 127.5f).Transform(cropped); IDataView backToBitmaps = new VectorToImageTransform(env, new VectorToImageTransform.Arguments() { InterleaveArgb = true, @@ -264,9 +264,9 @@ public void TestBackAndForthConversionWithoutAlphaInterleave() new TextLoader.Column("Name", DataKind.TX, 1), } }, new MultiFileSource(dataFile)); - var images = new ImageLoaderTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); - var cropped = new ImageResizerTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); - var pixels = new ImagePixelExtractorTransformer(env, "ImagePixels", "ImageCropped", ImagePixelExtractorTransformer.ColorBits.Rgb, true, 2f / 255, 127.5f).Transform(cropped); + var images = new ImageLoadingTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); + var cropped = new ImageResizingTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); + var pixels = new ImagePixelExtractingTransformer(env, "ImagePixels", "ImageCropped", ImagePixelExtractingEstimator.ColorBits.Rgb, true, 2f / 255, 127.5f).Transform(cropped); IDataView backToBitmaps = new VectorToImageTransform(env, new VectorToImageTransform.Arguments() { @@ -331,9 +331,9 @@ public void TestBackAndForthConversionWithAlphaNoInterleave() new TextLoader.Column("Name", DataKind.TX, 1), } }, new MultiFileSource(dataFile)); - var images = new ImageLoaderTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); - var cropped = new ImageResizerTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); - var pixels = new ImagePixelExtractorTransformer(env, "ImagePixels", "ImageCropped", ImagePixelExtractorTransformer.ColorBits.All, false, 2f / 255, 127.5f).Transform(cropped); + var images = new ImageLoadingTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); + var cropped = new ImageResizingTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); + var pixels = new ImagePixelExtractingTransformer(env, "ImagePixels", "ImageCropped", ImagePixelExtractingEstimator.ColorBits.All, false, 2f / 255, 127.5f).Transform(cropped); IDataView backToBitmaps = new VectorToImageTransform(env, new VectorToImageTransform.Arguments() { @@ -398,9 +398,9 @@ public void TestBackAndForthConversionWithoutAlphaNoInterleave() new TextLoader.Column("Name", DataKind.TX, 1), } }, new MultiFileSource(dataFile)); - var images = new ImageLoaderTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); - var cropped = new ImageResizerTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); - var pixels = new ImagePixelExtractorTransformer(env, "ImagePixels", "ImageCropped", ImagePixelExtractorTransformer.ColorBits.Rgb, false, 2f / 255, 127.5f).Transform(cropped); + var images = new ImageLoadingTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); + var cropped = new ImageResizingTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); + var pixels = new ImagePixelExtractingTransformer(env, "ImagePixels", "ImageCropped", ImagePixelExtractingEstimator.ColorBits.Rgb, false, 2f / 255, 127.5f).Transform(cropped); IDataView backToBitmaps = new VectorToImageTransform(env, new VectorToImageTransform.Arguments() { @@ -465,10 +465,10 @@ public void TestBackAndForthConversionWithAlphaInterleaveNoOffset() new TextLoader.Column("Name", DataKind.TX, 1), } }, new MultiFileSource(dataFile)); - var images = new ImageLoaderTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); - var cropped = new ImageResizerTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); + var images = new ImageLoadingTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); + var cropped = new ImageResizingTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); - var pixels = new ImagePixelExtractorTransformer(env, "ImagePixels", "ImageCropped", ImagePixelExtractorTransformer.ColorBits.All, true).Transform(cropped); + var pixels = new ImagePixelExtractingTransformer(env, "ImagePixels", "ImageCropped", ImagePixelExtractingEstimator.ColorBits.All, true).Transform(cropped); IDataView backToBitmaps = new VectorToImageTransform(env, new VectorToImageTransform.Arguments() { @@ -531,10 +531,10 @@ public void TestBackAndForthConversionWithoutAlphaInterleaveNoOffset() new TextLoader.Column("Name", DataKind.TX, 1), } }, new MultiFileSource(dataFile)); - var images = new ImageLoaderTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); - var cropped = new ImageResizerTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); + var images = new ImageLoadingTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); + var cropped = new ImageResizingTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); - var pixels = new ImagePixelExtractorTransformer(env, "ImagePixels", "ImageCropped", ImagePixelExtractorTransformer.ColorBits.Rgb, true).Transform(cropped); + var pixels = new ImagePixelExtractingTransformer(env, "ImagePixels", "ImageCropped", ImagePixelExtractingEstimator.ColorBits.Rgb, true).Transform(cropped); IDataView backToBitmaps = new VectorToImageTransform(env, new VectorToImageTransform.Arguments() { @@ -597,10 +597,10 @@ public void TestBackAndForthConversionWithAlphaNoInterleaveNoOffset() new TextLoader.Column("Name", DataKind.TX, 1), } }, new MultiFileSource(dataFile)); - var images = new ImageLoaderTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); - var cropped = new ImageResizerTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); + var images = new ImageLoadingTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); + var cropped = new ImageResizingTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); - var pixels = new ImagePixelExtractorTransformer(env, "ImagePixels", "ImageCropped", ImagePixelExtractorTransformer.ColorBits.All).Transform(cropped); + var pixels = new ImagePixelExtractingTransformer(env, "ImagePixels", "ImageCropped", ImagePixelExtractingEstimator.ColorBits.All).Transform(cropped); IDataView backToBitmaps = new VectorToImageTransform(env, new VectorToImageTransform.Arguments() { @@ -663,9 +663,9 @@ public void TestBackAndForthConversionWithoutAlphaNoInterleaveNoOffset() new TextLoader.Column("Name", DataKind.TX, 1), } }, new MultiFileSource(dataFile)); - var images = new ImageLoaderTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); - var cropped = new ImageResizerTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); - var pixels = new ImagePixelExtractorTransformer(env, "ImagePixels", "ImageCropped").Transform(cropped); + var images = new ImageLoadingTransformer(env, imageFolder, ("ImageReal", "ImagePath")).Transform(data); + var cropped = new ImageResizingTransformer(env, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); + var pixels = new ImagePixelExtractingTransformer(env, "ImagePixels", "ImageCropped").Transform(cropped); IDataView backToBitmaps = new VectorToImageTransform(env, new VectorToImageTransform.Arguments() { @@ -729,7 +729,7 @@ public void ImageResizerTransformResizingModeFill() const int targetDimension = 50; var pipe = new ImageLoadingEstimator(env, imageFolder, ("ImageReal", "ImagePath")) .Append(new ImageResizingEstimator(env, "ImageReal", targetDimension, targetDimension, "ImageReal", - resizing: ImageResizerTransformer.ResizingKind.Fill)); + resizing: ImageResizingEstimator.ResizingKind.Fill)); var rowView = pipe.Preview(data).RowView; Assert.Single(rowView); diff --git a/test/Microsoft.ML.Tests/ScenariosWithDirectInstantiation/TensorflowTests.cs b/test/Microsoft.ML.Tests/ScenariosWithDirectInstantiation/TensorflowTests.cs index 86578220b1..0b95aff834 100644 --- a/test/Microsoft.ML.Tests/ScenariosWithDirectInstantiation/TensorflowTests.cs +++ b/test/Microsoft.ML.Tests/ScenariosWithDirectInstantiation/TensorflowTests.cs @@ -235,10 +235,10 @@ public void TensorFlowTransformObjectDetectionTest() var dataFile = GetDataPath("images/images.tsv"); var imageFolder = Path.GetDirectoryName(dataFile); var data = mlContext.CreateLoader("Text{col=ImagePath:TX:0 col=Name:TX:1}", new MultiFileSource(dataFile)); - var images = new ImageLoaderTransformer(mlContext, imageFolder, ("ImageReal", "ImagePath")).Transform(data); - var cropped = new ImageResizerTransformer(mlContext, "ImageCropped", 32, 32, "ImageReal").Transform(images); + var images = new ImageLoadingTransformer(mlContext, imageFolder, ("ImageReal", "ImagePath")).Transform(data); + var cropped = new ImageResizingTransformer(mlContext, "ImageCropped", 32, 32, "ImageReal").Transform(images); - var pixels = new ImagePixelExtractorTransformer(mlContext, "image_tensor", "ImageCropped", asFloat: false).Transform(cropped); + var pixels = new ImagePixelExtractingTransformer(mlContext, "image_tensor", "ImageCropped", asFloat: false).Transform(cropped); var tf = new TensorFlowTransformer(mlContext, modelLocation, new[] { "detection_boxes", "detection_scores", "num_detections", "detection_classes" }, new[] { "image_tensor" }).Transform(pixels); @@ -276,9 +276,9 @@ public void TensorFlowTransformInceptionTest() var dataFile = GetDataPath("images/images.tsv"); var imageFolder = Path.GetDirectoryName(dataFile); var data = mlContext.CreateLoader("Text{col=ImagePath:TX:0 col=Name:TX:1}", new MultiFileSource(dataFile)); - var images = new ImageLoaderTransformer(mlContext, imageFolder, ("ImageReal", "ImagePath")).Transform(data); - var cropped = new ImageResizerTransformer(mlContext, "ImageCropped", 224, 224 , "ImageReal").Transform(images); - var pixels = new ImagePixelExtractorTransformer(mlContext, "input","ImageCropped").Transform(cropped); + var images = new ImageLoadingTransformer(mlContext, imageFolder, ("ImageReal", "ImagePath")).Transform(data); + var cropped = new ImageResizingTransformer(mlContext, "ImageCropped", 224, 224 , "ImageReal").Transform(images); + var pixels = new ImagePixelExtractingTransformer(mlContext, "input","ImageCropped").Transform(cropped); var tf = new TensorFlowTransformer(mlContext, modelLocation, "softmax2_pre_activation", "input").Transform(pixels); tf.Schema.TryGetColumnIndex("input", out int input); @@ -781,9 +781,9 @@ public void TensorFlowTransformCifarSavedModel() new TextLoader.Column("Name", DataKind.TX, 1), } ); - var images = new ImageLoaderTransformer(mlContext, imageFolder, ("ImageReal", "ImagePath")).Transform(data); - var cropped = new ImageResizerTransformer(mlContext, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); - var pixels = new ImagePixelExtractorTransformer(mlContext, "Input", "ImageCropped", interleave: true).Transform(cropped); + var images = new ImageLoadingTransformer(mlContext, imageFolder, ("ImageReal", "ImagePath")).Transform(data); + var cropped = new ImageResizingTransformer(mlContext, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); + var pixels = new ImagePixelExtractingTransformer(mlContext, "Input", "ImageCropped", interleave: true).Transform(cropped); IDataView trans = new TensorFlowTransformer(mlContext, tensorFlowModel, "Output", "Input").Transform(pixels); trans.Schema.TryGetColumnIndex("Output", out int output); @@ -833,9 +833,9 @@ public void TensorFlowTransformCifarInvalidShape() new TextLoader.Column("Name", DataKind.TX, 1), } ); - var images = new ImageLoaderTransformer(mlContext, imageFolder, ("ImageReal", "ImagePath")).Transform(data); - var cropped = new ImageResizerTransformer(mlContext, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); - var pixels = new ImagePixelExtractorTransformer(mlContext, "Input", "ImageCropped").Transform(cropped); + var images = new ImageLoadingTransformer(mlContext, imageFolder, ("ImageReal", "ImagePath")).Transform(data); + var cropped = new ImageResizingTransformer(mlContext, "ImageCropped", imageWidth, imageHeight, "ImageReal").Transform(images); + var pixels = new ImagePixelExtractingTransformer(mlContext, "Input", "ImageCropped").Transform(cropped); var thrown = false; try