0

the following code throws a NullPointerException and I'm not sure why. If someone could point me to the error it would be much apprecciated.

The code from the MainActivity, the error is in line 4:

private void init(){
    this.createClassifier();
    this.takePhoto();
}

private void createClassifier(){
    try {
        classifier = ImageClassifierFactory.create(
                getAssets(),
                Constants.GRAPH_FILE_PATH,
                Constants.LABELS_FILE_PATH,
                Constants.IMAGE_SIZE,
                Constants.GRAPH_INPUT_NAME,
                Constants.GRAPH_OUTPUT_NAME);
    }catch (IOException e) {
        Log.e("MainActivity", e.getMessage());
    }


}
private Classifier classifier; 
...

private final void classifyAndShowResult(final Bitmap croppedBitmap){
    runInBackground((new Runnable(){
        public final void run(){
            Result result = classifier.recognizeImage(croppedBitmap);
            showResult(result);
        }
    }));

}

There are different methods calling init(), so I can't figure out why classifier doesn't get initialised.

The result class:

public class Result {
private String result;
private float confidence;

public Result(String result, float confidence) {
    this.result = result;
    this.confidence = confidence;
}

public String getResult() {
    return result;
}

public void setResult(String result) {
    this.result = result;
}

public float getConfidence() {
    return confidence;
}

public void setConfidence(float confidence) {
    this.confidence = confidence;
}
}

the classifier Interface:

public interface Classifier {
Result recognizeImage(Bitmap bitmap);

and the initiated recognizeImage:

public Result recognizeImage(Bitmap bitmap){
    preprocessImageToNormalizedFloats(bitmap);
    classifyImageToOutputs();
    PriorityQueue outputQueue = new PriorityQueue(getResults());
    Object queue = outputQueue.poll();
    return (Result)queue;
}

The error code was: java.lang.NullPointerException: Attempt to invoke interface method 'classifier.Result classifier.Classifier.recognizeImage(android.graphics.Bitmap)' on a null object reference

ImageClassifier Constructor:

 public ImageClassifier(String inputName, String outputName, long imageSize, List labels, int[] imageBitmapPixels, float[] imageNormalizedPixels, float[] results, TensorFlowInferenceInterface tensorFlowInference) {
    this.inputName = inputName;
    this.outputName = outputName;
    this.imageSize = imageSize;
    this.labels = labels;
    this.imageBitmapPixels = imageBitmapPixels;
    this.imageNormalizedPixels = imageNormalizedPixels;
    this.results = results;
    this.tensorFlowInference = tensorFlowInference;
}

ImageClassifierFactory Class:

public class ImageClassifierFactory {

public final static Classifier create(AssetManager assetManager, String graphFilePath, String labelsFilePath, int imageSize, String inputName, String outputName) throws IOException {

    List labels = getLabels(assetManager, labelsFilePath);
    ImageClassifier  im = new ImageClassifier(inputName, outputName, (long)imageSize, labels, new int[imageSize * imageSize], new float[imageSize * imageSize * COLOR_CHANNELS], new float[labels.size()], new TensorFlowInferenceInterface(assetManager, graphFilePath));
    return im;

}

}

smart78
  • 13
  • 1
  • 5
  • Sounds like `classifier` is `null`. Where do you define it? – David Jan 26 '19 at 16:30
  • I define it as "private Classifier classifier" at the top of the MainActivity. I already looked at that question but I can't seem to figure out how to fix the problem. – smart78 Jan 26 '19 at 16:33
  • Then where do you *initialize* `classifier`? A `NullPointerException` always means the same thing. You're trying to use a variable that hasn't been initialized (and is therefore `null`). – David Jan 26 '19 at 18:20

2 Answers2

0

You can't create classifier Instance of the interface Classifier . you need to change Classifier to A class and create classifier instance of the class or create an instance of a Another class which implements the Classifier interface

Mouad Khali
  • 114
  • 3
  • The recognizeImage method is initiated in a ImageClassifier Class which implements the Classifier interface. Is this what you mean? I'm not sure how to corporate an instance of this class in our method. I'm a beginner so I'm sorry if I don't understand you correctly – smart78 Jan 26 '19 at 16:48
  • since recognizeImage method is implemented in ImageClassifier Class , now you need to create and instance of that class as an attribute classifyAndShowResult Class – Mouad Khali Jan 26 '19 at 16:53
  • Do you mean I have to create an instance of the ImageClassifier Instance in the class where the classifyAndShowResult is? – smart78 Jan 26 '19 at 17:00
  • Yes . you need to create an instance of the ImageClassifier Instance in the class where the classifyAndShowResult exist – Mouad Khali Jan 26 '19 at 17:05
  • Could you take a look at the updated code? Because we created an object in the ImageClassifierFactory I think that we somehow have to incorporate that one and not the ImageClassifier but I'm not sure how/if. – smart78 Jan 26 '19 at 17:43
  • you have inside the ImageClassifierFactory a static method that create's your classifier , now call that method inside the class where the classifyAndShowResult is like so Classifier classifier = ImageClassifierFactory.create(pass in your arguments); this will return a classifier then you can use it inside classifyAndShowResult – Mouad Khali Jan 26 '19 at 17:57
  • I just realised that we already did this in the mainActivity using a createClassifier method but classifier is still initalized with null. I'll add the code again. – smart78 Jan 26 '19 at 18:20
  • ok you need to change private Classifier classifier to public Classifier classifier and place it before createClassifier() method + does init() get called somewhere? – Mouad Khali Jan 26 '19 at 18:27
  • Yes init() is called when the app asks for permission to use the camera, this happens right in the beginning - at least I think it gets called – smart78 Jan 26 '19 at 18:31
  • as i said before Classifier is an interface you can't do this private Classifier classifier to change it Classifier to ImageClassifier and in the create method inside ImageClassifierFactory change return type to ImageClassifier – Mouad Khali Jan 26 '19 at 18:40
0

The class declaring the classifyAndShowResult-Method must have classifier within its attributes. That variable is nullat the time you call that method. To debug this, you should start your application in 'debug' mode (Assuming you program in eclipse) and then read the stack of the NullPointerExceptionto isolate the reason classifierhas not been initiated.

@Edit: After seeing your code-snipped for classifier, you need to do something like this:

private Classifier classifier = new ImageClassifier();

...assuming classifierdoes not need parameters, when being initialized.

TreffnonX
  • 2,924
  • 15
  • 23
  • I have a constructor for the ImageClassifier class because we call it in another class (ImageClassifierFactory). I'll add those to the original post but I'm not sure if the ImageClassfierFactory is connected to this. Could it be that I have to somehow corporate this into the declaration? – smart78 Jan 26 '19 at 17:37
  • It depends. This is a question of runtime. If the attribute ```classifier```is set before ```classifyAndShowResult```is called, your code should not throw an NPE at that point, unless it is initialized with ```null```.But it does. If i were you, I'd set a breakpoint at that particulat code point, and run it. Then take a look at the 'variables'-View of eclipse, and see for yourself, that (probably) ```classifier```has not yet been initialized. – TreffnonX Jan 26 '19 at 17:41