Я знаю, что прошло много времени с тех пор, как вы задали этот вопрос, но, возможно, мой ответ может быть кому-то полезен.Я также пытаюсь использовать Xamarin с tflite для запуска простого CNN.Вот мой код:
private MappedByteBuffer LoadModelFile()
{
var assets = Application.Context.Assets;
AssetFileDescriptor fileDescriptor = assets.OpenFd("seed_model_no_qt.tflite");
FileInputStream inputStream = new FileInputStream(fileDescriptor.FileDescriptor);
FileChannel fileChannel = inputStream.Channel;
long startOffset = fileDescriptor.StartOffset;
long declaredLength = fileDescriptor.DeclaredLength;
return fileChannel.Map(FileChannel.MapMode.ReadOnly, startOffset, declaredLength);
}
private string Classify(MediaFile mediaFile)
{
var assets = Application.Context.Assets;
Bitmap bp = BitmapFactory.DecodeStream(mediaFile.GetStream());
var resizedBitmap = Bitmap.CreateScaledBitmap(bp, 1280, 1280, false).Copy(Bitmap.Config.Argb8888, false);
var bufint = new int[1280 * 1280];
resizedBitmap.GetPixels(bufint, 0, 1280, 0, 0, 1280, 1280);
int pixels = 0;
var input_buffer = new byte[4 * 1280 * 1280 * 3];
for(int i = 0; i < 1280; i++)
{
for(int k = 0; k < 1280; k++)
{
int val = bufint[pixels++];
Array.Copy(BitConverter.GetBytes(((val >> 16) & 0xFF) * (1f / 255f)), 0, input_buffer, (i * 1280 + k) * 12, 4);
Array.Copy(BitConverter.GetBytes(((val >> 8) & 0xFF) * (1f / 255f)), 0, input_buffer, (i * 1280 + k) * 12 + 4, 4);
Array.Copy(BitConverter.GetBytes((val & 0xFF) * (1f / 255f)), 0, input_buffer, (i * 1280 + k) * 12 + 8, 4);
}
}
var bytebuffer = Java.Nio.ByteBuffer.Wrap(input_buffer);
var output = Java.Nio.ByteBuffer.AllocateDirect(4*160*160);
interpreter.Run(bytebuffer, output);
var buffer = new byte[4 * 160 * 160];
Marshal.Copy(output.GetDirectBufferAddress(), buffer, 0, 4 * 160 * 160);
float sum = 0.0f;
for(int i = 0; i < 160*160; i++)
{
sum += BitConverter.ToSingle(buffer, i * 4);
}
return "Count : " + ((int)(sum/255)).ToString();
}
Я снова использовал вашу функцию LoadModelFile () как есть.Код берет изображение из mediaFile (поступающего с камеры телефона), затем изменяет его размер до изображения 1280x1280 rgb перед передачей его в CNN в виде массива значений float32.Ваша проблема с плавающей точкой [] [] [] [] для Java.Lang.Object возникла из-за метода interpreter.Run (), ожидающего объект Java.Некоторые люди онлайн решают эту проблему, передавая в качестве параметра Java.Nio.ByteBuffer вместо массива.Это подразумевает некоторые побитовые манипуляции, но метод Run принимает объект ByteBuffer.При заполнении ByteBuffer я советую вам не использовать его методы, такие как PutFloat (), но заполнить буфер byte [], а затем использовать метод Java.Nio.ByteBuffer.Wrap (), как я это сделал.Использование методов ByteBuffer в моем случае означало большие проблемы с производительностью.То же самое происходит при манипулировании выводом моего CNN (тепловая карта 160x160 значений float32).Использование метода ByteBuffer.Get () для доступа к значениям было очень медленным.Вместо этого используйте Marshal.Copy, чтобы сохранить значения в байтовом массиве, а затем вернуть значения с плавающей запятой с помощью BitConverter.ToSingle.