Модель Tflite дает различную производительность в Android (мл зрения) и Python - PullRequest
2 голосов
/ 13 апреля 2020

Я использую ML Vision api для создания вложений из модели Fa ceNet, а затем сравниваю косинусное расстояние между двумя вложениями. Вывод Android версии и Python сильно отличается. Версия Python работает лучше, чем android. В чем может быть проблема? Я использую модель Fa ceNet в обеих.

Я использую комплект ML для вывода https://firebase.google.com/docs/ml-kit/android/use-custom-models

Я думаю, что это может быть вызвано java считывает изображения, поскольку массив изображений, созданный в android, отличается от массива того же изображения в python.

1 Ответ

1 голос
/ 14 апреля 2020

Так что я застрял в этой проблеме, поскольку я следовал документации Google в Документы ML vision Где изображение было преобразовано в массив с плавающей точкой перед подачей его в классификатор, Это выглядит так:

val bitmap = Bitmap.createScaledBitmap(yourInputImage, 224, 224, true)

val batchNum = 0
val input = Array(1) { Array(224) { Array(224) { FloatArray(3) } } }
for (x in 0..223) {
    for (y in 0..223) {
        val pixel = bitmap.getPixel(x, y)
        // Normalize channel values to [-1.0, 1.0]. This requirement varies by
        // model. For example, some models might require values to be normalized
        // to the range [0.0, 1.0] instead.
        input[batchNum][x][y][0] = (Color.red(pixel) - 127) / 255.0f
        input[batchNum][x][y][1] = (Color.green(pixel) - 127) / 255.0f
        input[batchNum][x][y][2] = (Color.blue(pixel) - 127) / 255.0f
    }
}

Затем я проанализировал каждый шаг один за другим и обнаружил, что способ выборки пикселей неправильный и полностью отличается от способа, которым python делает все это.

Затем я нашел такой способ сделать это из этого источника Я изменил эту функцию с моей:

    private fun convertBitmapToByteBuffer(bitmap: Bitmap): ByteBuffer {
        val imgData = ByteBuffer.allocateDirect(4 * INPUT_SIZE * INPUT_SIZE * PIXEL_SIZE)
        imgData.order(ByteOrder.nativeOrder())
        val intValues = IntArray(INPUT_SIZE * INPUT_SIZE)


        imgData.rewind()
        bitmap.getPixels(intValues, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
        // Convert the image to floating point.
        var pixel = 0
        for (i in 0 until INPUT_SIZE) {
            for (j in 0 until INPUT_SIZE) {
                val `val` = intValues[pixel++]
                imgData.putFloat(((`val`.shr(16) and 0xFF) - IMAGE_MEAN)/IMAGE_STD)
                imgData.putFloat(((`val`.shr(8) and 0xFF)- IMAGE_MEAN)/ IMAGE_STD)
                imgData.putFloat(((`val` and 0xFF) - IMAGE_MEAN)/IMAGE_STD)
            }
        }
        return imgData;
   }

И это сработало!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...