// Use for multiple dimension arrays static IntPtr SetupMulti(TFDataType dt, long [] dims, Array data, long bytes) { var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); if (dims == null) { return(TF_NewTensor(dt, IntPtr.Zero, 0, dataHandle.AddrOfPinnedObject(), (UIntPtr)bytes, FreeTensorHandle, GCHandle.ToIntPtr(dataHandle))); } else { return(TF_NewTensor(dt, dims, dims.Length, dataHandle.AddrOfPinnedObject(), (UIntPtr)bytes, FreeTensorHandle, GCHandle.ToIntPtr(dataHandle))); } }
private static void FetchMultiDimensionalArray(Array target, TFDataType dt, IntPtr data, long[] shape) { var idx = new int[shape.Length]; for (int i = 0; i < shape.Length; i++) { if (shape[i] > Int32.MaxValue) { throw new ArgumentOutOfRangeException("Shape can not be longer than 32 bits"); } } Copy(target, dt, shape, idx, 0, ref data); }
/// <summary> /// Input() is used to instantiate a Keras tensor. /// </summary> /// /// <remarks> /// A Keras tensor is a tensor object from the underlying backend (Theano or TensorFlow), which we /// augment with certain attributes that allow us to build a Keras model just by knowing the inputs /// and outputs of the model. /// </remarks> /// /// <param name="shape">A shape tuple (integer), including the batch size. For instance, /// <c>batch_shape= (10, 32)</c> indicates that the expected input will be batches of 10 32-dimensional /// vectors. <c>batch_shape= (None, 32)</c> indicates batches of an arbitrary number of 32-dimensional /// vectors.</param> /// <param name="batch_shape">The batch shape.</param> /// <param name="name">An optional name string for the layer. Should be unique in a model (do not reuse /// the same name twice). It will be autogenerated if it isn't provided.</param> /// <param name="dtype">The data type expected by the input, as a string /// (`float32`, `float64`, `int32`...)</param> /// <param name="sparse">A boolean specifying whether the placeholder to be created is sparse.</param> /// <param name="tensor">Optional existing tensor to wrap into the `Input` layer. /// If set, the layer will not create a placeholder tensor.</param> /// public static List <Tensor> Input(int?[] shape = null, int?[] batch_shape = null, string name = null, TFDataType dtype = KerasSharp.Tools.DEFAULT_DTYPE, bool sparse = false, Tensor tensor = null) { if (batch_shape == null && tensor == null) { throw new ArgumentException("Please provide to Input either a `shape` or a `batch_shape` argument. Note that " + "`shape` does not include the batch dimension."); } if (shape != null && batch_shape != null) { batch_shape = new int?[] { null } }
private static (string[], int[], bool[], TFShape[], TFDataType[]) GetInputMetaData(TFGraph graph, string[] source, ISchema inputSchema) { var tfShapes = new TFShape[source.Length]; var tfTypes = new TFDataType[source.Length]; var colNames = new string[source.Length]; var inputColIndices = new int[source.Length]; var isInputVector = new bool[source.Length]; for (int i = 0; i < source.Length; i++) { colNames[i] = source[i]; if (!inputSchema.TryGetColumnIndex(colNames[i], out inputColIndices[i])) { throw Contracts.Except($"Column '{colNames[i]}' does not exist"); } var tfoutput = new TFOutput(graph[colNames[i]]); if (!TensorFlowUtils.IsTypeSupported(tfoutput.OutputType)) { throw Contracts.Except($"Input type '{tfoutput.OutputType}' of input column '{colNames[i]}' is not supported in TensorFlow"); } tfShapes[i] = graph.GetTensorShape(tfoutput); var type = inputSchema.GetColumnType(inputColIndices[i]); var shape = tfShapes[i].ToIntArray().Skip(tfShapes[i][0] == -1 ? BatchSize : 0); if (type.AsVector.DimCount == 1) { int valCount = shape.Aggregate((x, y) => x * y); if (type.ValueCount != valCount) { throw Contracts.Except($"Input shape mismatch: Input '{colNames[i]}' has shape {tfShapes[i].ToString()}, but input data is of length {valCount}."); } } else if (shape.Select((dim, j) => dim != type.AsVector.GetDim(j)).Any(b => b)) { throw Contracts.Except($"Input shape mismatch: Input '{colNames[i]}' has shape {tfShapes[i].ToString()}, but input data is {type.AsVector.ToString()}."); } isInputVector[i] = type.IsVector; tfTypes[i] = tfoutput.OutputType; var l = new long[tfShapes[i].NumDimensions]; for (int ishape = 0; ishape < tfShapes[i].NumDimensions; ishape++) { l[ishape] = tfShapes[i][ishape] == -1 ? BatchSize : tfShapes[i][ishape]; } tfShapes[i] = new TFShape(l); } return(colNames, inputColIndices, isInputVector, tfShapes, tfTypes); }
/// <summary> /// Converts a <see cref="TFDataType"/> to a system type. /// </summary> /// <param name="type">The <see cref="TFDataType"/> to be converted.</param> /// <returns>The system type corresponding to the given <paramref name="type"/>.</returns> public static Type TypeFromTensorType(TFDataType type) { switch (type) { case TFDataType.Float: return(typeof(float)); case TFDataType.Float_ref: return(typeof(float)); case TFDataType.Double: return(typeof(double)); case TFDataType.Int8: return(typeof(sbyte)); case TFDataType.Int16: return(typeof(short)); case TFDataType.Int32: return(typeof(int)); case TFDataType.Int64: return(typeof(long)); case TFDataType.UInt8: return(typeof(byte)); case TFDataType.UInt16: return(typeof(ushort)); case TFDataType.UInt32: return(typeof(uint)); case TFDataType.UInt64: return(typeof(ulong)); case TFDataType.String: throw new NotSupportedException(); case TFDataType.Bool: return(typeof(bool)); case TFDataType.Complex128: return(typeof(Complex)); default: return(null); } }
/// <summary> /// Input() is used to instantiate a Keras tensor. /// </summary> /// /// <remarks> /// A Keras tensor is a tensor object from the underlying backend (Theano or TensorFlow), which we /// augment with certain attributes that allow us to build a Keras model just by knowing the inputs /// and outputs of the model. /// </remarks> /// /// <param name="shape">A shape tuple (integer), including the batch size. For instance, /// <c>batch_shape= (10, 32)</c> indicates that the expected input will be batches of 10 32-dimensional /// vectors. <c>batch_shape= (None, 32)</c> indicates batches of an arbitrary number of 32-dimensional /// vectors.</param> /// <param name="batch_shape">The batch shape.</param> /// <param name="name">An optional name string for the layer. Should be unique in a model (do not reuse /// the same name twice). It will be autogenerated if it isn't provided.</param> /// <param name="dtype">The data type expected by the input, as a string /// (`float32`, `float64`, `int32`...)</param> /// <param name="sparse">A boolean specifying whether the placeholder to be created is sparse.</param> /// <param name="tensor">Optional existing tensor to wrap into the `Input` layer. /// If set, the layer will not create a placeholder tensor.</param> /// public static List <Tensor> Input(int?[] shape = null, int?[] batch_shape = null, string name = null, TFDataType dtype = KerasSharp.Utils.DEFAULT_DTYPE, bool sparse = false, Tensor tensor = null) { // https://github.com/fchollet/keras/blob/f65a56fb65062c8d14d215c9f4b1015b97cc5bf3/keras/engine/topology.py#L1416 if (batch_shape == null && tensor == null) { throw new ArgumentException("Please provide to Input either a 'shape' or a 'batch_shape' argument. Note that " + "'shape' does not include the batch dimension."); } if (shape != null && batch_shape != null) { batch_shape = new int?[] { null } }
private TFTensor CreateTensorFromImage(byte[] contents, TFDataType dataType = TFDataType.Float) { // DecodeJpeg uses a scalar String-valued tensor as input. using (var tensor = TFTensor.CreateString(contents)) using (var graph = ConstructGraphToNormalizeImage(out TFOutput input, out TFOutput output, dataType)) using (var session = new TFSession(graph)) { var normalized = session.Run( inputs: new[] { input }, inputValues: new[] { tensor }, outputs: new[] { output }); return(normalized[0]); } }
internal static bool IsTypeSupported(TFDataType tfoutput) { switch (tfoutput) { case TFDataType.Float: case TFDataType.Double: case TFDataType.UInt8: case TFDataType.UInt16: case TFDataType.UInt32: case TFDataType.UInt64: return(true); default: return(false); } }
private static unsafe object FetchSimple(TFDataType dt, IntPtr data) { switch (dt) { case TFDataType.Float: return(*(float *)data); case TFDataType.Double: return(*(double *)data); case TFDataType.Int8: return(*(sbyte *)data); case TFDataType.Int16: return(*(short *)data); case TFDataType.Int32: return(*(int *)data); case TFDataType.Int64: return(*(long *)data); case TFDataType.UInt8: return(*(byte *)data); case TFDataType.UInt16: return(*(ushort *)data); case TFDataType.UInt32: return(*(uint *)data); case TFDataType.UInt64: return(*(ulong *)data); case TFDataType.String: throw new NotImplementedException(); case TFDataType.Bool: return(*(bool *)data); case TFDataType.Complex128: return(*(Complex *)data); default: return(null); } }
private static PrimitiveDataViewType Tf2MlNetTypeOrNull(TFDataType type) { switch (type) { case TFDataType.Float: return(NumberDataViewType.Single); case TFDataType.Float_ref: return(NumberDataViewType.Single); case TFDataType.Double: return(NumberDataViewType.Double); case TFDataType.UInt8: return(NumberDataViewType.Byte); case TFDataType.UInt16: return(NumberDataViewType.UInt16); case TFDataType.UInt32: return(NumberDataViewType.UInt32); case TFDataType.UInt64: return(NumberDataViewType.UInt64); case TFDataType.Int8: return(NumberDataViewType.SByte); case TFDataType.Int16: return(NumberDataViewType.Int16); case TFDataType.Int32: return(NumberDataViewType.Int32); case TFDataType.Int64: return(NumberDataViewType.Int64); case TFDataType.Bool: return(BooleanDataViewType.Instance); case TFDataType.String: return(TextDataViewType.Instance); default: return(null); } }
/// <summary> /// Specifies the ndim, dtype and shape of every input to a layer. /// </summary> /// /// <remarks> /// Every layer should expose (if appropriate) an `input_spec` attribute: /// a list of instances of InputSpec(one per input tensor). /// A null entry in a shape is compatible with any dimension, /// a null shape is compatible with any shape. /// </remarks> /// /// <param name="dtype">Expected datatype of the input.</param> /// <param name="shape">Shape tuple, expected shape of the input /// (may include null for unchecked axes).</param> /// <param name="ndim">Integer, expected rank of the input.</param> /// <param name="max_ndim">The maximum rank of the input.</param> /// <param name="min_ndim">The minimum rank of the input.</param> /// <param name="axes">Dictionary mapping integer axes to /// a specific dimension value.</param> public InputSpec(TFDataType dtype = Tools.DEFAULT_DTYPE, int[] shape = null, int?ndim = null, int?max_ndim = null, int?min_ndim = null, Dictionary <int, int> axes = null) { this.dtype = dtype; this.shape = shape; if (shape != null) { this.ndim = shape.Length; } else { this.ndim = ndim; } this.max_ndim = max_ndim; this.min_ndim = min_ndim; this.axes = axes ?? new Dictionary <int, int>(); }
private static TFGraph ConstructGraphToNormalizeImage(out TFOutput input, out TFOutput output, TFDataType destinationDataType = TFDataType.Float) { var graph = new TFGraph(); input = graph.Placeholder(TFDataType.String); output = graph.Cast( graph.ExpandDims( input: graph.Cast(graph.DecodeJpeg(contents: input, channels: 3), DstT: TFDataType.Float), dim: graph.Const(0, "make_batch") ) , destinationDataType ); return(graph); }
// Convert the image in filename to a Tensor suitable as input to the Inception model. public static TFTensor CreateTensorFromImage(byte[] image, TFDataType destinationDataType = TFDataType.Float) { // DecodeJpeg uses a scalar String-valued tensor as input. var tensor = TFTensor.CreateString(image); // Construct a graph to normalize the image var(graph, input, output) = ConstructGraphToNormalizeImage(destinationDataType); // Execute that graph to normalize this one image using (var session = new TFSession(graph)) { var normalized = session.Run( inputs: new[] { input }, inputValues: new[] { tensor }, outputs: new[] { output }); return(normalized[0]); } }
// Use for single dimension arrays internal static IntPtr SetupTensor(TFDataType dt, long[] dims, Array data, int start, int count, int size) { if (start < 0 || start > data.Length - count) { throw new ArgumentException("start + count > Array size"); } var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); if (dims == null) { return(TF_NewTensor(dt, IntPtr.Zero, 0, dataHandle.AddrOfPinnedObject() + start * size, (UIntPtr)(count * size), FreeTensorHandleDelegate, GCHandle.ToIntPtr(dataHandle))); } else { return(TF_NewTensor(dt, dims, dims.Length, dataHandle.AddrOfPinnedObject() + start * size, (UIntPtr)(count * size), FreeTensorHandleDelegate, GCHandle.ToIntPtr(dataHandle))); } }
private static PrimitiveType Tf2MlNetTypeOrNull(TFDataType type) { switch (type) { case TFDataType.Float: return(NumberType.R4); case TFDataType.Float_ref: return(NumberType.R4); case TFDataType.Double: return(NumberType.R8); case TFDataType.UInt8: return(NumberType.U1); case TFDataType.UInt16: return(NumberType.U2); case TFDataType.UInt32: return(NumberType.U4); case TFDataType.UInt64: return(NumberType.U8); case TFDataType.Int8: return(NumberType.I1); case TFDataType.Int16: return(NumberType.I2); case TFDataType.Int32: return(NumberType.I4); case TFDataType.Int64: return(NumberType.I8); case TFDataType.Bool: return(BoolType.Instance); default: return(null); } }
private static TFGraph ConstructGraphToNormalizeRawImage(out TFOutput input, out TFOutput output, int resizeWidth, int resizeHeight, TFDataType destinationDataType = TFDataType.Float) { // Some constants specific to the pre-trained model at: // https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip // // - The model was trained after with images scaled to 224x224 pixels. // - The colors, represented as R, G, B in 1-byte each were converted to // float using (value - Mean)/Scale. const float Mean = 117; const float Scale = 1; //var graph = new TFGraph(); //input = graph.Placeholder(TFDataType.UInt8); //output = graph.Cast(graph.Div( // x: graph.Sub( // x: graph.ResizeBilinear( // images: graph.ExpandDims( // input: graph.Cast(input, DstT: TFDataType.Float), // dim: graph.Const(0, "make_batch")), // size: graph.Const(new int[] { resizeWidth, resizeHeight }, "size")), // y: graph.Const(Mean, "mean")), // y: graph.Const(Scale, "scale")), destinationDataType); //return graph; var graph = new TFGraph(); input = graph.Placeholder(TFDataType.UInt8); output = graph.Cast( graph.ExpandDims( input: graph.Cast(input, DstT: TFDataType.Float), dim: graph.Const(0, "make_batch") ) , destinationDataType ); return(graph); }
// Convert the image in filename to a Tensor suitable as input to the Inception model. public static TFTensor CreateTensorFromImageFile(string file, TFDataType destinationDataType = TFDataType.Float) { var contents = File.ReadAllBytes(file); // DecodeJpeg uses a scalar String-valued tensor as input. using (var tensor = TFTensor.CreateString(contents)) // Construct a graph to normalize the image using (var graph = ConstructGraphToNormalizeImage(out TFOutput input, out TFOutput output, destinationDataType)) // Execute that graph to normalize this one image using (var session = new TFSession(graph)) { var normalized = session.Run( inputs: new[] { input }, inputValues: new[] { tensor }, outputs: new[] { output }); Console.WriteLine(normalized.Length); return(normalized[0]); } }
public static TFTensor CreateTensor(TFTensor tensor, TFDataType destinationDataType = TFDataType.Float) { TFGraph graph; TFOutput input, output; // Construct a graph to normalize the image ConstructGraphToNormalizeImage(out graph, out input, out output, destinationDataType); // Execute that graph to normalize this one image using (var session = new TFSession(graph)) { var normalized = session.Run( inputs: new[] { input }, inputValues: new[] { tensor }, outputs: new[] { output }); return(normalized[0]); } }
internal static PrimitiveType Tf2MlNetType(TFDataType type) { switch (type) { case TFDataType.Float: return(NumberType.R4); case TFDataType.Double: return(NumberType.R8); case TFDataType.UInt32: return(NumberType.U4); case TFDataType.UInt64: return(NumberType.U8); default: throw new NotSupportedException("TensorFlow type not supported."); } }
static Type TypeFromTensorType(TFDataType type) { switch (type) { case TFDataType.Float: return(typeof(float)); case TFDataType.Double: return(typeof(double)); case TFDataType.Int32: return(typeof(int)); case TFDataType.UInt8: return(typeof(byte)); case TFDataType.Int16: return(typeof(short)); case TFDataType.Int8: return(typeof(sbyte)); case TFDataType.String: return(typeof(TFString)); case TFDataType.Int64: return(typeof(long)); case TFDataType.Bool: return(typeof(bool)); case TFDataType.UInt16: return(typeof(ushort)); case TFDataType.Complex128: return(typeof(Complex)); default: return(null); } }
private unsafe TFTensor CreateTensorFromImageFileAlt(Mat inputFileName, TFDataType destinationDataType = TFDataType.Float) { Cv2.Resize(inputFileName, inputFileName, new OpenCvSharp.Size(64, 64)); // 일반 graph일 때 var array = new byte[inputFileName.Width * inputFileName.Height * inputFileName.ElemSize()]; // 임시 array 생성 Marshal.Copy(inputFileName.Data, array, 0, array.Length); // MS에서 제공하는 COPY Method var matrix = new byte[1, inputFileName.Rows, inputFileName.Width, 3]; for (int i = 0; i < inputFileName.Rows; i++) { for (int j = 0; j < inputFileName.Cols; j++) { // 혹시라도 안되면 byte의 channel에 주목해보기!!! 난 bgr2rgb도 따로 안해서 둘다 시험해보기. matrix[0, i, j, 0] = array[i * inputFileName.Step() + j * 3 + 0]; // 행-렬이다 여기서도. 즉 y,x이다. matrix[0, i, j, 1] = array[i * inputFileName.Step() + j * 3 + 1]; matrix[0, i, j, 2] = array[i * inputFileName.Step() + j * 3 + 2]; // c++에서 복사해보고 제대로 복사되나 보고 } } UInt16[,,,] float_array = new UInt16[1, inputFileName.Rows, inputFileName.Cols, 3]; for (int i = 0; i < inputFileName.Rows; i++) { for (int j = 0; j < inputFileName.Cols; j++) { // 안된다면 byte에 // 혹시라도 안되면 byte의 channel에 주목해보기!!! 난 bgr2rgb도 따로 안해서 둘다 시험해보기. float_array[0, i, j, 0] = (UInt16)(matrix[0, i, j, 0]); float_array[0, i, j, 1] = (UInt16)(matrix[0, i, j, 1]); float_array[0, i, j, 2] = (UInt16)(matrix[0, i, j, 2]); // c++에서 복사해보고 제대로 복사되나 보고 } } //Buffer.BlockCopy(array, 0, float_array, 0, matrix.Length); TFTensor tensor = float_array; // 그대로 주게되면 제대로 들어가는지도 보고. return(tensor); }
public static TFTensor CreateTensorFromImageFile(byte[] contents, TFDataType destinationDataType = TFDataType.Float) { var tensor = TFTensor.CreateString(contents); TFOutput input, output; // Construct a graph to normalize the image using (var graph = ConstructGraphToNormalizeImage(out input, out output, destinationDataType)) { // Execute that graph to normalize this one image using (var session = new TFSession(graph)) { var normalized = session.Run( inputs: new[] { input }, inputValues: new[] { tensor }, outputs: new[] { output }); return(normalized[0]); } } }
/// <summary> /// Creates a sequence of numbers. /// </summary> /// <remarks> /// Creates a sequence of numbers that begins at `start` and extends by increments of `delta` up to but not including /// `limit`. The dtype of the resulting tensor is inferred from the inputs unless it is provided explicitly. /// </remarks> /// <param name="start">A 0 - D `Tensor` (scalar).Acts as first entry in the range if `limit` is not None; otherwise, acts as range limit and first entry defaults to 0.</param> /// <param name="limit">A 0 - D `Tensor` (scalar).Upper limit of sequence, exclusive. If None, defaults to the value of `start` while the first entry of the range defaults to 0.</param> /// <param name="delta">A 0 - D `Tensor` (scalar).Number that increments `start`. Defaults to 1.</param> /// <param name="dataType">The type of the elements of the resulting tensor.</param> /// <param name="operName">A name for the operation.Defaults to "range".</param> public TFOutput Range(TFOutput start, TFOutput?limit = null, TFOutput?delta = null, TFDataType?dataType = null, string operName = "range") { // https://github.com/tensorflow/tensorflow/blob/r1.2/tensorflow/python/ops/math_ops.py#L1156 if (limit == null) { limit = start; start = Cast(Const(new TFTensor(0.0)), start.OutputType); // TODO: Maybe add dataType as convenience in Const? } if (delta == null) { delta = Cast(Const(new TFTensor(1.0)), start.OutputType); } using (var newScope = WithScope(MakeName("Range", operName))) { // infer dtype if not explicitly provided if (dataType == null) { var dtype_hierarchy = new[] { TFDataType.Int32, TFDataType.Int64, TFDataType.Float, TFDataType.Double }; if (!dtype_hierarchy.Contains(start.OutputType) || !dtype_hierarchy.Contains(limit.Value.OutputType) || !dtype_hierarchy.Contains(delta.Value.OutputType)) { throw new ArgumentException("Unexpected type"); } TFDataType[] dtypes = new[] { start.OutputType, limit.Value.OutputType, delta.Value.OutputType }; int imax = dtypes.Select(x => Array.IndexOf(dtype_hierarchy, x)).Max(); TFDataType inferred_dtype = dtype_hierarchy[imax]; start = Cast(start, inferred_dtype); limit = Cast(limit.Value, inferred_dtype); delta = Cast(delta.Value, inferred_dtype); } return(Range(start, limit.Value, delta.Value, operName: operName)); } }
/// <summary> /// Create a constant tensor based on a shape /// Used by Zeros and Ones /// </summary> /// <param name="value">Value for tensor</param> /// <param name="tfshape">Shape of the tensor</param> /// <param name="dtype">Optional Type of the Zero value. Default: Double</param> /// <param name="operName">Operation name, optional.</param> /// <returns></returns> /// see https://github.com/tensorflow/tensorflow/blob/r1.1/tensorflow/python/framework/constant_op.py public TFOutput Constant(object value, TFShape tfshape, TFDataType dtype = TFDataType.Double, string operName = null) { if (tfshape.NumDimensions <= 0) { TFTensor tensor = TFTensor.Create1DTensor(dtype, value); return(Const(tensor, tensor.TensorType, operName)); } //convert the .net type to relevant tensorflow type object dtvalue = TFTensor.FetchSimple(dtype, value); var shape = tfshape.ToArray(); var idx = new int [shape.Length]; for (int i = 0; i < shape.Length; i++) { if (shape [i] > Int32.MaxValue) { throw new ArgumentOutOfRangeException("Shape can not be longer than 32 bits"); } } Array data = null; if (tfshape.IsLongArray) { data = Array.CreateInstance(dtvalue.GetType(), tfshape.ToArray()); } else { data = Array.CreateInstance(dtvalue.GetType(), tfshape.ToIntArray()); } TFTensor.Set(data, dtype, shape, idx, 0, value); TFTensor tensor_value = new TFTensor(data); return(Const(tensor_value, tensor_value.TensorType, operName)); }
// Convert the image in filename to a Tensor suitable as input to the Inception model. public static TFTensor CreateTensorFromImageFile(string file, TFDataType destinationDataType = TFDataType.Float) { contents = File.ReadAllBytes(file); System.Buffer.BlockCopy(contents, 99712, crop, 0, 336 * 336); // DecodeJpeg uses a scalar String-valued tensor as input. var tensor = TFTensor.CreateString(contents); TFOutput input, output; // Construct a graph to normalize the image using (var graph = ConstructGraphToNormalizeImage(out input, out output, destinationDataType)){ // Execute that graph to normalize this one image using (var session = new TFSession(graph)) { var normalized = session.Run( inputs: new [] { input }, inputValues: new [] { tensor }, outputs: new [] { output }); return(normalized [0]); } } }
// Additional pointers for using TensorFlow & CustomVision together // Python: https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/label_image/label_image.py // C++: https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/label_image/main.cc // Java: https://github.com/Azure-Samples/cognitive-services-android-customvision-sample/blob/master/app/src/main/java/demo/tensorflow/org/customvision_sample/MSCognitiveServicesClassifier.java private static (TFGraph, TFOutput, TFOutput) ConstructGraphToNormalizeImage(TFDataType destinationDataType = TFDataType.Float) { const int W = 227; const int H = 227; //const float Scale = 1; // Depending on your CustomVision.ai Domain - set appropriate Mean Values (RGB) // https://github.com/Azure-Samples/cognitive-services-android-customvision-sample for RGB values (in BGR order) //var bgrValues = new TFTensor(new float[] { 104.0f, 117.0f, 123.0f }); // General (Compact) & Landmark (Compact) //var bgrValues = new TFTensor(0f); // Retail (Compact) var graph = new TFGraph(); var input = graph.Placeholder(TFDataType.String); var caster = graph.Cast(graph.DecodeJpeg(contents: input, channels: 3), DstT: TFDataType.Float); var dims_expander = graph.ExpandDims(caster, graph.Const(0, "batch")); var resized = graph.ResizeBilinear(dims_expander, graph.Const(new int[] { H, W }, "size")); //var resized_mean = graph.Sub(resized, graph.Const(bgrValues, "mean")); //var normalised = graph.Div(resized_mean, graph.Const(Scale)); var output = resized; return(graph, input, output); }
// The inception model takes as input the image described by a Tensor in a very // specific normalized format (a particular image size, shape of the input tensor, // normalized pixel values etc.). // // This function constructs a graph of TensorFlow operations which takes as // input a JPEG-encoded string and returns a tensor suitable as input to the // inception model. private (TFGraph graph, TFOutput input, TFOutput output) PreprocessNeuralNetwork(int width, int height) { // Custom model has been processed using Keras // which uses its own algorithm for normalizing images // RGB values are normalized between -1 and 1 // image shape can be customized in keras, // so width and height are converted to method arguments const TFDataType destinationDataType = TFDataType.Float; TFGraph graph = new TFGraph(); TFOutput input = graph.Placeholder(TFDataType.String); var decodeJpeg = graph.DecodeJpeg(contents: input, channels: 3); var castToFloat = graph.Cast(decodeJpeg, DstT: TFDataType.Float); var expandDims = graph.ExpandDims(castToFloat, dim: graph.Const(0, "make_batch")); // shape: [1, height, width, channels] var resize = graph.ResizeBilinear(expandDims, size: graph.Const(new int[] { width, height }, "size")); var divide = graph.Div(resize, y: graph.Const(255f, destinationDataType, "divide")); var substract = graph.Sub(divide, y: graph.Const(.5f, destinationDataType, "sub")); var multiply = graph.Mul(substract, y: graph.Const(2f, destinationDataType, "multiply")); var castToDestinationDataType = graph.Cast(multiply, destinationDataType); return(graph, input, castToDestinationDataType); }
public static TFTensor CreateTensorFromMemoryJpg(Byte[] jpeg, TFDataType destinationDataType = TFDataType.Float) { // DecodeJpeg uses a scalar String-valued tensor as input. var tensor = TFTensor.CreateString(jpeg); TFOutput input; TFOutput output; // Construct a graph to normalize the image using (var graph = ConstructGraphToNormalizeImage2(out input, out output, destinationDataType)) { // Execute that graph to normalize this one image using (var session = new TFSession(graph)) { var normalized = session.Run( inputs: new[] { input }, inputValues: new[] { tensor }, outputs: new[] { output }); return(normalized[0]); } } }
private static TFTensor CreateTensorFromBitmap(Image bitmap, TFDataType destinationDataType = TFDataType.Float) { //var contents = File.ReadAllBytes(file); var contents = ImageUtils.ImageToByte(bitmap); // DecodeJpeg uses a scalar String-valued tensor as input. var tensor = TFTensor.CreateString(contents); // Construct a graph to normalize the image using (var graph = ConstructGraphToNormalizeImage(out TFOutput input, out TFOutput output, destinationDataType)) { // Execute that graph to normalize this one image using (var session = new TFSession(graph)) { var normalized = session.Run( inputs: new[] { input }, inputValues: new[] { tensor }, outputs: new[] { output }); return(normalized[0]); } } }
public static TFTensor CreateTensorFromBGR(Byte[] rgb, TFDataType destinationDataType = TFDataType.Float) { // DecodeJpeg uses a scalar String-valued tensor as input. //var tensor = TFTensor.CreateString(bgr); /* * byte[] floatValues = new byte[640 * 480 * 3]; * int j = 0; * for (int i = 0; i < rgb.Length/4; i++) * { * floatValues[j * 3 + 0] = (rgb[i * 4 + 0]) ; * floatValues[j * 3 + 1] = (rgb[i * 4 + 1]) ; * floatValues[j * 3 + 2] = (rgb[i * 4 + 2]) ; * j++; * }*/ TFShape shape = new TFShape(480, 640, 3); var tensor = TFTensor.FromBuffer(shape, rgb, 0, rgb.Length); TFOutput input; TFOutput output; // Construct a graph to normalize the image using (var graph = ConstructGraphToNormalizeImage(out input, out output, destinationDataType)) { // Execute that graph to normalize this one image using (var session = new TFSession(graph)) { var normalized = session.Run( inputs: new[] { input }, inputValues: new[] { tensor }, outputs: new[] { output }); return(normalized[0]); } } }