I tried to do it as in your 3.6.2 video but it won’t let me do it like you have. Firstly I can only use executeAsync not predict. And secondly I can’t call data.Sync or arrraySync on the result. I get 8 Tensor results and I can call it on each of those but have no idea what to make of any of the data. I figure my output is somewhat similar to TensorFlow | ssd_mobilenet_v2 | Kaggle however its different enough that I cannot use this as a guide. I have pretty much given up at this point. I just wanted to get the bounding box of a webcam within a screenshot of a live stream but have wasted days going down the rabbit hole. I tried my best to shoehorn this solution to mine but it couldn’t javascript - How to get bounding box from object detection of TensorFlowJS? - Stack Overflow .
Can you show me your updated code that you tried?
In the end I tried the cocssd library but got the same error as I was getting manually trying to use the code from the stack overflow.
const tf = require('@tensorflow/tfjs-node')
const cocoSsd = require('@tensorflow-models/coco-ssd');
const fs = require('fs');
var path = './webcams/test.jpg';
const buf = fs.readFileSync(path);
const input = tf.node.decodeJpeg(buf)
async function load(img){
// I also tried the cocossd version and got the same error
cocoSsd.load({
base: 'lite_mobilenet_v2',
modelUrl: 'file://webcam_tfjs_model/webcam_tfjs_model/model.json'
}
).then(model => {
// detect objects in the image.
model.detect(img).then(predictions => {
console.log('Predictions: ', predictions);
});
});
}
load(input)
The error is
Error: Tensor must have a shape comprised of positive integers but got shape [30,].
But I feel like something is off anyway, because all the ‘shape’ numbers in the Tensors are the same regardless of using a different image where the bounding box should be different.
I tried to use tensorflowjs_converter again and for the life of me couldn’t get it to work. I have tried to write the input and output paths in every possible way. I always get the same error
tensorflowjs_converter \ --input_format=tf_saved_model \ --output_format=tfjs_graph_model \ --output_node_names='Postprocessor/ExpandDims_1,Postprocessor/Slice' \ /saved_model /web_model
TensorFlow.js model converters.: error: unrecognized arguments: \ \ \ ./saved_model \ ./web_model
But thats a seperate issue and many people seem to be having issues with this in the github issues but none of the answers helped me
This code works for me to print correctly to console the results. You can not log the returned tensor like you are doing as that will print the tensor not the data it holds.
const tf = require('@tensorflow/tfjs');
// Defining tensor input elements
const model_Url =
'https://storage.googleapis.com/tfjs-models/savedmodel/mobilenet_v2_1.0_224/model.json';
async function doIt() {
// Calling the loadGraphModel() method
const mymodel = await tf.loadGraphModel(model_Url);
// Defining inputs
const inputs = tf.zeros([1, 224, 224, 3]);
// Calling executeAsync() method
const res = await mymodel.execute(inputs);
// Printing output
res.print();
}
doIt();
Below I have put the new code and the errors I get doing it your suggested way.
const tf = require('@tensorflow/tfjs-node')
const cocoSsd = require('@tensorflow-models/coco-ssd');
const fs = require('fs');
var path = './webcams/demo.jpg';
const buf = fs.readFileSync(path);
const input = tf.node.decodeJpeg(buf)
const model_Url = 'file://OG/tfjsmodel/model.json';
async function doIt(input) {
// Calling the loadGraphModel() method
const mymodel = await tf.loadGraphModel(model_Url);
// Defining inputs
// const inputs = tf.zeros([1, 224, 224, 3]); // Error: The dtype of dict['input_tensor'] provided in model.execute(dict) must be int32, but was float32
const inputs = input.expandDims(0);
// Calling executeAsync() method
// const result = await mymodel.execute(inputs); // Error: This execution contains the node 'StatefulPartitionedCall/SecondStagePostprocessor/BatchMultiClassNonMaxSuppression/MultiClassNonMaxSuppression/ClipToWindow/Where', which has the dynamic op 'Where'. Please use model.executeAsync() instead. Alternatively, to avoid the dynamic ops, specify the inputs [StatefulPartitionedCall/SecondStagePostprocessor/ BatchMultiClassNonMaxSuppression/MultiClassNonMaxSuppression/ClipToWindow/Reshape]
const result = await mymodel.executeAsync(inputs);
// result.print() // TypeError: result.print is not a function
// Printing output
result.forEach(function(res, index){
res.print()
})
}
doIt(input);
The results look like below, always the same regardless of whether the image had an object or not.
Tensor
[0]
Tensor
[[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
...,
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]]
Tensor
[[0, 0, 0, ..., 0, 0, 0],]
Tensor
[[0, 0, 0, ..., 0, 0, 0],]
Tensor
[[[0.9999999, 0],
[0.9999999, 0],
[0.9999999, 0],
...,
[1 , 0],
[1 , 0],
[1 , 0]]]
Tensor
[[[0, 0],
[0, 0],
[0, 0],
...,
[0, 0],
[0, 0],
[0, 0]]]
Tensor
[[1, 1, 1, ..., 1, 1, 1],]
Tensor
[[[0, 1, 0, 1],
[0, 1, 0, 1],
[0, 1, 0, 1],
...,
[0, 1, 0, 1],
[0, 1, 0, 1],
[0, 1, 0, 1]]]
I ended up just doing it in python and served it up on a AWS lambda using a docker container. Works nicely.
Why using result.foreach here? The result is a Tensor not an Array as far as I can tell from your code. You should just need to call result.arraySync() and that will return an array which you can then loop through as you like to get all the outputs.
You can see a comment in the code .print() and arraySync are not available as functions, only within each of the 8 array elements are they available.
TypeError: result.arraySync is not a function
That is odd as my code above which is essentially the same but using the mobilenet model as I dont have access to your local one works with the code written. There may be something I am missing here that is specific to your environment/model which is hard to debug without having access.