TransWikia.com

Running Tensorflow MobileNet from Java

Data Science Asked on March 13, 2021

I am trying to run Tensorflow for image recognition (classification) in Java (JSE not Android).

I am using the code from here, and here.

It works for Inceptionv3 models, and for models retrained from Inceptionv3.

But for MobileNet models it does not work, (such as following this article).

The code works, but gives the wrong results (wrong classify labels). What code/settings are required to use MobileNet from Java?

The code that works for Inceptionv3 is

try (Tensor image = Tensor.create(imageBytes)) {
            float[] labelProbabilities = executeInceptionGraph(graphDef, image);
            int bestLabelIdx = maxIndex(labelProbabilities);
            result.setText("");
            result.setText(String.format(
                            "BEST MATCH: %s (%.2f%% likely)",
                            labels.get(bestLabelIdx), labelProbabilities[bestLabelIdx] * 100f));
            System.out.println(
                    String.format(
                            "BEST MATCH: %s (%.2f%% likely)",
                            labels.get(bestLabelIdx), labelProbabilities[bestLabelIdx] * 100f));
        }

This works of Inceptionv3 models, but not MobileNet,
Gives the error, “Expects args[0] to be float but string is provided”

For MobileNet we tried the code,

try (Graph g = new Graph()) {
  GraphBuilder b = new GraphBuilder(g);
  // Some constants specific to the pre-trained model at:
  // https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip
  //
  // - The model was trained with images scaled to 224x224 pixels.
  // - The colors, represented as R, G, B in 1-byte each were converted to
  //   float using (value - Mean)/Scale.
  final int H = 224;
  final int W = 224;
  final float mean = 128f;
  final float scale = 1f;

  // Since the graph is being constructed once per execution here, we can use a constant for the
  // input image. If the graph were to be re-used for multiple input images, a placeholder would
  // have been more appropriate.
  final Output<String> input = b.constant("input", imageBytes);
  final Output<Float> output =
      b.div(
          b.sub(
              b.resizeBilinear(
                  b.expandDims(
                      b.cast(b.decodeJpeg(input, 3), Float.class),
                      b.constant("make_batch", 0)),
                  b.constant("size", new int[] {H, W})),
              b.constant("mean", mean)),
          b.constant("scale", scale));
  try (Session s = new Session(g)) {
    return s.runner().fetch(output.op().name()).run().get(0).expect(Float.class);
  }
}

This works, but gives the wrong labels.

One Answer

Don't give to use in java :)

I had the same problem, try to change the scale value, I had the same labels from java and python after that.

        // - The model was trained with images scaled to 224x224 pixels.
        // - The colors, represented as R, G, B in 1-byte each were converted to
        // float using (value - Mean)/Scale.
        final int H = 224;
        final int W = 224;
        final float mean = 117f;
        final float scale = 255f;

Answered by Eduardo SantAna da Silva on March 13, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP