* Synthesize an input image, run inference on it and visualize the results. * * @param {tf.Model} model Model to be used for inference.
(model)
| 95 | * @param {tf.Model} model Model to be used for inference. |
| 96 | */ |
| 97 | async function runAndVisualizeInference(model) { |
| 98 | // Synthesize an input image and show it in the canvas. |
| 99 | const synth = new ObjectDetectionImageSynthesizer(canvas, tf); |
| 100 | |
| 101 | const numExamples = 1; |
| 102 | const numCircles = 10; |
| 103 | const numLineSegments = 10; |
| 104 | const {images, targets} = await synth.generateExampleBatch( |
| 105 | numExamples, numCircles, numLineSegments); |
| 106 | |
| 107 | const t0 = tf.util.now(); |
| 108 | // Runs inference with the model. |
| 109 | const modelOut = await model.predict(images).data(); |
| 110 | inferenceTimeMs.textContent = `${(tf.util.now() - t0).toFixed(1)}`; |
| 111 | |
| 112 | // Visualize the true and predicted bounding boxes. |
| 113 | const targetsArray = Array.from(await targets.data()); |
| 114 | const boundingBoxArray = targetsArray.slice(1); |
| 115 | drawBoundingBoxes(canvas, boundingBoxArray, modelOut.slice(1)); |
| 116 | |
| 117 | // Display the true and predict object classes. |
| 118 | const trueClassName = targetsArray[0] > 0 ? 'rectangle' : 'triangle'; |
| 119 | trueObjectClass.textContent = trueClassName; |
| 120 | |
| 121 | // The model predicts a number to indicate the predicted class |
| 122 | // of the object. It is trained to predict 0 for triangle and |
| 123 | // 224 (canvas.width) for rectangel. This is how the model combines |
| 124 | // the class loss with the bounding-box loss to form a single loss |
| 125 | // value. Therefore, at inference time, we threshold the number |
| 126 | // by half of 224 (canvas.width). |
| 127 | const shapeClassificationThreshold = canvas.width / 2; |
| 128 | const predictClassName = |
| 129 | (modelOut[0] > shapeClassificationThreshold) ? 'rectangle' : 'triangle'; |
| 130 | predictedObjectClass.textContent = predictClassName; |
| 131 | |
| 132 | if (predictClassName === trueClassName) { |
| 133 | predictedObjectClass.classList.remove('shape-class-wrong'); |
| 134 | predictedObjectClass.classList.add('shape-class-correct'); |
| 135 | } else { |
| 136 | predictedObjectClass.classList.remove('shape-class-correct'); |
| 137 | predictedObjectClass.classList.add('shape-class-wrong'); |
| 138 | } |
| 139 | |
| 140 | // Tensor memory cleanup. |
| 141 | tf.dispose([images, targets]); |
| 142 | } |
| 143 | |
| 144 | async function init() { |
| 145 | const LOCAL_MODEL_PATH = 'object_detection_model/model.json'; |
no test coverage detected