3

I have created a model for object detection in Python Tensorflow and then converted it in Tensorflow JS so as to use in browser. The model works perfectly in python. Now, when I give an input image to browser, there is major difference between prediction results in python and in Tensorflow JS. I am sharing the prediction results for both python and JS.

Results for Python :

enter image description here

And Results for JS :

enter image description here

I have given the same image as input to both python and JS but still the big difference specially for Scores where python predicts with 99% and JS predicts with just 16%.

What could be the reason for this ? Have I inadvertently committed some mistake while converting to Tensorflow JS or is there some other reason for this ?

I went through this and other resources on the internet but couldn't find any specific reason for the difference in results.

Any help will be grateful. Thanks a lot.

Update 1 :

Here is my Python Code :

def load_image_into_numpy_array(image_path):
     return np.array(Image.open(image_path))

image_path = random.choice(TEST_IMAGE_PATHS)
image_np = load_image_into_numpy_array(image_path)
input_tensor = tf.convert_to_tensor(
    np.expand_dims(image_np, 0), dtype=tf.float32)
detections, predictions_dict, shapes = detect_fn(input_tensor)

label_id_offset = 1
image_np_with_detections = image_np.copy()

viz_utils.visualize_boxes_and_labels_on_image_array(
      image_np_with_detections,
      detections['detection_boxes'][0].numpy(),
      (detections['detection_classes'][0].numpy() + label_id_offset).astype(int),
      detections['detection_scores'][0].numpy(),
      category_index,
      use_normalized_coordinates=True,
      max_boxes_to_draw=200,
      #Set min_score_thresh accordingly to display the boxes
      min_score_thresh=.5, 
      agnostic_mode=False
)

plt.figure(figsize=(12,25))
plt.imshow(image_np_with_detections)
plt.show()

And here is model call in JS :

async function run() {

    //Loading the Model : 
    model = await tf.loadGraphModel(MODEL_URL);
    console.log("SUCCESS");

    let img = document.getElementById("myimg");

    console.log("Predicting....");

    //Image PreProcessing 
    var example = tf.browser.fromPixels(img);
    example = example.expandDims(0);

    //model call
    const output = await model.executeAsync(example);
    console.log(output);

    const boxes = output[4].arraySync();
    const scores = output[5].arraySync();
    const classes = output[1].arraySync();

    console.log(boxes);
    console.log(scores);
    console.log(classes);

}

Update 2 :

import pathlib

filenames = list(pathlib.Path('/content/train/').glob('*.index'))

filenames.sort()
print(filenames)

#recover our saved model
pipeline_config = pipeline_file
#generally you want to put the last ckpt from training in here
model_dir = str(filenames[-1]).replace('.index','')
configs = config_util.get_configs_from_pipeline_file(pipeline_config)
model_config = configs['model']
detection_model = model_builder.build(
      model_config=model_config, is_training=False)

# Restore checkpoint
ckpt = tf.compat.v2.train.Checkpoint(
      model=detection_model)
ckpt.restore(os.path.join(str(filenames[-1]).replace('.index','')))


def get_model_detection_function(model):
  """Get a tf.function for detection."""

  @tf.function
  def detect_fn(image):
    """Detect objects in image."""

    image, shapes = model.preprocess(image)
    prediction_dict = model.predict(image, shapes)
    detections = model.postprocess(prediction_dict, shapes)

    return detections, prediction_dict, tf.reshape(shapes, [-1])

  return detect_fn

detect_fn = get_model_detection_function(detection_model)
S M
  • 111
  • 11
  • 1
    image preprocessing most likely. But there's not enough information in your question to answer. We need your training pipeline in Python, your model call in JS. – Lescurel May 06 '21 at 15:11
  • @Lescurel I have added more information as suggested. – S M May 06 '21 at 17:56
  • The first thing that comes to mind is that you're using different weights. Are you sure that you're loading the trained weights in Javascript? Because an accuracy of 16% sounds like a randomly initialized network. – mmiron May 06 '21 at 18:18
  • Can you share the definition of `detect_fn` in the python code? – Lescurel May 06 '21 at 18:55
  • @mmiron No, I am not using different weights. The MODEL_URL points towards the .json file. – S M May 07 '21 at 05:15
  • @Lescurel Definition for detect_fn added. – S M May 07 '21 at 06:54
  • You are *randomly selecting images* in the Python code, are you doing the same for the JavaScript code? – yudhiesh May 07 '21 at 07:47
  • @yudhiesh For JS I am passing the same image as input which I am passing to Python Code. And in Python, the Image directory contains only 2 images. As a result I can easily distinguish prediction results of both the images. – S M May 07 '21 at 08:00
  • Last question: how do you export your model to JS? Do you include the `detect_fn` function or not in your export? – Lescurel May 07 '21 at 09:28
  • @Lescurel My python model has the following Structure : assets,saved_model.pb and variables. And then I converted to TensoflowJS in the following way : ' !tensorflowjs_converter \ --input_format=tf_saved_model \ --saved_model_tags=serve \ /content/ObjectDetectionModel/my_model/1 \ /content/TensorflowJSOP ' I haven't included detect_fn in my export. – S M May 07 '21 at 11:47

1 Answers1

0

You're missing preprocessing. When exporting your model, you are exporting the default serve tag, so your call to model.executeAsync in JS is equivalent to model.predict in python. However, in your python code, you are also preprocessing the inputs with a call to model.preprocess.

You should replicate the python preprocessing in JS.

Lescurel
  • 10,749
  • 16
  • 39
  • Noted. Will work on the pre processing aspect in JS as suggested and will update. Also would like to know if there are more tags other than the 'serve' tag for exporting the model. And Thanks for the help. – S M May 07 '21 at 17:48
  • After trying the preprocessing in JS, I still couldn't get the same accuracy as I was getting in Python. As a result I am using TensorflowServing now. Interestingly, I am not doing any of the processing which I did while training but still I am getting the same results as Python in TensorflowServing. – S M May 21 '21 at 13:41