Xamarin Android:TFLite物体检测的输入输出是什么?

6qfn3psc  于 2022-09-21  发布在  Android
关注(0)|答案(2)|浏览(158)

我正在试着完成一次物体探测。我正在使用Xamarin FormsXamarin.Tensorflow.Lite。首先,我加载我的模型:

AssetFileDescriptor fileDescriptor = assets.OpenFd("model.tflite");
FileInputStream inputStream = new FileInputStream(fileDescriptor.FileDescriptor);
FileChannel fileChannel = inputStream.Channel;
long startOffset = fileDescriptor.StartOffset;
long declaredLength = fileDescriptor.DeclaredLength;
var asd = fileChannel.Map(FileChannel.MapMode.ReadOnly, startOffset, declaredLength);
var model = new Xamarin.TensorFlow.Lite.Interpreter(asd);

我知道我应该调用model.Run(),但我不太知道应该给它提供什么参数。我想给它一个图像,然后把数据读回来?如何做到这一点?

ylamdve6

ylamdve61#

首先,我们应该将图像读到bitmap

var bitmap = await BitmapFactory.DecodeStreamAsync(image.GetStreamWithImageRotatedForExternalStorage());

然后将bitmap转换为float[],如下所示。

static float[] GetBitmapPixels(Bitmap bitmap)
    {
        var floatValues = new float[_inputSize * _inputSize * 3];

        using (var scaledBitmap = Bitmap.CreateScaledBitmap(bitmap, _inputSize, _inputSize, false))
        {
            using (var resizedBitmap = scaledBitmap.Copy(Bitmap.Config.Argb8888, false))
            {
                var intValues = new int[_inputSize * _inputSize];
                resizedBitmap.GetPixels(intValues, 0, resizedBitmap.Width, 0, 0, resizedBitmap.Width, resizedBitmap.Height);

                for (int i = 0; i < intValues.Length; ++i)
                {
                    var val = intValues[i];

                    floatValues[i * 3 + 0] = ((val & 0xFF) - 104);
                    floatValues[i * 3 + 1] = (((val >> 8) & 0xFF) - 117);
                    floatValues[i * 3 + 2] = (((val >> 16) & 0xFF) - 123);
                }

                resizedBitmap.Recycle();
            }

            scaledBitmap.Recycle();
        }

        return floatValues;
    }

最后,我们可以回读数据。

public string RecognizeImage(Bitmap bitmap)
    {
        var outputNames = new[] { OutputName };
        var floatValues = GetBitmapPixels(bitmap);
        var outputs = new float[labels.Count];

        inferenceInterface.Feed(InputName, floatValues, 1, _inputSize, _inputSize, 3);
        inferenceInterface.Run(outputNames);
        inferenceInterface.Fetch(OutputName, outputs);

        var results = new List<Tuple<float, string>>();
        for (var i = 0; i < outputs.Length; ++i)
            results.Add(Tuple.Create(outputs[i], labels[i]));

        return results.OrderByDescending(t => t.Item1).First().Item2;
    }

这里有一个关于它的博客。https://devblogs.microsoft.com/xamarin/android-apps-tensorflow/

这是演示。https://github.com/jimbobbennett/blog-samples/tree/master/UsingTensorFlowAndAzureInAndroid

92dk7w1h

92dk7w1h2#

我也很难弄清楚对象检测模型的输出(所有微软的博客都是关于图像分类模型的)。无论语言如何,TensorFlow Lite的输入和输出都是相同的(请参阅Tf文档),但在Xamarin应用程序中执行此操作所需的所有类型转换都很困难。

当然,输出取决于您的模型,从本质上讲,您希望使用RunForMultipleInputsOutlets()并创建一个输出对象,该对象是匹配输出Tensor的数组Map。输入与图像分类相同,但放在数组中。这是一个excerpt from a working app

outputLocations = CreateJagged(1, NUM_DETECTIONS, 4);
            outputClasses = CreateJagged(1, NUM_DETECTIONS);
            outputScores = CreateJagged(1, NUM_DETECTIONS);
            numDetections = new float[1];

            var mOutputLocations= OutputLocations;
            var mOutputClasses= OutputClasses;
            var mOutputScores= OutputScores;

            Java.Lang.Object[] inputArray = { imgData };

            var outputMap = new Dictionary<Java.Lang.Integer, Java.Lang.Object>();
            outputMap.Add(new Java.Lang.Integer(0), mOutputLocations);
            outputMap.Add(new Java.Lang.Integer(1), mOutputClasses);
            outputMap.Add(new Java.Lang.Integer(2), mOutputScores);
            outputMap.Add(new Java.Lang.Integer(3), numDetections);

            tfLite.RunForMultipleInputsOutputs(inputArray, outputMap);

看看这个GitHub问题,我有更多的示例代码,我让它与从Azure Custom Vision导出的tflite模型一起工作:https://github.com/xamarin/GooglePlayServicesComponents/issues/668,我写了一篇关于实现它的博客:https://intellitect.com/blog/object-detection-tensorflow-lite/

相关问题