Tensorflow keras freeze .pb模型在android上返回错误结果

时间:2018-01-24 09:01:45

标签: android python tensorflow keras protocol-buffers

我使用Keras在IncpetionV3上创建了我的模型,并使用以下python代码将其导出到 .pb 文件中:

MODEL_NAME = 'Model_all1'

def export_model(saver, model, input_node_names, output_node_name):
    tf.train.write_graph(K.get_session().graph_def, 'out_all2', MODEL_NAME + '_graph.pbtxt')

    saver.save(K.get_session(), 'out_all2/' + MODEL_NAME + '.chkp')

    freeze_graph.freeze_graph('out_all2/' + MODEL_NAME + '_graph.pbtxt', None,
                          False, 'out_all2/' + MODEL_NAME + '.chkp', output_node_name,
                          "save/restore_all", "save/Const:0",
                          'out_all2/final_' + MODEL_NAME + '.pb', True, "")

    print("graph saved!")

export_model(tf.train.Saver(), model, ["input_3"], "dense_6/Softmax")

然后我尝试将我的模型加载到我的Android应用程序中。 对于我的应用程序,我使用以下代码预先处理我的图像,然后将其发送到 .pb 模型。 Bitmap来自我手机上的相机。

//scaled the bitmap down
Bitmap bitmap = Bitmap.createScaledBitmap(imageBitmap, PIXEL_WIDTH, PIXEL_WIDTH, true);

float pixels[] = getPixelData(bitmap);
public static float[] getPixelData(Bitmap imageBitmap) {
    if (imageBitmap == null) {
        return null;
    }

    int width = imageBitmap.getWidth();
    int height = imageBitmap.getHeight();
    int inputSize = 299;
    int imageMean = 155;
    float imageStd = 255.0f;

    int[] pixels = new int[width * height];
    float[] floatValues = new float[inputSize * inputSize * 3];

    imageBitmap.getPixels(pixels, 0, imageBitmap.getWidth(), 0, 0, imageBitmap.getWidth(), imageBitmap.getHeight());
    for (int i = 0; i < pixels.length; ++i) {
        final int val = pixels[i];
        floatValues[i * 3 + 0] = (((val >> 16) & 0xFF) - imageMean) / imageStd;
        floatValues[i * 3 + 1] = (((val >> 8) & 0xFF) - imageMean) / imageStd;
        floatValues[i * 3 + 2] = ((val & 0xFF) - imageMean) / imageStd;
    }


    return floatValues;
}

下面显示我识别的图像代码,链接到我在Android上加载的.pb文件

public ArrayList<Classification> recognize(final float[] pixels) {

    //using the interface
    //input size
    tfHelper.feed(inputName, pixels, 1, inputSize, inputSize, 3);

    //get the possible outputs
     tfHelper.run(outputNames, logStats);

    //get the output
    tfHelper.fetch(outputName, outputs);

    // Find the best classifications.
    PriorityQueue<Recognition> pq =
            new PriorityQueue<Recognition>(
                    3,
                    new Comparator<Recognition>() {
                        @Override
                        public int compare(Recognition lhs, Recognition rhs) {
                            // Intentionally reversed to put high confidence at the head of the queue.
                            return Float.compare(rhs.getConfidence(), lhs.getConfidence());
                        }
                    });
    for (int i = 0; i < outputs.length; ++i) {
        if (outputs[i] > THRESHOLD) {
            pq.add(
                    new Classifier.Recognition(
                            "" + i, labels.size() > i ? labels.get(i) : "unknown", outputs[i], null));
        }
    }
    final ArrayList<Recognition> recognitions = new ArrayList<Recognition>();
    int recognitionsSize = Math.min(pq.size(), MAX_RESULTS);
    for (int i = 0; i < recognitionsSize; ++i) {
        recognitions.add(pq.poll());
    }
    Trace.endSection(); // "recognizeImage"
    //fit into classification list
    ArrayList<Classification> anslist = new ArrayList<>();
    for (int i = 0; i < recognitions.size(); i++) {
        Log.d("classification",recognitions.get(i).getTitle() +" confidence : "+ recognitions.get(i).getConfidence());
        Classification ans = new Classification();
        ans.update(recognitions.get(i).getConfidence(),recognitions.get(i).getTitle());
        anslist.add(ans);
    }
    return anslist;
}

在我的测试中,在我生成冻结图模型之前, .pb 文件。我的模型的准确性非常高。但是,当我将其加载到我的Android应用程序时,我在Android上的模型返回的预测结果到处都是。

我已经测试了很长时间,我无法找到问题所在。有没有人有任何见解?我是否生成了错误的 .pb 文件?或者我是否错误地将图像发送到冻结图表?我很难过。

2 个答案:

答案 0 :(得分:0)

很难说,因为我不确定你的Keras模型的细节,但是在移植到另一个平台时最合适的部分之一是输入图像处理参数。您已定义imageMeanimageStd,但是您知道它们与Keras模型相同吗?

要调试这个,我会经常尝试通过Python和设备上的代码提供相同的图像(例如Admiral Hopper),并确保得到相同的结果。

答案 1 :(得分:0)

如果您确定图像预处理步骤。然后问题可能和我的一样。我遇到了同样的问题,我找到了答案。 here有更多说明。我猜你除了以下所做的所有步骤都是我的。

您的问题可能在于色彩通道还原。 imageBitmap.getPixels将颜色通道从BGR反转为RGB。如果这是图像预处理的一部分,您只需要将它们转换回BGR。

使用以下代码执行此操作:

    floatValues[i * 3 + 0] = (((val >> 16) & 0xFF) - imageMean) / imageStd;
    floatValues[i * 3 + 1] = (((val >> 8) & 0xFF) - imageMean) / imageStd;
    floatValues[i * 3 + 2] = ((val & 0xFF) - imageMean) / imageStd;
 // reverse the color orderings to BGR.
    floatValues[i*3 + 2] = Color.red(val);
    floatValues[i*3 + 1] = Color.green(val);
    floatValues[i*3] = Color.blue(val);

希望有帮助,