You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Bitmap传入TensorFlow Mobile模型?推理异常求助

Troubleshooting Your TensorFlow Mobile Prediction Mismatch

Let's break down why your Android app is giving wrong predictions—since your model works perfectly on desktop, the issue almost certainly lies in mismatched image preprocessing between your training/desktop inference and Android code. Here are the key areas to check and fix:

1. Verify Input Channel Order & Dimension Layout

TensorFlow models can use two common dimension formats:

  • NHWC (batch, height, width, channel): This is Keras/TensorFlow's default for most pre-trained models like InceptionV3
  • NCHW (batch, channel, height, width): Less common in Keras, but possible if you modified the model or conversion process

How to Check:

Use TensorFlow's saved_model_cli tool on your PB model to confirm input shape:

saved_model_cli show --dir path/to/your/pb_model --all

Fix If NCHW is Required:

Your current code assumes NHWC, but if the model expects NCHW, you need to reorder your pixel array to group all R, G, B pixels together:

public float[] normalizeBitmap(Bitmap source,int size,float mean,float std){
    float[] output = new float[3 * size * size];
    int[] intValues = new int[source.getHeight() * source.getWidth()];
    source.getPixels(intValues, 0, source.getWidth(), 0, 0, source.getWidth(), source.getHeight());
    int pixelCount = size * size;
    
    for (int i = 0; i < intValues.length; ++i) {
        final int val = intValues[i];
        // Group all R pixels first, then G, then B
        output[i] = (((val >> 16) & 0xFF) - mean)/std;          // R channel
        output[i + pixelCount] = (((val >> 8) & 0xFF) - mean)/std; // G channel
        output[i + 2 * pixelCount] = ((val & 0xFF) - mean)/std;     // B channel
    }
    return output;
}

And update the feed call to match the NCHW shape:

inferenceInterface.feed(INPUT_NODE, imageValuesFloat, 1, 3, 128, 128);

2. Match Training-Time Image Resizing/Cropping Logic

If your training data used center-cropping instead of direct stretching, your Android code must replicate this exactly. Stretching images to 128x128 distorts proportions and will confuse the model.

Add Cropping Logic to Android:

public Bitmap cropAndResizeBitmap(Bitmap source, int targetSize) {
    int width = source.getWidth();
    int height = source.getHeight();
    int cropSize = Math.min(width, height);
    
    // Crop the center square of the image
    int xOffset = (width - cropSize) / 2;
    int yOffset = (height - cropSize) / 2;
    Bitmap croppedBitmap = Bitmap.createBitmap(source, xOffset, yOffset, cropSize, cropSize);
    
    // Resize to target dimension
    return Bitmap.createScaledBitmap(croppedBitmap, targetSize, targetSize, true);
}

Use this function to generate your resized_image instead of direct scaling.

3. Validate Normalization Accuracy

Double-check that your Android normalization matches exactly what you did during training. Print pixel values from both Python and Android to compare:

Python Test Code:

from PIL import Image
import numpy as np

img = Image.open("A.png").resize((128,128))
img_array = np.array(img)
normalized = (img_array - 127.5) / 1.0
print("Python normalized pixel (0,0):", normalized[0][0])

Android Debug Code:

float[] normalized = normalizeBitmap(resized_image, 128, 127.5f, 1.0f);
Log.d("Preprocessing", "Android normalized pixel (0,0): " + normalized[0] + ", " + normalized[1] + ", " + normalized[2]);

If values don't match, check if your Bitmap is using a different color format (e.g., grayscale instead of RGB) or if you accidentally swapped R/B channels.

4. Fix Output Node Execution

Ensure you're passing an array of output nodes to the run method—single strings can cause silent failures:

String[] OUTPUT_NODES = new String[]{OUTPUT_NODE};
inferenceInterface.run(OUTPUT_NODES);

5. Confirm Model Load Success

Add logging to make sure your model loads without errors:

try {
    inferenceInterface = new TensorFlowInferenceInterface(getAssets(), "your_model.pb");
    Log.d("TFModel", "Model loaded successfully");
} catch (IOException e) {
    Log.e("TFModel", "Failed to load model", e);
}

Most Likely Culprits:

  • Mismatched dimension layout (NHWC vs NCHW)
  • Inconsistent image cropping/resizing between training and Android
  • Accidental channel swapping (R/B) in preprocessing

内容的提问来源于stack exchange,提问作者Yusuf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:06:13