I have a p5 webcam video prediction system working right now. Currently, I’m trying to plug this into a React app to create a fuller web app.
My problem is, the prediction is now only made in my p5 sketch, I want the prediction value to be passed into React’s App.js for further constructions. Is there any method of doing so?
I’m using react-p5-wrapper btw.
Here’s the sketch.js:
import "react-p5-wrapper/node_modules/p5/lib/addons/p5.dom"; import ml5 from 'ml5'; let mobileNet; let video; let label='model loading...'; function sketch (p) { p.setup = function () { p.createCanvas(1000, 1000); //imitialize the webcam stream in a object video = p.createCapture(p.VIDEO); //hide the webcam stream video.hide(); //initialize the mobilenet object with a callback mobileNet= ml5.imageClassifier('MobileNet',video,ModelLoaded); }; p.draw = function () { p.image(video,0,0); p.textSize(16); p.fill(255,140,0); p.text(label,10,450); }; }; function ModelLoaded() { console.log('Model is ready'); //predicting the image mobileNet.predict(result) } //callback function to get the results function result(err,res) { //check for errors if(err) { //log the error if any console.error(err) } else{ //get the label from the json result label = res[0].className; //predicting the image again mobileNet.predict(result) } } export default sketch;
And my App.js currently looks like this:
import React, { Component } from 'react'; // import logo from './logo.svg'; import './App.css'; import sketch from './sketch'; import P5Wrapper from 'react-p5-wrapper'; class App extends Component { componentDidMount(){ } render() { return ( <div className="App"> <P5Wrapper sketch={sketch} /> </div> ); } } export default App;
Any help appreciated!
Advertisement
Answer
I gave this a go and came up with a solution. It isn’t very elegant but it should do. I made a very simple test project in sketch.js where I try to illustrate two ways accessing the infromation. The things to note are the timesClicked variable and the updateWithProps function.
export let timesClicked = 0; export default function sketch (p) { p.setup = function () { p.createCanvas(300, 300); }; p.draw = function () { p.background(0); p.fill(255); p.ellipse(p.mouseX, p.mouseY, 100, 100); }; p.updateWithProps() = function(newProps){ if(newProps.getCoords){ p.sendCoords = newProps.getCoords; } } p.mouseClicked = function() { p.sendCoords(p.mouseX, p.mouseY); timesClicked++; } };
timesClicked is a variable that can be imported and counts the times the mouse has been clicked. It can be modified from inside the sketch scope and imported from other files.
updateWithProps is a function called from the react-p5-wrapper library whenever the component receives props and can be defined inside the sketch.
With this, your App.js file could be modified like so:
import React, { Component } from 'react'; import P5Wrapper from 'react-p5-wrapper'; import sketch from './sketch'; import {timesClicked} from './sketch'; function getCoords(){ console.log(arguments); } class App extends Component { componentDidMount(){ } render() { return ( <div className="App"> <P5Wrapper sketch={sketch} getCoords={getCoords}/> </div> ); } } export default App; document.body.onkeyup = function(e){ if(e.keyCode == 32){ console.log(timesClicked); } }
When running, every time there is a click, the sketch will execute the getCoords() function in the App.js file and, alternatively, every time the space bar is pressed the timesClicked variable will be accessed from the App.js file. I think you can modify this in order to “send” or “read” the prediction value.
Edited as per Daniel’s answer