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
相关产品推荐
相关产品推荐

