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

Android TensorFlow:如何避免图像风格化时自动缩放图像

解决TensorFlow图像风格化中的自动缩放问题

我之前也踩过这个坑,用TensorFlow做风格化时,一改默认的256尺寸就会出现图像被自动缩放的情况,核心问题其实出在输入张量的形状配置、预处理逻辑以及模型本身的尺寸限制上,下面给你一步步梳理解决方案:

1. 初始化时明确指定输入张量的动态形状

很多预训练风格化模型默认是固定256x256的输入尺寸,如果你只改了INPUT_SIZE但没同步更新输入张量的形状,模型会自动把输入缩放到它预期的固定尺寸。你需要在初始化TensorFlowInferenceInterface后,手动设置输入张量的形状为原图的宽高:

private TensorFlowInferenceInterface inferenceInterface;
private void applyStyle(Bitmap originalBitmap, AssetManager assetManager, String MODEL_PATH) {
    int inputWidth = originalBitmap.getWidth();
    int inputHeight = originalBitmap.getHeight();
    
    // 初始化推理接口
    inferenceInterface = new TensorFlowInferenceInterface(assetManager, MODEL_PATH);
    // 关键步骤:替换默认固定形状,设置为原图的动态尺寸
    inferenceInterface.setInputShape("input", new int[]{1, inputHeight, inputWidth, 3});
    
    // 后续预处理、推理逻辑...
}

2. 预处理阶段完全避免缩放操作

很多示例代码里会强制把图像缩放到固定尺寸再传入模型,这一步一定要删掉,直接用原图的像素数据做预处理:

// 从原图提取像素数据,全程不做缩放
int[] intValues = new int[inputWidth * inputHeight];
originalBitmap.getPixels(intValues, 0, inputWidth, 0, 0, inputWidth, inputHeight);

// 转换为模型需要的归一化float格式
float[] floatValues = new float[inputWidth * inputHeight * 3];
for (int i = 0; i < inputWidth * inputHeight; ++i) {
    final int val = intValues[i];
    floatValues[i * 3] = ((val >> 16) & 0xFF) / 255.0f;
    floatValues[i * 3 + 1] = ((val >> 8) & 0xFF) / 255.0f;
    floatValues[i * 3 + 2] = (val & 0xFF) / 255.0f;
}

// 传入预处理后的数据,严格匹配之前设置的输入形状
inferenceInterface.feed("input", floatValues, 1, inputHeight, inputWidth, 3);

3. 推理后按原图尺寸生成输出图像

推理完成后,要确保按原图的宽高解析输出张量的数据,生成对应分辨率的风格化图像:

// 执行风格化推理
inferenceInterface.run(new String[]{"output"}, false);

// 获取和输入尺寸完全一致的输出数据
float[] outputValues = new float[inputWidth * inputHeight * 3];
inferenceInterface.fetch("output", outputValues);

// 将输出数据转换为Bitmap格式
int[] outputIntValues = new int[inputWidth * inputHeight];
for (int i = 0; i < inputWidth * inputHeight; ++i) {
    outputIntValues[i] =
        0xFF000000
            | (((int) (outputValues[i * 3] * 255)) << 16)
            | (((int) (outputValues[i * 3 + 1] * 255)) << 8)
            | ((int) (outputValues[i * 3 + 2] * 255));
}

// 生成和原图分辨率完全相同的风格化图像
Bitmap styledBitmap = Bitmap.createBitmap(inputWidth, inputHeight, Bitmap.Config.ARGB_8888);
styledBitmap.setPixels(outputIntValues, 0, inputWidth, 0, 0, inputWidth, inputHeight);

4. 模型层面的额外排查

如果上面的步骤都做了还是有问题,那大概率是你用的预训练模型本身是固定输入尺寸的。这种情况下,你需要:

  • 重新训练模型,将输入层的shape设置为[None, None, None, 3](支持任意尺寸的输入)
  • 或者换用支持动态输入的风格化模型(比如基于MobileNet的轻量风格化模型)

小提示

处理大尺寸图像(比如1280x960)时,要注意内存占用问题,可以考虑用Bitmap.Config.RGB_565来减少内存消耗,或者在设备内存不足时做适当降采样(这是妥协方案,优先保证原图尺寸)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:59:23