Tensor shape must be [-1,-1,-1,3] but was [X,XXX,XXXX,X]? - javascript

I'm new to JS (especially to Node and tfjs) and I want to convert my image into a tensor.
But whenever I try to do so, I get this error:
UnhandledPromiseRejectionWarning: Error: The shape of dict['image_tensor'] provided in model.execute(dict) must be [-1,-1,-1,3], but was [1,628,1100,4]
Here's my code:
async function gotMessage(msg) {
if(msg.content === '!object') {
const attachments = (msg.attachments).array();
const filepath = "./images/" + Date.now() + "J" + ".png";
console.log(filepath);
const imageurl = attachments[0].url;
await saveImageToDisk(imageurl,filepath)
let img_buffer = fs.readFileSync(filepath)
const img = tf.node.decodePng(img_buffer)
coco.load().then(model => {
// detect objects in the image.
model.detect(img).then(predictions => {
console.log('Predictions: ', predictions);
});
});
msg.reply('Enjoy');
msg.channel.send(attachments[0].url);
}
}
async function saveImageToDisk(url,path) {
return new Promise((resolve, reject) => {
var fullUrl = url;
var localPath = fs.createWriteStream(path);
var request = https.get(fullUrl,function(response) {
//console.log(response)
response.pipe(localPath)
response.on('end', resolve);
}).on('error', reject);
});
}

decodePng returns a 4D array. If you want to use it for training your model, just pass
expand_animations=True to decodePng. It will return a 3D array.
Tensorflow doc on decodePng

Related

Execute a new set of fetches only after the earlier set has ran trough

I'm trying to fetch images for a live camera feed web page from an API. The problem is that with just timed fetch request, eventually one of the API responds takes so long that the code errors. The page has multiple camera feeds that are simultaneously refreshing with the loop for all the cameras in the cameraObjects[] array. The image() function should respond with a resolve that would then be collected in to an array promises[].
Put simply I need to run the refreshImages() function when ALL the image() functions called by the loop in updateImages() have been ran. I have just started coding so bare with me...
class camera {
constructor(Uuid,url,username,password) {
this.Uuid = Uuid;
this.url = url;
this.username = username;
this.password = password;
}
image() {
let uuid = this.Uuid
let url = this.url
let username = this.username
let password = this.password
let headers = new Headers();
let authString = `${username}:${password}`;
headers.set('Authorization', 'Basic ' + btoa(authString));
let imageUrl = url + uuid
fetch(imageUrl,{method: 'GET', headers: headers})
.then(response => response.blob())
.then(image => {
console.log(image);
var reader = new FileReader();
reader.readAsDataURL(image);
reader.onloadend = function() {
var base64data = reader.result;
let img = document.getElementById("camera_" + uuid);
img.src = base64data;
return new Promise(function(resolve) {
resolve(promise);
})
}
})
}
}
function updateImages() {
cameraObjects = listOfCameraObjects();
let promises = [];
for(let e = 0; e < cameraObjects.length; e++) {
let promise = new Promise(cameraObjects[e].image())
promises.push(promise)
}
Promise.all(promises)
.then(() => {
refreshImages();
})
}
function refreshImages() {
let currentInterval = getInterval();
refrehInterval = setTimeout(updateImages, currentInterval);
console.log(refrehInterval)
}
There a few things you're doing wrong with Promises -
return new Promise(function(resolve) {
resolve(promise);
})
That's sort of OK though return Promise.resolve(promise) is identical - however in your code, what is promise? not declared anywhere in that scope - also, as the last code in an event handler (onloadend) it is pointless, since returning a value from an event handler is meaningless
let promise = new Promise(cameraObjects[e].image())
that's not how you construct a promise ... the argument to the promise constructor needs to be a function, not the result of calling a function (unless that returns a function, of course, but it doesn't)
I'd suggest you perhaps read some docs about how you construct a Promise, and how you then use them
In the meantime, I believe this code will do what you want
class camera {
constructor(Uuid,url,username,password) {
this.Uuid = Uuid;
this.url = url;
this.username = username;
this.password = password;
}
image() {
const headers = new Headers();
const authString = `${this.username}:${this.password}`;
headers.set('Authorization', 'Basic ' + btoa(authString));
const imageUrl = this.url + this.Uuid;
return fetch(imageUrl, {method: 'GET', headers: headers})
.then(response => response.blob())
.then(image => new Promise((resolve, reject) {
const reader = new FileReader();
reader.readAsDataURL(image);
reader.addEventListener('loadend', () => {
const img = document.getElementById("camera_" + uuid);
img.src = reader.result;
resolve();
});
reader.addEventListener('error', reject);
}));
}
}
function updateImages() {
Promise.all(listOfCameraObjects().map(cam => cam.image()))
.then(refreshImages);
}
function refreshImages() {
let currentInterval = getInterval();
refrehInterval = setTimeout(updateImages, currentInterval);
console.log(refrehInterval)
}

