teachable_machine.html
<!-- Node Configuration Templates -->
<script type="text/html" data-template-name="teachable machine">
<div class="form-row">
<label for="node-input-mode"><i class="fa fa-file" style="margin-right: 6px"></i>Mode</label>
<select style="width: 160px;" type="text" id="node-input-mode">
<option value="online" selected> Online</option>
<option value="local"> Local</option>
</select>
</div>
<div class="node-row-msg-modelUri">
<div class="form-row node-row-modelUri">
<label for="node-input-modelUri"><i class="fa fa-link" style="margin-right: 6px;"></i>URI</label>
<input type="text" id="node-input-modelUri" placeholder="https://teachablemachine.withgoogle.com/model/[...]">
</div>
</div>
<div class="form-row">
<label for="node-input-output"><i class="fa fa-sign-out" style="margin-right: 6px;"></i>Output</label>
<select style="width: 160px;" type="text" id="node-input-output">
<option value="best" selected>Best prediction</option>
<option value="all">All predictions</option>
</select>
</div>
<div class="node-row-msg-filters">
<div class="form-row">
<label for="node-input-filters"><i class="fa fa-filter" style="margin-right: 6px;"></i>Filters</label>
<label for="node-input-threshold" style="width:70%;">
<input type="checkbox" id="node-input-activeThreshold" style="display:inline-block; width:22px; vertical-align:baseline;">
<label style="width:65px;">threshold</label>
<input type="text" id="node-input-threshold" style="width: 40px;" placeholder="80"> %
</label>
</div>
<div class="form-row">
<label for="node-input-filters"></label>
<label for="node-input-threshold" style="width:70%;">
<input type="checkbox" id="node-input-activeMaxResults" style="display:inline-block; width:22px; vertical-align:baseline;">
<label style="width:65px;">maximum</label>
<input type="text" id="node-input-maxResults" style="width: 40px;" placeholder="3"> predictions
</label>
</div>
</div>
<div class="form-row">
<label for="node-input-passThrough"><i class="fa fa-picture-o" style="margin-right: 6px;"></i>Image</label>
<input type="checkbox" id="node-input-passThrough" style="display:inline-block; width:22px; vertical-align:baseline;">
save original image in <code>msg.image</code>.
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag" style="margin-right: 6px;"></i>Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
</script>
<!-- Information Help Menu -->
<script type="text/html" data-help-name="teachable machine">
<p>A <a href="https://www.tensorflow.org/js" target = "_new">tensorflow.js</a> node to run custom trained <a href="https://teachablemachine.withgoogle.com" target = "_new">Teachable Machine</a> image classification online models.</p>
<h3>Inputs</h3>
<dl class="message-properties">
<dt>payload<span class="property-type">image buffer</span></dt>
<dd>A binary buffer of an image (jpeg or png)</dd>
<dt>reload<span class="property-type">bool</span></dt>
<dd>Set to true to reload the model. In the same time, ignore image in payload (if any) and do not perform image classification.</dd>
</dl>
<h3>Outputs</h3>
<dl class="message-properties">
<dt>payload<span class="property-type">array</span></dt>
<dd>Objects in the array are ordered by descending probability and have the following properties:
<ul>
<li><code>nameClass</code> <i>string</i></li>
<li><code>probability</code> <i>float (0-1)</i></li>
</ul>
</dd>
<dt>classes<span class="property-type">array</span></dt>
<dd>All the possible class names used in the model.</dd>
</dl>
<h3>Configuration</h3>
<h4><i class="fa fa-file" style="margin-right: 6px"></i>Mode</h4>
<p>You can configure how to load the model.</p>
<ul>
<li><code>Online</code> from the teachable machine URL</li>
<li><code>Local</code> from the local URI (where the model.json, metadata.json and model.weights.bin exist)</li>
</ul>
<p>If you select the <code>Online</code> mode, you must set the URL obtained from the uploaded model in the <a href="https://teachablemachine.withgoogle.com" target = "_new">Teachable Machine</a> webpage.</p>
<h4><i class="fa fa-sign-out" style="margin-right: 6px"></i>Output</h4>
<p>You can configure how the <code>msg.payload</code> is generated.</p>
<ul>
<li><code>Best prediction</code> only the top-1 classification result</li>
<li><code>All predictions</code> all predictions with enabled filters</li>
</ul>
<h4><i class="fa fa-filter" style="margin-right: 6px"></i>Filters</h4>
<p>You can enable or disable any of the filters when <code>All predictions</code> Output mode is selected. Filters are all aplied if enabled.
<ul>
<li><code>Threshold</code> filters only the results that are above the threshold (0-100)</li>
<li><code>Max. Predictions</code> limits the results to any number (1-5)</li>
</ul>
</script>
<!-- Node JavaScript Registration -->
<script type="text/javascript">
RED.nodes.registerType('teachable machine',
{
category: 'analysis-function',
color: '#ED782F',
defaults: {
name: { value: '' },
mode: { value: 'online' },
modelUri: { value: '', required: true },
localModel: { value: 'teachable_model' },
output: { value: 'best', required: true },
activeThreshold: { value: false },
threshold: { value: 80, validate: function(v) { return RED.validators.number(v) && (v > 0) && (v < 100)}},
activeMaxResults: { value: false },
maxResults: { value: 3, validate: function(v) { return RED.validators.number(v) && (v > 0) && (v < 5)}},
passThrough: { value: false }
},
inputs: 1,
outputs: 1,
icon: 'tensorflow_logo.png',
label: function () {
return this.name || 'teachable machine'
},
oneditprepare: function() {
$("#node-input-threshold").spinner({ min: 0, max: 100})
$("#node-input-maxResults").spinner({ min: 1, max: 5})
$("#node-input-output").on("change", function(e) {
var val = $(this).val()
$(".node-row-msg-filters").toggle(val==="all")
})
}
})
</script>