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

基于SNPE的Pix2Pix去雾APP推理输出图像错位问题问询

安卓Pix2Pix去雾APP图像错位问题排查

我正在开发一款基于Pix2Pix(类UNet)模型的安卓去雾APP,采用一加7手机摄像头采集图像,经去雾处理后在主界面展示结果,深度学习推理采用高通SNPE框架。目前遇到模型输出转Bitmap后图像错位的问题,初始错位效果如下:
misaligned pic


推理核心代码

final List<String> result = new LinkedList<>();

final FloatTensor tensor = mNeuralNetwork.createFloatTensor(
        mNeuralNetwork.getInputTensorsShapes().get(mInputLayer));

Log.e("[MODEL]", "create tensor");
Bitmap smImage = Bitmap.createScaledBitmap(mImage, 1080, 720, true);

final int[] dimensions = tensor.getShape();
final boolean isGrayScale = (dimensions[dimensions.length -1] == 1);
float[] rgbBitmapAsFloat;
if (!isGrayScale) {
    rgbBitmapAsFloat = loadRgbBitmapAsFloat(smImage);
} else {
    rgbBitmapAsFloat = loadGrayScaleBitmapAsFloat(smImage);
}
tensor.write(rgbBitmapAsFloat, 0, rgbBitmapAsFloat.length);

Log.e("[MODEL]", "create tensor done!");
final Map<String, FloatTensor> inputs = new HashMap<>();
inputs.put(mInputLayer, tensor);
Log.e("[MODEL]", "create input tensor done!");

final long javaExecuteStart = SystemClock.elapsedRealtime();
final Map<String, FloatTensor> outputs = mNeuralNetwork.execute(inputs);
Log.e("[MODEL]", "model execute!");
final long javaExecuteEnd = SystemClock.elapsedRealtime();
mJavaExecuteTime = javaExecuteEnd - javaExecuteStart;
FloatTensor outputTensor = new FloatTensor() {
    @Override
    public void write(float[] floats, int i, int i1, int... ints) {

    }

    @Override
    public void write(float v, int... ints) {

    }

    @Override
    public int read(float[] floats, int i, int i1, int... ints) {
        return 0;
    }

    @Override
    public float read(int... ints) {
        return 0;
    }

    @Override
    public void release() {

    }
};
for (Map.Entry<String, FloatTensor> output : outputs.entrySet()) {
    Log.e("[MODEL]", "output_layer: " + output.getKey());
    if (output.getKey().equals(mOutputLayer)) {
        outputTensor = output.getValue();
        Log.e("[MODEL]", "output_layer: " + output.getKey() + ", shape: " +
                String.valueOf(outputTensor.getShape()[0]) + " " +
                String.valueOf(outputTensor.getShape()[1]) + " " +
                String.valueOf(outputTensor.getShape()[2]) + " " +
                String.valueOf(outputTensor.getShape()[3]) + " " );
        }
    }
return outputTensor;

SNPE FloatTensor转Bitmap代码

final float[] pixelsBatched = new float[tensor.getSize()];
tensor.read(pixelsBatched, 0, tensor.getSize());
Log.i("[IMAGE]", "size: " + String.valueOf(tensor.getSize()));
int w = 1080;
int h = 720;
Bitmap img = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
for (int y = 0; y < h; y++) {
    for (int x = 0; x < w; x++) {
        float r = pixelsBatched[y * w * 3 + x * 3 + 0] * 255;
        float g = pixelsBatched[y * w * 3 + x * 3 + 1] * 255;
        float b = pixelsBatched[y * w * 3 + x * 3 + 2] * 255;
        int color = ((int)r << 16) | ((int)g << 8) | (int)b | 0xFF000000;
        img.setPixel(x, y, color);
    }
}

return img;

初步排查

直接返回输入张量转Bitmap显示正常,说明输入处理无问题,问题出在推理环节。模型用PyTorch训练,导出ONNX测试正常,经onnx-sim简化后转SNPE的DLC模型,ONNX网络结构如下:
ONNX网络结构


后续排查更新

更新1:调整通道读取逻辑

修改通道读取代码为:

int channelSize = w * h;
float r = pixelsBatched[y * w + x] * 255;
float g = pixelsBatched[y * w + x + channelSize] * 255;
float b = pixelsBatched[y * w + x + 2 * channelSize] * 255;

修改后图像效果:
调整通道后效果

更新2:SNPE工具查看结果

  • snpe-dlv-viewer结果:
    snpe-dlv-viewer结果
  • 输入层信息:
    输入层信息
  • 输出层信息:
    输出层信息

更新3:RGB转Float数组代码

float[] loadRgbBitmapAsFloat(Bitmap image) {
    final int[] pixels = new int[image.getWidth() * image.getHeight()];
    image.getPixels(pixels, 0, image.getWidth(), 0, 0,
            image.getWidth(), image.getHeight());

    final float[] pixelsBatched = new float[pixels.length * 3];
    for (int y = 0; y < image.getHeight(); y++) {
        for (int x = 0; x < image.getWidth(); x++) {
            final int idx = y * image.getWidth() + x;
            final int batchIdx = idx * 3;

            final float[] rgb = extractColorChannels(pixels[idx]);
            pixelsBatched[batchIdx]     = rgb[0];
            pixelsBatched[batchIdx + 1] = rgb[1];
            pixelsBatched[batchIdx + 2] = rgb[2];
        }
    }
    return pixelsBatched;
}

问题

请问该图像错位问题的可能原因是什么?

内容的提问来源于stack exchange,提问作者梁生珺

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 07:07:12