Awat doesn't wait for async

I'm new to async and await, I have a simple web app with firebase which gets files through input fields and upload them to the firebase via a button click but when I click button it does,t wait for async function to uload the files at first click. But when I click second time the files uploaded and I got the expected output. How can I solve this?
Here are my codes
Upload Function
async function uploadImages() {
var storageRef = firebase.storage().ref();
var uploadImages = document.getElementsByName("fupload").forEach((element) => {
var imageRef = storageRef.child(
"projects/" + projectName + "/" + (element as HTMLInputElement).files[0].name
);
let file = (element as HTMLInputElement).files[0];
imageRef.put(file).then((snapshot) => {
snapshot.ref.getDownloadURL().then(function (downloadURL) {
paragraphUrl.push(downloadURL);
});
});
});
if (document.getElementsByName("fupload").length == paragraphUrl.length) {
return paragraphUrl;
} else {
return 1;
}
}
Button click function
async function upload(){
await uploadImages().then((data) => {
if (data != 1) {
paragraphData = paragraphData.map(
function (x, i) {
return {
Title: x.Title,
Paragraph: x.Paragraph,
Image: data[i],
};
}.bind(this)
);
console.log(paragraphData);
//dispatch("paragraphData",{data})
} else {
console.log("d");
}
});
}
Thank you all I fixed the problem I'll add my code below.
Upload function
async function uploadImages() {
var storageRef = firebase.storage().ref();
for (const file of document.getElementsByName("fupload")) {
// let test = (file as HTMLInputElement).files[0].name;
// console.log(test);
var imageRef = storageRef.child(
"projects/" + projectName + "/" + (file as HTMLInputElement).files[0].name
);
let test = (file as HTMLInputElement).files[0].name;
let testFile = (file as HTMLInputElement).files[0];
await imageRef.put(testFile).then((snapshot) => {
snapshot.ref.getDownloadURL().then(function (downloadURL) {
paragraphUrl.push(downloadURL);
});
});
}
return paragraphUrl;
}
Button Click function
async function submitParagraphData() {
paragraphTitles = [];
paragraphs = [];
var e = document.getElementsByName("ParagrphTitle").forEach((element) => {
paragraphTitles.push((element as HTMLInputElement).value);
});
var f = document.getElementsByName("Paragraph").forEach((element) => {
paragraphs.push((element as HTMLInputElement).value);
});
let paragraphData = paragraphTitles.map(
function (x, i) {
return { Title: x, Paragraph: paragraphs[i] };
}.bind(this)
);
await uploadImages().then((data) => {
console.log(data);
});
}
The problem I had was when I click the button it displayed an empty array because file upload takes some time but when I click second time it displays the expected output because file was uploaded. So I added await to the line
imageRef.put(testFile) ............
So it fixed my problem.Thank you all for the support.

node.js convert xml to json

