T IModelPrediction.FetchOutput <T, U>(U inputTex)
    {
        //////// TODO : shape should be passed as argument to Transform Input
        var shape = new TFShape(1, inputWidth, inputHeight, 3);
        ////////

        var scaled  = TextureTools.scaled(inputTex as Texture2D, 224, 224, FilterMode.Trilinear);
        var rotated = TextureTools.RotateImageMatrix(scaled.GetPixels32(), scaled.width, scaled.height, 180);

        var input = graph[inputName][0];

        var inputTensor = TFSharpUtils.TransformInput(rotated, 224, 224, inputMean, inputStd);

        var runner = session.GetRunner();

        runner.AddInput(input, inputTensor).Fetch(graph[outputName][0]);

        var output          = runner.Run()[0];
        var feautures       = output.GetValue() as float[, , , ];
        var jagged_features = ((float[][][][])output.GetValue(jagged: true));

        var flat3D = jagged_features.SelectMany(a => a).ToArray();
        var flat2D = flat3D.SelectMany(a => a).ToArray();
        var flat1D = flat2D.SelectMany(a => a).ToArray();

        List <float> featureVector = new List <float>(flat1D);

        inputTensor.Dispose();
        output.Dispose();

        return(featureVector as T);
    }
    /// <summary>
    /// This is the model inference method. You specify an input and the relevant output
    /// of the model is extracted.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="U"></typeparam>
    /// <param name="inputTex"></param>
    /// <returns></returns>
    public T FetchOutput <T, U>(U inputTex) where T : class, IList where U : class
    {
        //////// TODO : shape should be passed as argument to Transform Input
        //var shape = new TFShape(1, inputWidth, inputHeight, 3);
        ////////

        //var scaled = TextureTools.scaled(inputTex as Texture2D, 224, 224, FilterMode.Trilinear);
        var scaled = GenericUtils.Resize(inputTex as Texture2D, 224, 224);
        //var rotated = TextureTools.RotateImageMatrix(scaled.GetPixels32(), scaled.width, scaled.height, 180);

        var input = graph[inputName][0];

        //var inputTensor = TFSharpUtils.TransformInput(rotated, 224, 224, inputMean, inputStd);
        var inputTensor = TFSharpUtils.TransformInput(scaled.GetPixels32(), 224, 224, inputMean, inputStd);

        var runner = session.GetRunner();

        runner.AddInput(input, inputTensor).Fetch(graph[outputName][0]);

        var output  = runner.Run()[0];
        var outputs = output.GetValue() as float[, ];

        inputTensor.Dispose();
        output.Dispose();
        UnityEngine.Object.DestroyImmediate(scaled);

        var list = new List <KeyValuePair <string, float> >();

        for (int i = 0; i < labels.Length; i++)
        {
            var confidence = outputs[0, i];
            if (confidence < 0.01f)
            {
                continue;
            }

            list.Add(new KeyValuePair <string, float>(labels[i], confidence));
        }

        var results = list.OrderByDescending(i => i.Value).Take(numOfResults).ToList();

        return(results as T);
    }