I'm following the basic example of the ML5.js featureExtractor. I am not using video. After loading a model I am adding new images to it, and then training again. I get the following error:
Mobilenet.js:323 Uncaught (in promise) Error: Batch size is 0 or NaN. Please choose a non-zero fraction.
at t. (Mobilenet.js:323)
My code seems correct, according to the documentation - using video is optional, so I expect I should be able to re-train the model after just adding images manually. I used the callback for the addImage function, to make sure the images are really added before calling train
let added = 0
let classifier
let featureExtractor = ml5.featureExtractor('MobileNet', modelLoaded)
function modelLoaded() {
classifier = featureExtractor.classification()
classifier.addImage(document.getElementById('person1'), 'nomask', addedImage)
classifier.addImage(document.getElementById('mask1'), 'mask', addedImage)
}
// this gets called twice, but then train goes wrong
function addedImage(){
added++
if(added == 2){
classifier.train((lossValue) => {
console.log('Loss is', lossValue);
})
}
You need to add at least 3 images for training to work.
The following code should work.
let added = 0;
let classifier;
let featureExtractor = ml5.featureExtractor('MobileNet', modelLoaded);
function modelLoaded() {
classifier = featureExtractor.classification()
classifier.addImage(document.getElementById('person1'), 'nomask', addedImage);
classifier.addImage(document.getElementById('person2'), 'nomask', addedImage);
classifier.addImage(document.getElementById('mask1'), 'mask', addedImage);
}
function addedImage(){
added++;
if(added == 3){
classifier.train((lossValue) => {
console.log('Loss is', lossValue);
});
}
A working example: https://glitch.com/edit/#!/ml5-feature-extractor-addimage
Related
I have a function that checks if bullet hits a player, and if so it should remove the bullet and the player that got hit.
I have check_if_bullet_hit_player(bulletRef) function that gets a bullet ref, and the id of the player got shot.
I also have a shoot() function that calls the check_if_bullet_hit_player(bulletRef) for every bullet's movement.
Currently when a bullet hits a player, the bullet disappear, but I can't make the player got hit to disappear also.
Attempt - 1:
I tried the following shoot function:
function shoot(speed=0.5, distance=5, targetX, targetY){
var shoot = setInterval(function() {
check_if_bullet_hit_player(bulletRef).then(player_got_shot_id => {
if (player_got_shot_id != ""){
clearInterval(shoot);
bulletRef.remove();
hitPlayerRef = firebase.database().ref(`players/${player_got_shot_id}`);
hitPlayerRef.once("value").then(function(){
alert("hi");
hitPlayerRef.remove();
})
}
})
})
}
I get alert hi when a player gets hit, and the player that gets hit disappear for a moment, then re-created (which is not what is wanted). I think that the player get re-created because of async, so I tried different methods.
Attempt - 2:
I tried as the following stack overflow's answer, which waits for the ref to return:
function shoot(speed=0.5, distance=5, targetX, targetY){
var shoot = setInterval(function() {
check_if_bullet_hit_player(bulletRef).then(player_got_shot_id => {
if (player_got_shot_id != ""){
clearInterval(shoot);
bulletRef.remove();
await firebase.database().ref(`players/${player_got_shot_id}`).remove();
}
})
})
}
and I get:
Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules
Attempt - 3:
I tried to wait with then:
function shoot(speed=0.5, distance=5, targetX, targetY){
var shoot = setInterval(function() {
check_if_bullet_hit_player(bulletRef).then(player_got_shot_id => {
if (player_got_shot_id != ""){
clearInterval(shoot);
bulletRef.remove();
hitPlayerRef = firebase.database().ref(`players/${player_got_shot_id}`);
return hitPlayerRef.get(); // HERE we chain the promise
}
}).then(hola => {
hola.remove();
})
})
}
But nothing happens.
How can I make the player got hit to disappear?
An Example I have linked below, that shows the problem I have.
My Problem
I have these two functions
const updatedDoc = checkForHeadings(stoneCtx, documentCtx); // returns object
documentCtx.setUserDocument(updatedDoc); // uses object to update state
and
convertUserDocument(stoneCtx, documentCtx.userDocument);
// uses State for further usage
The Problem I have is, that convertUserDocument runs with an empty state and throws an error and then runs again with the updated state. Since it already throws an error, I cannot continue to work with it.
I have tried several different approaches.
What I tried
In the beginning my code looked like this
checkForHeadings(stoneCtx, documentCtx);
// updated the state witch each new key:value inside the function
convertUserDocument(stoneCtx, documentCtx.userDocument);
// then this function was run; Error
Then I tried the version I had above, to first put everything into an object and update the state only once.
HavingconvertUserDocument be a callback inside of checkForHeadings, but that ran it that many times a matching key was found.
My current try was to put the both functions in seperate useEffects, one for inital render and one for the next render.
const isFirstRender = useRef(true);
let init = 0;
useEffect(() => {
init++;
console.log('Initial Render Number ' + init);
console.log(documentCtx);
const updatedDoc = checkForHeadings(stoneCtx.stoneContext, documentCtx);
documentCtx.setUserDocument(updatedDoc);
console.log(updatedDoc);
console.log(documentCtx);
isFirstRender.current = false; // toggle flag after first render/mounting
console.log('Initial End Render Number ' + init);
}, []);
let update = 0;
useEffect(() => {
update++;
console.log('Update Render Number ' + update);
if (!isFirstRender.current) {
console.log('First Render has happened.');
convertUserDocument(stoneCtx.stoneContext, documentCtx.userDocument);
}
console.log('Update End Render Number ' + update);
}, [documentCtx]);
The interesting part with this was to see the difference between Codesandbox and my local development.
On Codesandbox Intial Render was called twice, but each time the counter didn't go up, it stayed at 1. On the other hand, on my local dev server, Initial Render was called only once.
On both version the second useEffect was called twice, but here also the counter didn't go up to 2, and stayed at 1.
Codesandbox:
Local Dev Server:
Short example of that:
let counter = 0;
useEffect(()=> {
counter++;
// this should only run once, but it does twice in the sandbox.
// but the counter is not going up to 2, but stays at 1
},[])
The same happens with the second useEffect, but on the second I get different results, but the counter stays at 1.
I was told this is due to a Stale Cloruse, but doesn't explain why the important bits don't work properly.
I got inspiration from here, to skip the initial render: https://stackoverflow.com/a/61612292/14103981
Code
Here is the Sandbox with the Problem displayed: https://codesandbox.io/s/nameless-wood-34ni5?file=/src/TextEditor.js
I have also create it on Stackblitz: https://react-v6wzqv.stackblitz.io
The error happens in this function:
function orderDocument(structure, doc, ordered) {
structure.forEach((el) => {
console.log(el.id);
console.log(doc);
// ordered.push(doc[el.id].headingHtml);
// if (el.children?.length) {
// orderDocument(el.children, doc, ordered);
// }
});
return ordered;
}
The commented out code throws the error. I am console.loggin el.id and doc, and in the console you can see, that doc is empty and thus cannot find doc[el.id].
Someone gave me this simple example to my problem, which sums it up pretty good.
useEffect(() => {
documentCtx.setUserDocument('ANYTHING');
console.log(documentCtx.userDocument);
});
The Console:
{}
ANYTHING
You can view it here: https://stackblitz.com/edit/react-f1hwky?file=src%2FTextEditor.js
I have come to a solution to my problem.
const isFirstRender = useRef(true);
useEffect(() => {
const updatedDoc = checkForHeadings(stoneCtx.stoneContext, documentCtx);
documentCtx.setUserDocument(updatedDoc);
}, []);
useEffect(() => {
if (!isFirstRender.current) {
convertUserDocument(stoneCtx.stoneContext, documentCtx.userDocument);
} else {
isFirstRender.current = false;
}
}, [documentCtx]);
Moving isFirstRender.current = false; to an else statement actually gives me the proper results I want.
Is this the best way of achieving it, or are there better ways?
The p5.js sound library documentation says that removeCue() can be used to cancel cued events. It says it takes an ID input that is returned from addCue().
When I invoke addCue and store the result to a variable it does not return an ID. It returns NaN.
The image below is a code example I wrote using the p5.js code editor.
How do I get the id ?
OK, i found the issue.
Its an issue with the library https://github.com/processing/p5.js/blob/master/lib/addons/p5.sound.js
look at this link https://github.com/processing/p5.js/blob/master/lib/addons/p5.sound.js#L2178
its using var id = this._cueIDCounter++; but _cueIDCounter was never defined.
so i tried to define it like the following for your code:
Object.defineProperty(mySound,'_cueIDCounter',{value:1,writable:true});
now it returned the id.
so then i tried to remove the cue with removeCue but to my surprise there is also an issue which is getting error Uncaught TypeError: Cannot read property 'splice' of undefined
so then i looked again at the library code and i realised on the following line https://github.com/processing/p5.js/blob/master/lib/addons/p5.sound.js#L2198 within the removeCue function there is an error the current code is
p5.SoundFile.prototype.removeCue = function (id) {
var cueLength = this._cues.length;
for (var i = 0; i < cueLength; i++) {
var cue = this._cues[i];
if (cue.id === id) {
this.cues.splice(i, 1);
}
}
if (this._cues.length === 0) {
}
};
but it should be using this._cues.splice(i, 1); instead of this.cues.splice(i, 1);
I am using PDFJS to get textual data from PDF files, but occasionally encountering the following error:
Error: Invalid XRef table: unexpected first object.
I would prefer that my code just skip over problem files and continue on to the next file in the list. According to PDFJS documentation, setting stopAtErrors to true for the DocumentInitParameters in PDFJS should result in rejection of getTextContent when the associated PDF data cannot be successfully parsed. I am not finding such to be the case: even after setting stopAtErrors to true, I continue to get the above error and the code seems to be "spinning" on the problem file rather than just moving on to the next in the list. It is possible that I haven't properly set stopAtErrors to true as I think I have. A snippet of my code is below to illustrate what I think I've done (code based on this example):
// set up the variables to pass to getDocument, including the pdf file's url:
var obj = {};
obj.url = http://www.whatever.com/thefile.pdf; // the specific url linked to desired pdf file goes here
obj.stopAtErrors = true;
// now have PDF JS read in the file:
PDFJS.getDocument(obj).then(function(pdf) {
var pdfDocument = pdf;
var pagesPromises = [];
for (var i = 0; i < pdf.pdfInfo.numPages; i++) {
(function (pageNumber) {
pagesPromises.push(getPageText(pageNumber, pdfDocument));
}) (i+1);
}
Promise.all(pagesPromises).then(function(pagesText) {
// display text of all the pages in the console
console.log(pagesText);
});
}, function (reason) {
console.log('Error! '+reason);
});
function getPageText(pageNum, PDFDocumentInstance) {
return new Promise(function (resolve, reject) {
PDFDocumentInstance.getPage(pageNum).then(function(pdfPage) {
pdfPage.getTextContent().then(function(textContent) { // should stopAtErrors somehow be passed here to getTextContent instead of to getDocument??
var textItems = textContent.items;
var finalString = '';
for (var i = 0; i < textItems.length; i++) {
var item = textItems[i];
finalString += item.str + " ";
}
resolve(finalString);
});
});
}).catch(function(err) {
console.log('Error! '+err);
});
}
One thing I am wondering is if the stopAtErrors parameter should somehow instead be passed to getTextContent? I have not found any examples illustrating the use of stopAtErrors and the PDFJS documentation does not show a working example, either. Given that I am still at the stage of needing examples to get PDFJS to function, I am at a loss as to how to make PDFJS stop trying to parse a problem PDF file and just move on to the next one.
I am working with pngjs through many of it's methods. Most of the time, they work fine. However, like in the following example, I get an error: "Stream is not writable"
var fs = require('fs'),
PNG = require('pngjs').PNG;
var dst = new PNG({width: 100, height: 50});
fs.createReadStream('http://1.1m.yt/hry7Eby.png') //download this picture in order to examine the code.
.pipe(new PNG())
.on('parsed', function(data) {
console.log(data);
});
This case is not singular, I get this error on 1 random png image once a day, through all of pngjs methods, and that error obviously crashes my app.
(note: you can't use the http link I gave you with a readStream, you will have to download & rename it and do something like):
fs.createReadStream('1.png')
Thank you for your time and effort.
This seems to be a bug in the library, though I'm wary of saying so as I'm no expert in PNGs. The parser seems to complete while the stream is still writing. It encounters the IEND, and so calls this:
ParserAsync.prototype._finished = function() {
if (this.errord) {
return;
}
if (!this._inflate) {
this.emit('error', 'No Inflate block');
}
else {
// no more data to inflate
this._inflate.end();
}
this.destroySoon();
};
If you comment out the this.destroySoon(); it finishes the image correctly, instead of eventually calling this function:
ChunkStream.prototype.end = function(data, encoding) {
if (data) {
this.write(data, encoding);
}
this.writable = false;
// already destroyed
if (!this._buffers) {
return;
}
// enqueue or handle end
if (this._buffers.length === 0) {
this._end();
}
else {
this._buffers.push(null);
this._process();
}
};
...which would otherwise end up setting the stream.writeable to false, or, if you comment that out, to pushing a null value into the _buffers array and screwing up the ChunkStream._processRead.
I'm fairly certain this is a synchronicity problem between the time the zlib parser takes to complete and the time the stream takes to complete, since if you do this synchronously it works fine:
var data = fs.readFileSync('pic.png');
var png = PNG.sync.read(data);
var buff = PNG.sync.write(png);
fs.writeFileSync('out2.png', buff);