JSFiddle - React, Tailwind, and code Playground
by morphcast
HTML
<script src="https://ai-sdk.morphcast.com/v1.8.5/ai-sdk.js"></script>
<body>
<div class="row">
<canvas id="canvas" class="col-md-8"></canvas>
<br />
<button id="start" onclick="onStart()" disabled>Start</button>
<button id="stop" onclick="onStop()">Stop</button>
<div class="col-md-4">
<div style="height:25em;">
<strong>Mood detection with MorphCast SDK</strong>
<div id="debug" style="word-wrap:break-word;"></div>
<h1><div id="av_results" style="word-wrap:break-word;"></div></h1>
</div>
</div>
<div>
<div>
<strong>DETECTOR LOG MSGS</strong>
</div>
<div id="logs"></div>
<h3>MorphCast JS SDK detects different mood cards.</h3>
<p>
<strong>Instructions</strong>
<br/>
Press the start button to start the detector.
<br/> When a card is detected, the name of the card is written above.
<br/> Press the stop button to end the detector.
</p>
</div>
</div>
</body>
JavaScript
// Begin of mood detection code
/**
* Represents a point in 2D dimensions (Arousal and Valence)
*/
class AVPoint {
constructor(arousal, valence) {
this.arousal = arousal;
this.valence = valence;
}
distanceTo(point) {
return Math.sqrt(Math.pow(this.arousal - point.arousal, 2) + Math.pow(this.valence - point.valence, 2));
}
toString() {
return '( A: ' + this.arousal + ', V: ' + this.valence + ')';
}
}
/**
* Class for processing AVPoints and estimating moods
*/
class MoodEstimator {
constructor() {
this.last_result = null;
this.same_results = 0;
}
static get MIN_STABLE_SAMPLES() {
return 10;
}
static get MIN_DISTANCE() {
return 0.1;
}
static get AVAILABLE_MOODS() {
return {
frustrated: new AVPoint(0.01, -0.13),
excited: new AVPoint(0.13, 0.14),
sad: new AVPoint(-0.07, -0.13),
satisfied: new AVPoint(-0.08, 0.07)
};
}
/**
* Estimate the current mood, after receiving several samples of AVPoints
* @param sample AVPoint detected
* @returns {{result: (null|*), is_stable: boolean}} an object with the estimated mood, or null if the new result is not stable yet
*/
processNext(sample) {
const {best_mood, min_distance} = MoodEstimator.findBest(sample);
if (this.last_result && this.last_result === best_mood) {
this.same_results++;
} else {
this.last_result = best_mood;
this.same_results = 0;
}
const is_stable_result = this.last_result && this.same_results >= MoodEstimator.MIN_STABLE_SAMPLES;
console.log("[DEBUG] min_distance: " + min_distance.toFixed(3) + " ( < " + MoodEstimator.MIN_DISTANCE
+ "); same_results: " + this.same_results + " ( >= " + MoodEstimator.MIN_STABLE_SAMPLES + ")");
return {
result: this.last_result,
is_stable: !!is_stable_result
}
}
static findBest(sample, threshold = MoodEstimator.MIN_DISTANCE) {
let best_mood = null, min_distance = +Infinity;
const...