I want to convert xml compressed zip file to json file.
I used these.
https://www.npmjs.com/package/unzip
https://www.npmjs.com/package/xml2json
'use strict';
let fs = require('fs')
let unzip = require('unzip')
let parser = require('xml2json');
let originalFilePath = process.argv[2];
let XMLFileName = originalFilePath.replace(/^.*[\\\/]/, '').replace('.zip', '')
let XMLFileDirectory = '/users/*****/desktop/templatexml/' + XMLFileName + '/'
let XMLFilePath = '/users/*****/desktop/templatexml/' + XMLFileName + '/doc.xml'
let jsonFilePath = '/users/*****/desktop/templatexml/' + XMLFileName + '/doc.json'
convertToXML(originalFilePath).then(() => { createJson(jsonData) })
function convertToXML(filePath) {
return new Promise(() => {
fs.createReadStream(filePath).pipe(unzip.Extract({ path: XMLFileDirectory }))
})
}
function createJson(jsonData) {
fs.writeFile(jsonFilePath, JSON.stringify(jsonData, null, ' '))
}
I got error.
DeprecationWarning: Unhandled promise rejections are deprecated. In
the future, promise rejections that are not handled will terminate the
Node.js process with a non-zero exit code.
Please help me.
convertToXML and createJson is properly.
But I have to use promise , since I have to run createJson after xml file was created.
But I am having trouble using promise.
Sorry I forgot to write these
let XMLFileData = fs.readFileSync(XMLFilePath, 'utf-8')
let jsonData = parser.toJson(XMLFileData)
Now my code is like this.
'use strict';
let fs = require('fs')
let unzip = require('unzip')
let parser = require('xml2json');
let originalFilePath = process.argv[2];
let XMLFileName = originalFilePath.replace(/^.*[\\\/]/, '').replace('.zip', '')
let XMLFileDirectory = '/users/*****/desktop/templatexml/' + XMLFileName + '/'
let XMLFilePath = '/users/*****/desktop/templatexml/' + XMLFileName + '/doc.xml'
let jsonFilePath = '/users/*****/desktop/templatexml/' + XMLFileName + '/doc.json'
convertToXML(originalFilePath).then(() => {
let XMLFileData = fs.readFileSync(XMLFilePath, 'utf-8')
let jsonData = parser.toJson(XMLFileData)
createJson(jsonData)
})
function convertToXML(filePath) {
return new Promise((resolve, reject) => {
fs.createReadStream(filePath).pipe(unzip.Extract({ path: XMLFileDirectory }))
})
}
function createJson(jsonData) {
fs.writeFile(jsonFilePath, JSON.stringify(jsonData, null, ' '))
}
doc.xml would be created but doc.json won't be created.
Thank you so much I did like this.
But I got an error.
DeprecationWarning: Calling an asynchronous function without callback
is deprecated.
convertToXML(originalFilePath)
function convertToXML(filePath) {
fs.createReadStream(filePath).pipe(unzip.Extract({
path: XMLFileDirectory
})).on('close', function() {
createJson()
});
}
function createJson() {
let XMLFileData = fs.readFileSync(XMLFilePath, 'utf-8')
let jsonData = parser.toJson(XMLFileData)
fs.writeFile(jsonFilePath, JSON.stringify(jsonData, null, ' '))
}
I think this error happens because there is no xmlfile.
I still can't run createJson() after xmlFile is created.
Now I made correct code.
I had to change
"fs.writeFile"
to
"fs.writeFileSync"
Thank you so much!!!!!
Change this line new Promise
From:
return new Promise(() => {
}
To:
return new Promise((resolve, reject) => {
fs.createReadStream(filePath).pipe(unzip.Extract({
path: XMLFileDirectory
})).on('close', function () {
resolve();
});
})
Updated:
From the github README
Extract emits the 'close' event once the zip's contents have been
fully extracted to disk.
More detail about unzip at here

How to correctly implement a .then promise [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
How do I convert an existing callback API to promises?
(24 answers)
Closed 5 years ago.
How could I implement a .then promise, so once this function runs I have something inside of the array?
I can console.log the results into the function and I believe it returns the results correctly, however the res.json results will show an empty array. Which I assume is because it loads quicker than the function finishes.
const {grabArticles} = require('../controller/update.js');
// variables
const router = express.Router();
router.get('/new', (err, res) => {
const results = [];
const test = grabArticles(results)
test.then((results) => {
res.json(results);
})
});
//different file
const request = require('request');
const cheerio = require('cheerio');
grabArticles = (results) => {
// const results = [];
request("https://fivethirtyeight.com/", function(error, response, html) {
const $ = cheerio.load(html);
for (x=1; x<4; x++) {
// i is the current loop number, element=this is the current data requested
$('#home-feature-' + x.toString()).each((i, element) => {
const topic = $(element).children('.post-info').children('.topic').text().trim();
const title = $(element).children('.post-info').children('.tease-meta').children('.tease-meta-content').children('h2.article-title.entry-title').text().trim();
// console.log('topic: ' + topic + '\n' + 'title: ' + title);
const newArticle = {
topic: topic,
title: title
};
results.push(newArticle);
})
}
console.log('inside update.js' + results);
});
return results;
}
You need to return a Promise, which then resolves the results. The value of results will then be passed to your then callback as the first parameter.
Untested but it will look something like this:
//different file
const request = require('request');
const cheerio = require('cheerio');
grabArticles = (results) => {
// const results = [];
return new Promise(function(resolve) {
request("https://fivethirtyeight.com/", function(error, response, html) {
const $ = cheerio.load(html);
for (x = 1; x < 4; x++) {
// i is the current loop number, element=this is the current data requested
$('#home-feature-' + x.toString()).each((i, element) => {
const topic = $(element).children('.post-info').children('.topic').text().trim();
const title = $(element).children('.post-info').children('.tease-meta').children('.tease-meta-content').children('h2.article-title.entry-title').text().trim();
// console.log('topic: ' + topic + '\n' + 'title: ' + title);
const newArticle = {
topic: topic,
title: title
};
results.push(newArticle);
})
}
console.log('inside update.js' + results);
//////////////////////////
/// Resolve the promise here
/// the then() will get triggered
//////////////////////////
resolve(results);
});
});
}
A very simplified version would look like this:
// This function returns a Promise
function doSomethingAysnc(){
return new Promise(function(resolve){
request('/my/url', function(data){
// When we are staisfied with ending the promise
// We resolve it so the calling function can then
// handle the rest
return resolve(data);
});
});
}
// Here we will call our async function
// Once the promise resolves
// We get our data back for further usage
doSomethingAysnc().then(function(data){
// We can the access the data here
console.log(data);
});
Rewrite your grabArticles using Promise like this.
grabArticles = (results) => {
return new Promise((resolve, reject) => {
request("https://fivethirtyeight.com/", function(error, response, html) {
const $ = cheerio.load(html);
for (x=1; x<4; x++) {
// i is the current loop number, element=this is the current data requested
$('#home-feature-' + x.toString()).each((i, element) => {
const topic = $(element).children('.post-info').children('.topic').text().trim();
const title = $(element).children('.post-info').children('.tease-meta').children('.tease-meta-content').children('h2.article-title.entry-title').text().trim();
// console.log('topic: ' + topic + '\n' + 'title: ' + title);
const newArticle = {
topic: topic,
title: title
};
results.push(newArticle);
})
}
console.log('inside update.js' + results);
// return result using resolve, otherwise using reject(error) to reflect something wrong
resolve(results);
});
});
}

NodeJS Waiting for asynchronous function to complete foreach

Hi so i have been trying to make this tried using async module didn't really know how to convert this to one tried promising it didn't really work well i think i did it wrong so i reverted the function to the way it was at first
Basically i want to wait till the ReadJson() function is done with reading all the json files that are in the array then do other functions like editjson etc
Code:
App.js
const Reader = require('./Reader');
Reader.ReadJson();
Reader.js
const fsp = require('fs-promise');
const JsonFiles = ['json1.json', 'json2.json', 'json3.json', 'json4.json'];
const JsonContents = [];
class Reader {
static ReadJson() {
JsonFiles.forEach(name => {
let FileDir = "D:\\Development\\Java\\" + name;
fsp.readJson(FileDir).then(contents => {
if (contents) {
JsonContents.push(contents);
console.log(`Loaded >> ${name} ${Reader.JsonContents.length}/${JsonFiles.length}`);
}
});
});
console.log('Done Reading Json Content!');
//Other functions
}
}
Reader.JsonContents = JsonContents;
module.exports = Reader;
So basically the output is:
Done Reading Json Content!
Loaded >> json1.json 1/4
Loaded >> json2.json 2/4
Loaded >> json3.json 3/4
Loaded >> json4.json 4/4
When i need it to be:
Loaded >> json1.json 1/4
Loaded >> json2.json 2/4
Loaded >> json3.json 3/4
Loaded >> json4.json 4/4
Done Reading Json Content!
Thank you :)
Return a promise, track your progress in the forEach and resolve it only when JsonContents length is the same as JsonFiles length.
const fsp = require('fs-promise');
const JsonFiles = ['json1.json', 'json2.json', 'json3.json', 'json4.json'];
const JsonContents = [];
class Reader {
static ReadJson() {
return new Promise((resolve, reject) => {
JsonFiles.forEach(name => {
let FileDir = "D:\\Development\\Java\\" + name;
fsp.readJson(FileDir).then(contents => {
if (contents) {
JsonContents.push(contents);
console.log(`Loaded >> ${name} ${Reader.JsonContents.length}/${JsonFiles.length}`);
}
if (JsonContents.length == JsonFile.length) {
return resolve(JsonContents);
}
}).catch(err => {
return reject(err);
});
});
});
}
}
Reader.JsonContents = JsonContents;
module.exports = Reader;
And then use it in your app:
const Reader = require('./Reader');
Reader.ReadJson().then(() => { console.log('Done Reading Json Content!'); });
Another option is using Promise.all, because you are using fs-promise, but although it can be done with forEach, a regular for loop is better here.
const fsp = require('fs-promise');
const JsonFiles = ['json1.json', 'json2.json', 'json3.json', 'json4.json'];
const JsonContents = [];
class Reader {
static ReadJson() {
var promises = [];
for (let i = 0; i < JsonFiles.length; i++) {
let FileDir = "D:\\Development\\Java\\" + JsonFiles[i];
promises.push(fsp.readJson(FileDir).then(contents => {
if (contents) {
JsonContents.push(contents);
console.log(`Loaded >> ${JsonFiles[i]} ${Reader.JsonContents.length}/${JsonFiles.length}`);
}
}));
}
return Promise.all(promises);
}
}
Reader.JsonContents = JsonContents;
module.exports = Reader;
As an addendum to Ron Dadon's Promise.all method....
The Bluebird promise library provides some helper functions like Promise.map and Promise.filter that can remove a lot of the boiler plate of Promise array processing code.
const Promise = require('bluebird');
const fsp = require('fs-promise');
const path = require('path');
class Reader {
static readFiles(jsonPath, jsonFiles){
let fileReadCount = 0;
return Promise.map(jsonFiles, name => {
let filePath = path.join(jsonPath, name);
return fsp.readJson(filePath);
})
.filter((content, index, length) => {
if (!content) return false;
console.log(`Loaded >> ${jsonFiles[index]} ${index+1} / ${length}`);
return true;
})
}
static readJson() {
return this.readFiles(this.jsonPath, this.jsonFiles).then(contents => {
console.log('Done Reading Json Content!', contents);
return this.jsonContents = contents;
})
}
}
Reader.jsonFiles = ['json1.json', 'json2.json', 'json3.json', 'json4.json'];
Reader.jsonPath = 'D:\\Development\\Java';
module.exports = Reader;

Categories

Resources