/// <summary> /// Processes the input image to determine the classification /// </summary> /// <param name="imageContainer">The image to process</param> /// <returns>If two dimensional, it is a grid of the image and the /// classification of each cell within it. If one dimensional, it is list /// of classifications for the whole image. </returns> public Classification[,] ProcessImage(ImageContainer imageContainer) { // Convert the image to a shape that openCV can work with using var f = imageContainer.image.Reshape(1, 1); // flatten to a single row f.ConvertTo(f, Emgu.CV.CvEnum.DepthType.Cv32F); // Apply the decision tree to the input image var g = decisionTree.Predict(f, output); var d = (float[, ])output.GetData(); outputGrid[0, 0].Probability = d[0, 0]; // Return the classification return(outputGrid); }
/// <summary> /// Processes the input image to determine the classification /// </summary> /// <param name="imageContainer">The image to process</param> /// <returns>If two dimensional, it is a grid of the image and the /// classification of each cell within it. If one dimensional, it is list /// of classifications for the whole image. </returns> public Classification[,] ProcessImage(ImageContainer imageContainer) { // Get a version of the image that is the size and depth that we work with // and then pass the image to the input tensor for the model // We will key off of the type of the tensor if (inputType == DataType.Float32) { // Get the image of the size and types, in TFLite's RGB var image = imageContainer.Image(inputSize, DepthType.Cv32F, true); // Rescale, and offset the image using Mat matF = new Mat( size: inputSize, type: Emgu.CV.CvEnum.DepthType.Cv32F, channels: 3, data: InputTensor.DataPointer, step: sizeof(float) * 3 * inputSize.Width); // This is to put the pixels in the right type and range; It scales // each and then offsets them, usually putting them into the range // 0..1 or -1..1 image.ConvertTo(matF, Emgu.CV.CvEnum.DepthType.Cv32F, inputScale, inputOfs); } else if (inputType == DataType.UInt8) { // Get the image of the size and types, in TFLite's RGB var image = imageContainer.Image(inputSize, DepthType.Cv8U, true); using Mat matB = new Mat( size: inputSize, type: Emgu.CV.CvEnum.DepthType.Cv8U, channels: 3, data: InputTensor.DataPointer, step: sizeof(byte) * 3 * inputSize.Width); image.CopyTo(matB); } // And have the model be interpreted var status = interpreter.Invoke(); if (status == Status.Error) { throw new Exception("TF lite invocation failed."); } // Form the output grid of the classification results var data = (float[])OutputTensor.Data; if (!isLocalization) { // Find the "best" classification for this cell // Sort the items from most to least Array.Sort(indices, (a, b) => { return(data[a] < data[b] ? 1 : data[a] > data[b] ? -1 : 0); }); // Keep the best item(s) var num = indices.Length < 5 ? 1 : 5; for (var idx = 0; idx < num; idx++) { // Set the classification and probability outputGrid[idx, 0].Label = labels[indices[idx]]; outputGrid[idx, 0].Probability = data [indices[idx]]; } } else { // The output is a grid, row, column order var idx = 0; for (var row = 0; row < numRows; row++) { for (var col = 0; col < numColumns; col++, idx++) { outputGrid[row, col].Label = labels[0]; outputGrid[row, col].Probability = data[idx]; } } } // Return the classification return(outputGrid); }