AWS Rekognition JavaScript SDK using Bytes
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
The AWS Rekognition Javascript API states that for rekognition.compareFaces(params,...)
method, the SourceImage
and TargetImage
can take Bytes
or S3Object
. I want to use the Bytes
which can be
"Bytes — (Buffer, Typed Array, Blob, String)"
Blob of image bytes up to 5 MBs.
When I pass the Base64
encoded string of the images, the JS SDK is re-encoding again (i.e double encoded). Hence server responding with error saying
{"__type":"InvalidImageFormatException","Message":"Invalid image
encoding"}
Did anyone manage to use the compareFaces JS SDK API using base64 encoded images (not S3Object
)? or any JavaScript examples using Bytes
param would help.
javascript amazon-web-services sdk base64 amazon-rekognition
add a comment |
The AWS Rekognition Javascript API states that for rekognition.compareFaces(params,...)
method, the SourceImage
and TargetImage
can take Bytes
or S3Object
. I want to use the Bytes
which can be
"Bytes — (Buffer, Typed Array, Blob, String)"
Blob of image bytes up to 5 MBs.
When I pass the Base64
encoded string of the images, the JS SDK is re-encoding again (i.e double encoded). Hence server responding with error saying
{"__type":"InvalidImageFormatException","Message":"Invalid image
encoding"}
Did anyone manage to use the compareFaces JS SDK API using base64 encoded images (not S3Object
)? or any JavaScript examples using Bytes
param would help.
javascript amazon-web-services sdk base64 amazon-rekognition
1
I am also looking for an answer to how to do this as I have been unable to do this. I have tried using Base64 encoded string with same result as above as well have tried converting it to a Uint8array, Blob, & ArrayBuffer still with no success. Does anyone have an example that works? My source data is in a HTML5 Canvas object.
– Michael Dennis
May 26 '17 at 16:50
Related and Solved: stackoverflow.com/questions/43599556/…
– srikanth Nutigattu
Jul 30 '18 at 19:47
add a comment |
The AWS Rekognition Javascript API states that for rekognition.compareFaces(params,...)
method, the SourceImage
and TargetImage
can take Bytes
or S3Object
. I want to use the Bytes
which can be
"Bytes — (Buffer, Typed Array, Blob, String)"
Blob of image bytes up to 5 MBs.
When I pass the Base64
encoded string of the images, the JS SDK is re-encoding again (i.e double encoded). Hence server responding with error saying
{"__type":"InvalidImageFormatException","Message":"Invalid image
encoding"}
Did anyone manage to use the compareFaces JS SDK API using base64 encoded images (not S3Object
)? or any JavaScript examples using Bytes
param would help.
javascript amazon-web-services sdk base64 amazon-rekognition
The AWS Rekognition Javascript API states that for rekognition.compareFaces(params,...)
method, the SourceImage
and TargetImage
can take Bytes
or S3Object
. I want to use the Bytes
which can be
"Bytes — (Buffer, Typed Array, Blob, String)"
Blob of image bytes up to 5 MBs.
When I pass the Base64
encoded string of the images, the JS SDK is re-encoding again (i.e double encoded). Hence server responding with error saying
{"__type":"InvalidImageFormatException","Message":"Invalid image
encoding"}
Did anyone manage to use the compareFaces JS SDK API using base64 encoded images (not S3Object
)? or any JavaScript examples using Bytes
param would help.
javascript amazon-web-services sdk base64 amazon-rekognition
javascript amazon-web-services sdk base64 amazon-rekognition
edited Jan 5 at 20:31
jgraup
605811
605811
asked Apr 19 '17 at 11:40
srikanth Nutigattusrikanth Nutigattu
629514
629514
1
I am also looking for an answer to how to do this as I have been unable to do this. I have tried using Base64 encoded string with same result as above as well have tried converting it to a Uint8array, Blob, & ArrayBuffer still with no success. Does anyone have an example that works? My source data is in a HTML5 Canvas object.
– Michael Dennis
May 26 '17 at 16:50
Related and Solved: stackoverflow.com/questions/43599556/…
– srikanth Nutigattu
Jul 30 '18 at 19:47
add a comment |
1
I am also looking for an answer to how to do this as I have been unable to do this. I have tried using Base64 encoded string with same result as above as well have tried converting it to a Uint8array, Blob, & ArrayBuffer still with no success. Does anyone have an example that works? My source data is in a HTML5 Canvas object.
– Michael Dennis
May 26 '17 at 16:50
Related and Solved: stackoverflow.com/questions/43599556/…
– srikanth Nutigattu
Jul 30 '18 at 19:47
1
1
I am also looking for an answer to how to do this as I have been unable to do this. I have tried using Base64 encoded string with same result as above as well have tried converting it to a Uint8array, Blob, & ArrayBuffer still with no success. Does anyone have an example that works? My source data is in a HTML5 Canvas object.
– Michael Dennis
May 26 '17 at 16:50
I am also looking for an answer to how to do this as I have been unable to do this. I have tried using Base64 encoded string with same result as above as well have tried converting it to a Uint8array, Blob, & ArrayBuffer still with no success. Does anyone have an example that works? My source data is in a HTML5 Canvas object.
– Michael Dennis
May 26 '17 at 16:50
Related and Solved: stackoverflow.com/questions/43599556/…
– srikanth Nutigattu
Jul 30 '18 at 19:47
Related and Solved: stackoverflow.com/questions/43599556/…
– srikanth Nutigattu
Jul 30 '18 at 19:47
add a comment |
5 Answers
5
active
oldest
votes
The technique from this AWS Rekognition JS SDK Invalid image encoding error thread worked.
Convert the base64 image encoding to a ArrayBuffer:
function getBinary(base64Image) {
var binaryImg = atob(base64Image);
var length = binaryImg.length;
var ab = new ArrayBuffer(length);
var ua = new Uint8Array(ab);
for (var i = 0; i < length; i++) {
ua[i] = binaryImg.charCodeAt(i);
}
return ab;
}
Pass into rekognition as Bytes
parameter:
var data = canvas.toDataURL('image/jpeg');
var base64Image = data.replace(/^data:image/(png|jpeg|jpg);base64,/, '');
var imageBytes = getBinary(base64Image);
var rekognitionRequest = {
CollectionId: collectionId,
Image: {
Bytes: imageBytes
}
};
add a comment |
Based on the answer supplied by @Sean, I wanted to add another way to get the bytes from a URL request using axios and passed to rekognition.detectLabels()
-- or other various detection methods for Amazon Rekognition.
I went ahead create a promise for fs.readFile
that should work with the async/await structure. Then some regex to determine if you need a URL fetch or file read as a fallback.
I've also added a check for Gray
and World Of Warcraft
for the labels. Not sure if anyone else experiences that but lorempixel seems to throw those labels every once in a while. I've seen them show on an all black image before as well.
/* jshint esversion: 6, node:true, devel: true, undef: true, unused: true */
const AWS = require('aws-sdk'),
axios = require('axios'),
fs = require('fs'),
path = require('path');
// Get credentials from environmental variables.
const {S3_ACCESS_KEY, S3_SECRET_ACCESS_KEY, S3_REGION} = process.env;
// Set AWS credentials.
AWS.config.update({
accessKeyId: S3_ACCESS_KEY,
secretAccessKey: S3_SECRET_ACCESS_KEY,
region: S3_REGION
});
const rekognition = new AWS.Rekognition({
apiVersion: '2016-06-27'
});
startDetection();
// ----------------
async function startDetection() {
let found = {};
found = await detectFromPath(path.join(__dirname, 'test.jpg'));
console.log(found);
found = await detectFromPath('https://upload.wikimedia.org/wikipedia/commons/9/96/Bill_Nye%2C_Barack_Obama_and_Neil_deGrasse_Tyson_selfie_2014.jpg');
console.log(found);
found = await detectFromPath('http://placekitten.com/g/200/300');
console.log(found);
found = await detectFromPath('https://loremflickr.com/g/320/240/text');
console.log(found);
found = await detectFromPath('http://lorempixel.com/400/200/sports/');
console.log(found);
// Sometimes 'Grey' and 'World Of Warcraft' are the only labels...
if (found && found.labels.length === 2 && found.labels.some(i => i.Name === 'Gray') && found.labels.some(i => i.Name === 'World Of Warcraft')) {
console.log('⚠️', 'ntMaybe this is a bad image...`Gray` and `World Of Warcraft`???n');
}
}
// ----------------
/**
* @param {string} path URL or filepath on your local machine.
* @param {Number} maxLabels
* @param {Number} minConfidence
* @param {array} attributes
*/
async function detectFromPath(path, maxLabels, minConfidence, attributes) {
// Convert path to base64 Buffer data.
const bytes = (/^https?:///gm.exec(path)) ?
await getBase64BufferFromURL(path) :
await getBase64BufferFromFile(path);
// Invalid data.
if (!bytes)
return {
path,
faces: ,
labels: ,
text: ,
celebs: ,
moderation:
};
// Pass buffer to rekognition methods.
let labels = await detectLabelsFromBytes(bytes, maxLabels, minConfidence),
text = await detectTextFromBytes(bytes),
faces = await detectFacesFromBytes(bytes, attributes),
celebs = await recognizeCelebritiesFromBytes(bytes),
moderation = await detectModerationLabelsFromBytes(bytes, minConfidence);
// Filter out specific values.
labels = labels && labels.Labels ? labels.Labels : ;
faces = faces && faces.FaceDetails ? faces.FaceDetails : ;
text = text && text.TextDetections ? text.TextDetections.map(i => i.DetectedText) : ;
celebs = celebs && celebs.CelebrityFaces ? celebs.CelebrityFaces.map(i => ({
Name: i.Name,
MatchConfidence: i.MatchConfidence
})) : ;
moderation = moderation && moderation.ModerationLabels ? moderation.ModerationLabels.map(i => ({
Name: i.Name,
Confidence: i.Confidence
})) : ;
// Return collection.
return {
path,
faces,
labels,
text,
celebs,
moderation
};
}
/**
* https://nodejs.org/api/fs.html#fs_fs_readfile_path_options_callback
*
* @param {string} filename
*/
function getBase64BufferFromFile(filename) {
return (new Promise(function(resolve, reject) {
fs.readFile(filename, 'base64', (err, data) => {
if (err) return reject(err);
resolve(new Buffer(data, 'base64'));
});
})).catch(error => {
console.log('[ERROR]', error);
});
}
/**
* https://github.com/axios/axios
*
* @param {string} url
*/
function getBase64BufferFromURL(url) {
return axios
.get(url, {
responseType: 'arraybuffer'
})
.then(response => new Buffer(response.data, 'base64'))
.catch(error => {
console.log('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/labels.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectLabels-property
*
* @param {Buffer} bytes
* @param {Number} maxLabels
* @param {Number} minConfidence
*/
function detectLabelsFromBytes(bytes, maxLabels, minConfidence) {
return rekognition
.detectLabels({
Image: {
Bytes: bytes
},
MaxLabels: typeof maxLabels !== 'undefined' ? maxLabels : 1000,
MinConfidence: typeof minConfidence !== 'undefined' ? minConfidence : 50.0
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/text-detection.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectText-property
*
* @param {Buffer} bytes
*/
function detectTextFromBytes(bytes) {
return rekognition
.detectText({
Image: {
Bytes: bytes
}
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/celebrities.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#recognizeCelebrities-property
*
* @param {Buffer} bytes
*/
function recognizeCelebritiesFromBytes(bytes) {
return rekognition
.recognizeCelebrities({
Image: {
Bytes: bytes
}
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/moderation.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectModerationLabels-property
*
* @param {Buffer} bytes
* @param {Number} minConfidence
*/
function detectModerationLabelsFromBytes(bytes, minConfidence) {
return rekognition
.detectModerationLabels({
Image: {
Bytes: bytes
},
MinConfidence: typeof minConfidence !== 'undefined' ? minConfidence : 60.0
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/faces.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectFaces-property
*
* @param {Buffer} bytes
* @param {array} attributes Attributes can be "ALL" or "DEFAULT". "DEFAULT" includes: BoundingBox, Confidence, Landmarks, Pose, and Quality.
*/
function detectFacesFromBytes(bytes, attributes) {
return rekognition
.detectFaces({
Image: {
Bytes: bytes
},
Attributes: typeof attributes !== 'undefined' ? attributes : ['ALL']
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/API_CompareFaces.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#compareFaces-property
*
* @param {Buffer} sourceBytes
* @param {Buffer} targetBytes
* @param {Number} similarityThreshold
*/
function compareFaces(sourceBytes, targetBytes, similarityThreshold) {
return rekognition
.detectModerationLabels({
SourceImage: {
Bytes: sourceBytes
},
TargetImage: {
Bytes: targetBytes
},
SimilarityThreshold: typeof similarityThreshold !== 'undefined' ? similarityThreshold : 0.0
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
Resources:
- https://github.com/axios/axios
- https://docs.aws.amazon.com/rekognition/latest/dg/labels.html
- https://docs.aws.amazon.com/rekognition/latest/dg/text-detection.html
- https://docs.aws.amazon.com/rekognition/latest/dg/celebrities.html
- https://docs.aws.amazon.com/rekognition/latest/dg/moderation.html
- https://docs.aws.amazon.com/rekognition/latest/dg/faces.html
- https://docs.aws.amazon.com/rekognition/latest/dg/API_CompareFaces.html
- https://docs.aws.amazon.com/rekognition/latest/dg/image-bytes-javascript.html
AWS JavaScript SDK Reference:
- detectLabels
- detectText
- recognizeCelebrities
- detectModerationLabels
- detectFaces
- compareFaces
Reference:
- Download an image using Axios and convert it to base64
- Upload a binary file to S3 using AWS SDK for Node.js
- AWS Rekognition JS SDK Invalid image encoding error
- Pipe a stream to s3.upload()
- untarring files to S3 fails, not sure why
- Using Promises with fs.readFile in a loop
- How do I return the response from an asynchronous call?
- NodeJS UnhandledPromiseRejectionWarning
- How do I check whether an array contains a string in TypeScript?
- Do you need to use path.join in node.js?
add a comment |
I was running into a similar issue when reading in a file in Node as a byte array buffer and sending it to Rekognition.
I solved it by instead reading in the base64 representation, then turning it into a buffer like this:
const aws = require('aws-sdk');
const fs = require('fs');
var rekognition = new aws.Rekognition({
apiVersion: '2016-06-27'
});
// pull base64 representation of image from file system (or somewhere else)
fs.readFile('./test.jpg', 'base64', (err, data) => {
// create a new buffer out of the string passed to us by fs.readFile()
const buffer = new Buffer(data, 'base64');
// now that we have things in the right type, send it to rekognition
rekognition.detectLabels({
Image: {
Bytes: buffer
}
}).promise()
.then((res) => {
// print out the labels that rekognition sent back
console.log(res);
});
});
This might also be relevant to people getting the: Expected params.Image.Bytes to be a string, Buffer, Stream, Blob, or typed array object
message.
add a comment |
I had same issue you had and i'm going to tell you how i solved it.
Amazon Rekognition supports image type are JPEG and PNG
It means that if you input image file with encoding other formats like webp, you always get same that error.
After changing image formats which not encoding with jpeg or png to jpeg, i could solved that problem.
Hope you to solve this problem!
add a comment |
It seems that converting the string to a buffer works more consistently but documentation on it is very hard to find.
For Node, you can use this to convert the params from the string (make sure you take off the data... up to the ",".
var params = {
CollectionId: collectionId,
Image: {
Bytes: new Buffer(imageBytes, 'base64')
}
};
In normal JS, you'd want can convert with atob and pass the Array buffer using this code:
function getBinary(base64Image) {
var binaryImg = Buffer.from(base64Image, 'base64').toString();
var length = binaryImg.length;
var ab = new ArrayBuffer(length);
var ua = new Uint8Array(ab);
for (var i = 0; i < length; i++) {
ua[i] = binaryImg.charCodeAt(i);
}
return ab;
}
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f43494736%2faws-rekognition-javascript-sdk-using-bytes%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
The technique from this AWS Rekognition JS SDK Invalid image encoding error thread worked.
Convert the base64 image encoding to a ArrayBuffer:
function getBinary(base64Image) {
var binaryImg = atob(base64Image);
var length = binaryImg.length;
var ab = new ArrayBuffer(length);
var ua = new Uint8Array(ab);
for (var i = 0; i < length; i++) {
ua[i] = binaryImg.charCodeAt(i);
}
return ab;
}
Pass into rekognition as Bytes
parameter:
var data = canvas.toDataURL('image/jpeg');
var base64Image = data.replace(/^data:image/(png|jpeg|jpg);base64,/, '');
var imageBytes = getBinary(base64Image);
var rekognitionRequest = {
CollectionId: collectionId,
Image: {
Bytes: imageBytes
}
};
add a comment |
The technique from this AWS Rekognition JS SDK Invalid image encoding error thread worked.
Convert the base64 image encoding to a ArrayBuffer:
function getBinary(base64Image) {
var binaryImg = atob(base64Image);
var length = binaryImg.length;
var ab = new ArrayBuffer(length);
var ua = new Uint8Array(ab);
for (var i = 0; i < length; i++) {
ua[i] = binaryImg.charCodeAt(i);
}
return ab;
}
Pass into rekognition as Bytes
parameter:
var data = canvas.toDataURL('image/jpeg');
var base64Image = data.replace(/^data:image/(png|jpeg|jpg);base64,/, '');
var imageBytes = getBinary(base64Image);
var rekognitionRequest = {
CollectionId: collectionId,
Image: {
Bytes: imageBytes
}
};
add a comment |
The technique from this AWS Rekognition JS SDK Invalid image encoding error thread worked.
Convert the base64 image encoding to a ArrayBuffer:
function getBinary(base64Image) {
var binaryImg = atob(base64Image);
var length = binaryImg.length;
var ab = new ArrayBuffer(length);
var ua = new Uint8Array(ab);
for (var i = 0; i < length; i++) {
ua[i] = binaryImg.charCodeAt(i);
}
return ab;
}
Pass into rekognition as Bytes
parameter:
var data = canvas.toDataURL('image/jpeg');
var base64Image = data.replace(/^data:image/(png|jpeg|jpg);base64,/, '');
var imageBytes = getBinary(base64Image);
var rekognitionRequest = {
CollectionId: collectionId,
Image: {
Bytes: imageBytes
}
};
The technique from this AWS Rekognition JS SDK Invalid image encoding error thread worked.
Convert the base64 image encoding to a ArrayBuffer:
function getBinary(base64Image) {
var binaryImg = atob(base64Image);
var length = binaryImg.length;
var ab = new ArrayBuffer(length);
var ua = new Uint8Array(ab);
for (var i = 0; i < length; i++) {
ua[i] = binaryImg.charCodeAt(i);
}
return ab;
}
Pass into rekognition as Bytes
parameter:
var data = canvas.toDataURL('image/jpeg');
var base64Image = data.replace(/^data:image/(png|jpeg|jpg);base64,/, '');
var imageBytes = getBinary(base64Image);
var rekognitionRequest = {
CollectionId: collectionId,
Image: {
Bytes: imageBytes
}
};
edited Jan 4 at 15:35
jgraup
605811
605811
answered May 26 '17 at 19:07
Michael DennisMichael Dennis
185111
185111
add a comment |
add a comment |
Based on the answer supplied by @Sean, I wanted to add another way to get the bytes from a URL request using axios and passed to rekognition.detectLabels()
-- or other various detection methods for Amazon Rekognition.
I went ahead create a promise for fs.readFile
that should work with the async/await structure. Then some regex to determine if you need a URL fetch or file read as a fallback.
I've also added a check for Gray
and World Of Warcraft
for the labels. Not sure if anyone else experiences that but lorempixel seems to throw those labels every once in a while. I've seen them show on an all black image before as well.
/* jshint esversion: 6, node:true, devel: true, undef: true, unused: true */
const AWS = require('aws-sdk'),
axios = require('axios'),
fs = require('fs'),
path = require('path');
// Get credentials from environmental variables.
const {S3_ACCESS_KEY, S3_SECRET_ACCESS_KEY, S3_REGION} = process.env;
// Set AWS credentials.
AWS.config.update({
accessKeyId: S3_ACCESS_KEY,
secretAccessKey: S3_SECRET_ACCESS_KEY,
region: S3_REGION
});
const rekognition = new AWS.Rekognition({
apiVersion: '2016-06-27'
});
startDetection();
// ----------------
async function startDetection() {
let found = {};
found = await detectFromPath(path.join(__dirname, 'test.jpg'));
console.log(found);
found = await detectFromPath('https://upload.wikimedia.org/wikipedia/commons/9/96/Bill_Nye%2C_Barack_Obama_and_Neil_deGrasse_Tyson_selfie_2014.jpg');
console.log(found);
found = await detectFromPath('http://placekitten.com/g/200/300');
console.log(found);
found = await detectFromPath('https://loremflickr.com/g/320/240/text');
console.log(found);
found = await detectFromPath('http://lorempixel.com/400/200/sports/');
console.log(found);
// Sometimes 'Grey' and 'World Of Warcraft' are the only labels...
if (found && found.labels.length === 2 && found.labels.some(i => i.Name === 'Gray') && found.labels.some(i => i.Name === 'World Of Warcraft')) {
console.log('⚠️', 'ntMaybe this is a bad image...`Gray` and `World Of Warcraft`???n');
}
}
// ----------------
/**
* @param {string} path URL or filepath on your local machine.
* @param {Number} maxLabels
* @param {Number} minConfidence
* @param {array} attributes
*/
async function detectFromPath(path, maxLabels, minConfidence, attributes) {
// Convert path to base64 Buffer data.
const bytes = (/^https?:///gm.exec(path)) ?
await getBase64BufferFromURL(path) :
await getBase64BufferFromFile(path);
// Invalid data.
if (!bytes)
return {
path,
faces: ,
labels: ,
text: ,
celebs: ,
moderation:
};
// Pass buffer to rekognition methods.
let labels = await detectLabelsFromBytes(bytes, maxLabels, minConfidence),
text = await detectTextFromBytes(bytes),
faces = await detectFacesFromBytes(bytes, attributes),
celebs = await recognizeCelebritiesFromBytes(bytes),
moderation = await detectModerationLabelsFromBytes(bytes, minConfidence);
// Filter out specific values.
labels = labels && labels.Labels ? labels.Labels : ;
faces = faces && faces.FaceDetails ? faces.FaceDetails : ;
text = text && text.TextDetections ? text.TextDetections.map(i => i.DetectedText) : ;
celebs = celebs && celebs.CelebrityFaces ? celebs.CelebrityFaces.map(i => ({
Name: i.Name,
MatchConfidence: i.MatchConfidence
})) : ;
moderation = moderation && moderation.ModerationLabels ? moderation.ModerationLabels.map(i => ({
Name: i.Name,
Confidence: i.Confidence
})) : ;
// Return collection.
return {
path,
faces,
labels,
text,
celebs,
moderation
};
}
/**
* https://nodejs.org/api/fs.html#fs_fs_readfile_path_options_callback
*
* @param {string} filename
*/
function getBase64BufferFromFile(filename) {
return (new Promise(function(resolve, reject) {
fs.readFile(filename, 'base64', (err, data) => {
if (err) return reject(err);
resolve(new Buffer(data, 'base64'));
});
})).catch(error => {
console.log('[ERROR]', error);
});
}
/**
* https://github.com/axios/axios
*
* @param {string} url
*/
function getBase64BufferFromURL(url) {
return axios
.get(url, {
responseType: 'arraybuffer'
})
.then(response => new Buffer(response.data, 'base64'))
.catch(error => {
console.log('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/labels.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectLabels-property
*
* @param {Buffer} bytes
* @param {Number} maxLabels
* @param {Number} minConfidence
*/
function detectLabelsFromBytes(bytes, maxLabels, minConfidence) {
return rekognition
.detectLabels({
Image: {
Bytes: bytes
},
MaxLabels: typeof maxLabels !== 'undefined' ? maxLabels : 1000,
MinConfidence: typeof minConfidence !== 'undefined' ? minConfidence : 50.0
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/text-detection.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectText-property
*
* @param {Buffer} bytes
*/
function detectTextFromBytes(bytes) {
return rekognition
.detectText({
Image: {
Bytes: bytes
}
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/celebrities.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#recognizeCelebrities-property
*
* @param {Buffer} bytes
*/
function recognizeCelebritiesFromBytes(bytes) {
return rekognition
.recognizeCelebrities({
Image: {
Bytes: bytes
}
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/moderation.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectModerationLabels-property
*
* @param {Buffer} bytes
* @param {Number} minConfidence
*/
function detectModerationLabelsFromBytes(bytes, minConfidence) {
return rekognition
.detectModerationLabels({
Image: {
Bytes: bytes
},
MinConfidence: typeof minConfidence !== 'undefined' ? minConfidence : 60.0
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/faces.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectFaces-property
*
* @param {Buffer} bytes
* @param {array} attributes Attributes can be "ALL" or "DEFAULT". "DEFAULT" includes: BoundingBox, Confidence, Landmarks, Pose, and Quality.
*/
function detectFacesFromBytes(bytes, attributes) {
return rekognition
.detectFaces({
Image: {
Bytes: bytes
},
Attributes: typeof attributes !== 'undefined' ? attributes : ['ALL']
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/API_CompareFaces.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#compareFaces-property
*
* @param {Buffer} sourceBytes
* @param {Buffer} targetBytes
* @param {Number} similarityThreshold
*/
function compareFaces(sourceBytes, targetBytes, similarityThreshold) {
return rekognition
.detectModerationLabels({
SourceImage: {
Bytes: sourceBytes
},
TargetImage: {
Bytes: targetBytes
},
SimilarityThreshold: typeof similarityThreshold !== 'undefined' ? similarityThreshold : 0.0
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
Resources:
- https://github.com/axios/axios
- https://docs.aws.amazon.com/rekognition/latest/dg/labels.html
- https://docs.aws.amazon.com/rekognition/latest/dg/text-detection.html
- https://docs.aws.amazon.com/rekognition/latest/dg/celebrities.html
- https://docs.aws.amazon.com/rekognition/latest/dg/moderation.html
- https://docs.aws.amazon.com/rekognition/latest/dg/faces.html
- https://docs.aws.amazon.com/rekognition/latest/dg/API_CompareFaces.html
- https://docs.aws.amazon.com/rekognition/latest/dg/image-bytes-javascript.html
AWS JavaScript SDK Reference:
- detectLabels
- detectText
- recognizeCelebrities
- detectModerationLabels
- detectFaces
- compareFaces
Reference:
- Download an image using Axios and convert it to base64
- Upload a binary file to S3 using AWS SDK for Node.js
- AWS Rekognition JS SDK Invalid image encoding error
- Pipe a stream to s3.upload()
- untarring files to S3 fails, not sure why
- Using Promises with fs.readFile in a loop
- How do I return the response from an asynchronous call?
- NodeJS UnhandledPromiseRejectionWarning
- How do I check whether an array contains a string in TypeScript?
- Do you need to use path.join in node.js?
add a comment |
Based on the answer supplied by @Sean, I wanted to add another way to get the bytes from a URL request using axios and passed to rekognition.detectLabels()
-- or other various detection methods for Amazon Rekognition.
I went ahead create a promise for fs.readFile
that should work with the async/await structure. Then some regex to determine if you need a URL fetch or file read as a fallback.
I've also added a check for Gray
and World Of Warcraft
for the labels. Not sure if anyone else experiences that but lorempixel seems to throw those labels every once in a while. I've seen them show on an all black image before as well.
/* jshint esversion: 6, node:true, devel: true, undef: true, unused: true */
const AWS = require('aws-sdk'),
axios = require('axios'),
fs = require('fs'),
path = require('path');
// Get credentials from environmental variables.
const {S3_ACCESS_KEY, S3_SECRET_ACCESS_KEY, S3_REGION} = process.env;
// Set AWS credentials.
AWS.config.update({
accessKeyId: S3_ACCESS_KEY,
secretAccessKey: S3_SECRET_ACCESS_KEY,
region: S3_REGION
});
const rekognition = new AWS.Rekognition({
apiVersion: '2016-06-27'
});
startDetection();
// ----------------
async function startDetection() {
let found = {};
found = await detectFromPath(path.join(__dirname, 'test.jpg'));
console.log(found);
found = await detectFromPath('https://upload.wikimedia.org/wikipedia/commons/9/96/Bill_Nye%2C_Barack_Obama_and_Neil_deGrasse_Tyson_selfie_2014.jpg');
console.log(found);
found = await detectFromPath('http://placekitten.com/g/200/300');
console.log(found);
found = await detectFromPath('https://loremflickr.com/g/320/240/text');
console.log(found);
found = await detectFromPath('http://lorempixel.com/400/200/sports/');
console.log(found);
// Sometimes 'Grey' and 'World Of Warcraft' are the only labels...
if (found && found.labels.length === 2 && found.labels.some(i => i.Name === 'Gray') && found.labels.some(i => i.Name === 'World Of Warcraft')) {
console.log('⚠️', 'ntMaybe this is a bad image...`Gray` and `World Of Warcraft`???n');
}
}
// ----------------
/**
* @param {string} path URL or filepath on your local machine.
* @param {Number} maxLabels
* @param {Number} minConfidence
* @param {array} attributes
*/
async function detectFromPath(path, maxLabels, minConfidence, attributes) {
// Convert path to base64 Buffer data.
const bytes = (/^https?:///gm.exec(path)) ?
await getBase64BufferFromURL(path) :
await getBase64BufferFromFile(path);
// Invalid data.
if (!bytes)
return {
path,
faces: ,
labels: ,
text: ,
celebs: ,
moderation:
};
// Pass buffer to rekognition methods.
let labels = await detectLabelsFromBytes(bytes, maxLabels, minConfidence),
text = await detectTextFromBytes(bytes),
faces = await detectFacesFromBytes(bytes, attributes),
celebs = await recognizeCelebritiesFromBytes(bytes),
moderation = await detectModerationLabelsFromBytes(bytes, minConfidence);
// Filter out specific values.
labels = labels && labels.Labels ? labels.Labels : ;
faces = faces && faces.FaceDetails ? faces.FaceDetails : ;
text = text && text.TextDetections ? text.TextDetections.map(i => i.DetectedText) : ;
celebs = celebs && celebs.CelebrityFaces ? celebs.CelebrityFaces.map(i => ({
Name: i.Name,
MatchConfidence: i.MatchConfidence
})) : ;
moderation = moderation && moderation.ModerationLabels ? moderation.ModerationLabels.map(i => ({
Name: i.Name,
Confidence: i.Confidence
})) : ;
// Return collection.
return {
path,
faces,
labels,
text,
celebs,
moderation
};
}
/**
* https://nodejs.org/api/fs.html#fs_fs_readfile_path_options_callback
*
* @param {string} filename
*/
function getBase64BufferFromFile(filename) {
return (new Promise(function(resolve, reject) {
fs.readFile(filename, 'base64', (err, data) => {
if (err) return reject(err);
resolve(new Buffer(data, 'base64'));
});
})).catch(error => {
console.log('[ERROR]', error);
});
}
/**
* https://github.com/axios/axios
*
* @param {string} url
*/
function getBase64BufferFromURL(url) {
return axios
.get(url, {
responseType: 'arraybuffer'
})
.then(response => new Buffer(response.data, 'base64'))
.catch(error => {
console.log('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/labels.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectLabels-property
*
* @param {Buffer} bytes
* @param {Number} maxLabels
* @param {Number} minConfidence
*/
function detectLabelsFromBytes(bytes, maxLabels, minConfidence) {
return rekognition
.detectLabels({
Image: {
Bytes: bytes
},
MaxLabels: typeof maxLabels !== 'undefined' ? maxLabels : 1000,
MinConfidence: typeof minConfidence !== 'undefined' ? minConfidence : 50.0
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/text-detection.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectText-property
*
* @param {Buffer} bytes
*/
function detectTextFromBytes(bytes) {
return rekognition
.detectText({
Image: {
Bytes: bytes
}
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/celebrities.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#recognizeCelebrities-property
*
* @param {Buffer} bytes
*/
function recognizeCelebritiesFromBytes(bytes) {
return rekognition
.recognizeCelebrities({
Image: {
Bytes: bytes
}
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/moderation.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectModerationLabels-property
*
* @param {Buffer} bytes
* @param {Number} minConfidence
*/
function detectModerationLabelsFromBytes(bytes, minConfidence) {
return rekognition
.detectModerationLabels({
Image: {
Bytes: bytes
},
MinConfidence: typeof minConfidence !== 'undefined' ? minConfidence : 60.0
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/faces.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectFaces-property
*
* @param {Buffer} bytes
* @param {array} attributes Attributes can be "ALL" or "DEFAULT". "DEFAULT" includes: BoundingBox, Confidence, Landmarks, Pose, and Quality.
*/
function detectFacesFromBytes(bytes, attributes) {
return rekognition
.detectFaces({
Image: {
Bytes: bytes
},
Attributes: typeof attributes !== 'undefined' ? attributes : ['ALL']
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/API_CompareFaces.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#compareFaces-property
*
* @param {Buffer} sourceBytes
* @param {Buffer} targetBytes
* @param {Number} similarityThreshold
*/
function compareFaces(sourceBytes, targetBytes, similarityThreshold) {
return rekognition
.detectModerationLabels({
SourceImage: {
Bytes: sourceBytes
},
TargetImage: {
Bytes: targetBytes
},
SimilarityThreshold: typeof similarityThreshold !== 'undefined' ? similarityThreshold : 0.0
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
Resources:
- https://github.com/axios/axios
- https://docs.aws.amazon.com/rekognition/latest/dg/labels.html
- https://docs.aws.amazon.com/rekognition/latest/dg/text-detection.html
- https://docs.aws.amazon.com/rekognition/latest/dg/celebrities.html
- https://docs.aws.amazon.com/rekognition/latest/dg/moderation.html
- https://docs.aws.amazon.com/rekognition/latest/dg/faces.html
- https://docs.aws.amazon.com/rekognition/latest/dg/API_CompareFaces.html
- https://docs.aws.amazon.com/rekognition/latest/dg/image-bytes-javascript.html
AWS JavaScript SDK Reference:
- detectLabels
- detectText
- recognizeCelebrities
- detectModerationLabels
- detectFaces
- compareFaces
Reference:
- Download an image using Axios and convert it to base64
- Upload a binary file to S3 using AWS SDK for Node.js
- AWS Rekognition JS SDK Invalid image encoding error
- Pipe a stream to s3.upload()
- untarring files to S3 fails, not sure why
- Using Promises with fs.readFile in a loop
- How do I return the response from an asynchronous call?
- NodeJS UnhandledPromiseRejectionWarning
- How do I check whether an array contains a string in TypeScript?
- Do you need to use path.join in node.js?
add a comment |
Based on the answer supplied by @Sean, I wanted to add another way to get the bytes from a URL request using axios and passed to rekognition.detectLabels()
-- or other various detection methods for Amazon Rekognition.
I went ahead create a promise for fs.readFile
that should work with the async/await structure. Then some regex to determine if you need a URL fetch or file read as a fallback.
I've also added a check for Gray
and World Of Warcraft
for the labels. Not sure if anyone else experiences that but lorempixel seems to throw those labels every once in a while. I've seen them show on an all black image before as well.
/* jshint esversion: 6, node:true, devel: true, undef: true, unused: true */
const AWS = require('aws-sdk'),
axios = require('axios'),
fs = require('fs'),
path = require('path');
// Get credentials from environmental variables.
const {S3_ACCESS_KEY, S3_SECRET_ACCESS_KEY, S3_REGION} = process.env;
// Set AWS credentials.
AWS.config.update({
accessKeyId: S3_ACCESS_KEY,
secretAccessKey: S3_SECRET_ACCESS_KEY,
region: S3_REGION
});
const rekognition = new AWS.Rekognition({
apiVersion: '2016-06-27'
});
startDetection();
// ----------------
async function startDetection() {
let found = {};
found = await detectFromPath(path.join(__dirname, 'test.jpg'));
console.log(found);
found = await detectFromPath('https://upload.wikimedia.org/wikipedia/commons/9/96/Bill_Nye%2C_Barack_Obama_and_Neil_deGrasse_Tyson_selfie_2014.jpg');
console.log(found);
found = await detectFromPath('http://placekitten.com/g/200/300');
console.log(found);
found = await detectFromPath('https://loremflickr.com/g/320/240/text');
console.log(found);
found = await detectFromPath('http://lorempixel.com/400/200/sports/');
console.log(found);
// Sometimes 'Grey' and 'World Of Warcraft' are the only labels...
if (found && found.labels.length === 2 && found.labels.some(i => i.Name === 'Gray') && found.labels.some(i => i.Name === 'World Of Warcraft')) {
console.log('⚠️', 'ntMaybe this is a bad image...`Gray` and `World Of Warcraft`???n');
}
}
// ----------------
/**
* @param {string} path URL or filepath on your local machine.
* @param {Number} maxLabels
* @param {Number} minConfidence
* @param {array} attributes
*/
async function detectFromPath(path, maxLabels, minConfidence, attributes) {
// Convert path to base64 Buffer data.
const bytes = (/^https?:///gm.exec(path)) ?
await getBase64BufferFromURL(path) :
await getBase64BufferFromFile(path);
// Invalid data.
if (!bytes)
return {
path,
faces: ,
labels: ,
text: ,
celebs: ,
moderation:
};
// Pass buffer to rekognition methods.
let labels = await detectLabelsFromBytes(bytes, maxLabels, minConfidence),
text = await detectTextFromBytes(bytes),
faces = await detectFacesFromBytes(bytes, attributes),
celebs = await recognizeCelebritiesFromBytes(bytes),
moderation = await detectModerationLabelsFromBytes(bytes, minConfidence);
// Filter out specific values.
labels = labels && labels.Labels ? labels.Labels : ;
faces = faces && faces.FaceDetails ? faces.FaceDetails : ;
text = text && text.TextDetections ? text.TextDetections.map(i => i.DetectedText) : ;
celebs = celebs && celebs.CelebrityFaces ? celebs.CelebrityFaces.map(i => ({
Name: i.Name,
MatchConfidence: i.MatchConfidence
})) : ;
moderation = moderation && moderation.ModerationLabels ? moderation.ModerationLabels.map(i => ({
Name: i.Name,
Confidence: i.Confidence
})) : ;
// Return collection.
return {
path,
faces,
labels,
text,
celebs,
moderation
};
}
/**
* https://nodejs.org/api/fs.html#fs_fs_readfile_path_options_callback
*
* @param {string} filename
*/
function getBase64BufferFromFile(filename) {
return (new Promise(function(resolve, reject) {
fs.readFile(filename, 'base64', (err, data) => {
if (err) return reject(err);
resolve(new Buffer(data, 'base64'));
});
})).catch(error => {
console.log('[ERROR]', error);
});
}
/**
* https://github.com/axios/axios
*
* @param {string} url
*/
function getBase64BufferFromURL(url) {
return axios
.get(url, {
responseType: 'arraybuffer'
})
.then(response => new Buffer(response.data, 'base64'))
.catch(error => {
console.log('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/labels.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectLabels-property
*
* @param {Buffer} bytes
* @param {Number} maxLabels
* @param {Number} minConfidence
*/
function detectLabelsFromBytes(bytes, maxLabels, minConfidence) {
return rekognition
.detectLabels({
Image: {
Bytes: bytes
},
MaxLabels: typeof maxLabels !== 'undefined' ? maxLabels : 1000,
MinConfidence: typeof minConfidence !== 'undefined' ? minConfidence : 50.0
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/text-detection.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectText-property
*
* @param {Buffer} bytes
*/
function detectTextFromBytes(bytes) {
return rekognition
.detectText({
Image: {
Bytes: bytes
}
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/celebrities.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#recognizeCelebrities-property
*
* @param {Buffer} bytes
*/
function recognizeCelebritiesFromBytes(bytes) {
return rekognition
.recognizeCelebrities({
Image: {
Bytes: bytes
}
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/moderation.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectModerationLabels-property
*
* @param {Buffer} bytes
* @param {Number} minConfidence
*/
function detectModerationLabelsFromBytes(bytes, minConfidence) {
return rekognition
.detectModerationLabels({
Image: {
Bytes: bytes
},
MinConfidence: typeof minConfidence !== 'undefined' ? minConfidence : 60.0
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/faces.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectFaces-property
*
* @param {Buffer} bytes
* @param {array} attributes Attributes can be "ALL" or "DEFAULT". "DEFAULT" includes: BoundingBox, Confidence, Landmarks, Pose, and Quality.
*/
function detectFacesFromBytes(bytes, attributes) {
return rekognition
.detectFaces({
Image: {
Bytes: bytes
},
Attributes: typeof attributes !== 'undefined' ? attributes : ['ALL']
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/API_CompareFaces.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#compareFaces-property
*
* @param {Buffer} sourceBytes
* @param {Buffer} targetBytes
* @param {Number} similarityThreshold
*/
function compareFaces(sourceBytes, targetBytes, similarityThreshold) {
return rekognition
.detectModerationLabels({
SourceImage: {
Bytes: sourceBytes
},
TargetImage: {
Bytes: targetBytes
},
SimilarityThreshold: typeof similarityThreshold !== 'undefined' ? similarityThreshold : 0.0
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
Resources:
- https://github.com/axios/axios
- https://docs.aws.amazon.com/rekognition/latest/dg/labels.html
- https://docs.aws.amazon.com/rekognition/latest/dg/text-detection.html
- https://docs.aws.amazon.com/rekognition/latest/dg/celebrities.html
- https://docs.aws.amazon.com/rekognition/latest/dg/moderation.html
- https://docs.aws.amazon.com/rekognition/latest/dg/faces.html
- https://docs.aws.amazon.com/rekognition/latest/dg/API_CompareFaces.html
- https://docs.aws.amazon.com/rekognition/latest/dg/image-bytes-javascript.html
AWS JavaScript SDK Reference:
- detectLabels
- detectText
- recognizeCelebrities
- detectModerationLabels
- detectFaces
- compareFaces
Reference:
- Download an image using Axios and convert it to base64
- Upload a binary file to S3 using AWS SDK for Node.js
- AWS Rekognition JS SDK Invalid image encoding error
- Pipe a stream to s3.upload()
- untarring files to S3 fails, not sure why
- Using Promises with fs.readFile in a loop
- How do I return the response from an asynchronous call?
- NodeJS UnhandledPromiseRejectionWarning
- How do I check whether an array contains a string in TypeScript?
- Do you need to use path.join in node.js?
Based on the answer supplied by @Sean, I wanted to add another way to get the bytes from a URL request using axios and passed to rekognition.detectLabels()
-- or other various detection methods for Amazon Rekognition.
I went ahead create a promise for fs.readFile
that should work with the async/await structure. Then some regex to determine if you need a URL fetch or file read as a fallback.
I've also added a check for Gray
and World Of Warcraft
for the labels. Not sure if anyone else experiences that but lorempixel seems to throw those labels every once in a while. I've seen them show on an all black image before as well.
/* jshint esversion: 6, node:true, devel: true, undef: true, unused: true */
const AWS = require('aws-sdk'),
axios = require('axios'),
fs = require('fs'),
path = require('path');
// Get credentials from environmental variables.
const {S3_ACCESS_KEY, S3_SECRET_ACCESS_KEY, S3_REGION} = process.env;
// Set AWS credentials.
AWS.config.update({
accessKeyId: S3_ACCESS_KEY,
secretAccessKey: S3_SECRET_ACCESS_KEY,
region: S3_REGION
});
const rekognition = new AWS.Rekognition({
apiVersion: '2016-06-27'
});
startDetection();
// ----------------
async function startDetection() {
let found = {};
found = await detectFromPath(path.join(__dirname, 'test.jpg'));
console.log(found);
found = await detectFromPath('https://upload.wikimedia.org/wikipedia/commons/9/96/Bill_Nye%2C_Barack_Obama_and_Neil_deGrasse_Tyson_selfie_2014.jpg');
console.log(found);
found = await detectFromPath('http://placekitten.com/g/200/300');
console.log(found);
found = await detectFromPath('https://loremflickr.com/g/320/240/text');
console.log(found);
found = await detectFromPath('http://lorempixel.com/400/200/sports/');
console.log(found);
// Sometimes 'Grey' and 'World Of Warcraft' are the only labels...
if (found && found.labels.length === 2 && found.labels.some(i => i.Name === 'Gray') && found.labels.some(i => i.Name === 'World Of Warcraft')) {
console.log('⚠️', 'ntMaybe this is a bad image...`Gray` and `World Of Warcraft`???n');
}
}
// ----------------
/**
* @param {string} path URL or filepath on your local machine.
* @param {Number} maxLabels
* @param {Number} minConfidence
* @param {array} attributes
*/
async function detectFromPath(path, maxLabels, minConfidence, attributes) {
// Convert path to base64 Buffer data.
const bytes = (/^https?:///gm.exec(path)) ?
await getBase64BufferFromURL(path) :
await getBase64BufferFromFile(path);
// Invalid data.
if (!bytes)
return {
path,
faces: ,
labels: ,
text: ,
celebs: ,
moderation:
};
// Pass buffer to rekognition methods.
let labels = await detectLabelsFromBytes(bytes, maxLabels, minConfidence),
text = await detectTextFromBytes(bytes),
faces = await detectFacesFromBytes(bytes, attributes),
celebs = await recognizeCelebritiesFromBytes(bytes),
moderation = await detectModerationLabelsFromBytes(bytes, minConfidence);
// Filter out specific values.
labels = labels && labels.Labels ? labels.Labels : ;
faces = faces && faces.FaceDetails ? faces.FaceDetails : ;
text = text && text.TextDetections ? text.TextDetections.map(i => i.DetectedText) : ;
celebs = celebs && celebs.CelebrityFaces ? celebs.CelebrityFaces.map(i => ({
Name: i.Name,
MatchConfidence: i.MatchConfidence
})) : ;
moderation = moderation && moderation.ModerationLabels ? moderation.ModerationLabels.map(i => ({
Name: i.Name,
Confidence: i.Confidence
})) : ;
// Return collection.
return {
path,
faces,
labels,
text,
celebs,
moderation
};
}
/**
* https://nodejs.org/api/fs.html#fs_fs_readfile_path_options_callback
*
* @param {string} filename
*/
function getBase64BufferFromFile(filename) {
return (new Promise(function(resolve, reject) {
fs.readFile(filename, 'base64', (err, data) => {
if (err) return reject(err);
resolve(new Buffer(data, 'base64'));
});
})).catch(error => {
console.log('[ERROR]', error);
});
}
/**
* https://github.com/axios/axios
*
* @param {string} url
*/
function getBase64BufferFromURL(url) {
return axios
.get(url, {
responseType: 'arraybuffer'
})
.then(response => new Buffer(response.data, 'base64'))
.catch(error => {
console.log('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/labels.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectLabels-property
*
* @param {Buffer} bytes
* @param {Number} maxLabels
* @param {Number} minConfidence
*/
function detectLabelsFromBytes(bytes, maxLabels, minConfidence) {
return rekognition
.detectLabels({
Image: {
Bytes: bytes
},
MaxLabels: typeof maxLabels !== 'undefined' ? maxLabels : 1000,
MinConfidence: typeof minConfidence !== 'undefined' ? minConfidence : 50.0
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/text-detection.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectText-property
*
* @param {Buffer} bytes
*/
function detectTextFromBytes(bytes) {
return rekognition
.detectText({
Image: {
Bytes: bytes
}
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/celebrities.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#recognizeCelebrities-property
*
* @param {Buffer} bytes
*/
function recognizeCelebritiesFromBytes(bytes) {
return rekognition
.recognizeCelebrities({
Image: {
Bytes: bytes
}
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/moderation.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectModerationLabels-property
*
* @param {Buffer} bytes
* @param {Number} minConfidence
*/
function detectModerationLabelsFromBytes(bytes, minConfidence) {
return rekognition
.detectModerationLabels({
Image: {
Bytes: bytes
},
MinConfidence: typeof minConfidence !== 'undefined' ? minConfidence : 60.0
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/faces.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#detectFaces-property
*
* @param {Buffer} bytes
* @param {array} attributes Attributes can be "ALL" or "DEFAULT". "DEFAULT" includes: BoundingBox, Confidence, Landmarks, Pose, and Quality.
*/
function detectFacesFromBytes(bytes, attributes) {
return rekognition
.detectFaces({
Image: {
Bytes: bytes
},
Attributes: typeof attributes !== 'undefined' ? attributes : ['ALL']
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
/**
* https://docs.aws.amazon.com/rekognition/latest/dg/API_CompareFaces.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Rekognition.html#compareFaces-property
*
* @param {Buffer} sourceBytes
* @param {Buffer} targetBytes
* @param {Number} similarityThreshold
*/
function compareFaces(sourceBytes, targetBytes, similarityThreshold) {
return rekognition
.detectModerationLabels({
SourceImage: {
Bytes: sourceBytes
},
TargetImage: {
Bytes: targetBytes
},
SimilarityThreshold: typeof similarityThreshold !== 'undefined' ? similarityThreshold : 0.0
})
.promise()
.catch(error => {
console.error('[ERROR]', error);
});
}
Resources:
- https://github.com/axios/axios
- https://docs.aws.amazon.com/rekognition/latest/dg/labels.html
- https://docs.aws.amazon.com/rekognition/latest/dg/text-detection.html
- https://docs.aws.amazon.com/rekognition/latest/dg/celebrities.html
- https://docs.aws.amazon.com/rekognition/latest/dg/moderation.html
- https://docs.aws.amazon.com/rekognition/latest/dg/faces.html
- https://docs.aws.amazon.com/rekognition/latest/dg/API_CompareFaces.html
- https://docs.aws.amazon.com/rekognition/latest/dg/image-bytes-javascript.html
AWS JavaScript SDK Reference:
- detectLabels
- detectText
- recognizeCelebrities
- detectModerationLabels
- detectFaces
- compareFaces
Reference:
- Download an image using Axios and convert it to base64
- Upload a binary file to S3 using AWS SDK for Node.js
- AWS Rekognition JS SDK Invalid image encoding error
- Pipe a stream to s3.upload()
- untarring files to S3 fails, not sure why
- Using Promises with fs.readFile in a loop
- How do I return the response from an asynchronous call?
- NodeJS UnhandledPromiseRejectionWarning
- How do I check whether an array contains a string in TypeScript?
- Do you need to use path.join in node.js?
edited Jan 5 at 15:57
answered Jan 4 at 5:48
jgraupjgraup
605811
605811
add a comment |
add a comment |
I was running into a similar issue when reading in a file in Node as a byte array buffer and sending it to Rekognition.
I solved it by instead reading in the base64 representation, then turning it into a buffer like this:
const aws = require('aws-sdk');
const fs = require('fs');
var rekognition = new aws.Rekognition({
apiVersion: '2016-06-27'
});
// pull base64 representation of image from file system (or somewhere else)
fs.readFile('./test.jpg', 'base64', (err, data) => {
// create a new buffer out of the string passed to us by fs.readFile()
const buffer = new Buffer(data, 'base64');
// now that we have things in the right type, send it to rekognition
rekognition.detectLabels({
Image: {
Bytes: buffer
}
}).promise()
.then((res) => {
// print out the labels that rekognition sent back
console.log(res);
});
});
This might also be relevant to people getting the: Expected params.Image.Bytes to be a string, Buffer, Stream, Blob, or typed array object
message.
add a comment |
I was running into a similar issue when reading in a file in Node as a byte array buffer and sending it to Rekognition.
I solved it by instead reading in the base64 representation, then turning it into a buffer like this:
const aws = require('aws-sdk');
const fs = require('fs');
var rekognition = new aws.Rekognition({
apiVersion: '2016-06-27'
});
// pull base64 representation of image from file system (or somewhere else)
fs.readFile('./test.jpg', 'base64', (err, data) => {
// create a new buffer out of the string passed to us by fs.readFile()
const buffer = new Buffer(data, 'base64');
// now that we have things in the right type, send it to rekognition
rekognition.detectLabels({
Image: {
Bytes: buffer
}
}).promise()
.then((res) => {
// print out the labels that rekognition sent back
console.log(res);
});
});
This might also be relevant to people getting the: Expected params.Image.Bytes to be a string, Buffer, Stream, Blob, or typed array object
message.
add a comment |
I was running into a similar issue when reading in a file in Node as a byte array buffer and sending it to Rekognition.
I solved it by instead reading in the base64 representation, then turning it into a buffer like this:
const aws = require('aws-sdk');
const fs = require('fs');
var rekognition = new aws.Rekognition({
apiVersion: '2016-06-27'
});
// pull base64 representation of image from file system (or somewhere else)
fs.readFile('./test.jpg', 'base64', (err, data) => {
// create a new buffer out of the string passed to us by fs.readFile()
const buffer = new Buffer(data, 'base64');
// now that we have things in the right type, send it to rekognition
rekognition.detectLabels({
Image: {
Bytes: buffer
}
}).promise()
.then((res) => {
// print out the labels that rekognition sent back
console.log(res);
});
});
This might also be relevant to people getting the: Expected params.Image.Bytes to be a string, Buffer, Stream, Blob, or typed array object
message.
I was running into a similar issue when reading in a file in Node as a byte array buffer and sending it to Rekognition.
I solved it by instead reading in the base64 representation, then turning it into a buffer like this:
const aws = require('aws-sdk');
const fs = require('fs');
var rekognition = new aws.Rekognition({
apiVersion: '2016-06-27'
});
// pull base64 representation of image from file system (or somewhere else)
fs.readFile('./test.jpg', 'base64', (err, data) => {
// create a new buffer out of the string passed to us by fs.readFile()
const buffer = new Buffer(data, 'base64');
// now that we have things in the right type, send it to rekognition
rekognition.detectLabels({
Image: {
Bytes: buffer
}
}).promise()
.then((res) => {
// print out the labels that rekognition sent back
console.log(res);
});
});
This might also be relevant to people getting the: Expected params.Image.Bytes to be a string, Buffer, Stream, Blob, or typed array object
message.
edited Jan 7 at 22:07
answered Aug 2 '17 at 0:03
SeanSean
453518
453518
add a comment |
add a comment |
I had same issue you had and i'm going to tell you how i solved it.
Amazon Rekognition supports image type are JPEG and PNG
It means that if you input image file with encoding other formats like webp, you always get same that error.
After changing image formats which not encoding with jpeg or png to jpeg, i could solved that problem.
Hope you to solve this problem!
add a comment |
I had same issue you had and i'm going to tell you how i solved it.
Amazon Rekognition supports image type are JPEG and PNG
It means that if you input image file with encoding other formats like webp, you always get same that error.
After changing image formats which not encoding with jpeg or png to jpeg, i could solved that problem.
Hope you to solve this problem!
add a comment |
I had same issue you had and i'm going to tell you how i solved it.
Amazon Rekognition supports image type are JPEG and PNG
It means that if you input image file with encoding other formats like webp, you always get same that error.
After changing image formats which not encoding with jpeg or png to jpeg, i could solved that problem.
Hope you to solve this problem!
I had same issue you had and i'm going to tell you how i solved it.
Amazon Rekognition supports image type are JPEG and PNG
It means that if you input image file with encoding other formats like webp, you always get same that error.
After changing image formats which not encoding with jpeg or png to jpeg, i could solved that problem.
Hope you to solve this problem!
answered Mar 6 '18 at 9:09
JackKimJackKim
11
11
add a comment |
add a comment |
It seems that converting the string to a buffer works more consistently but documentation on it is very hard to find.
For Node, you can use this to convert the params from the string (make sure you take off the data... up to the ",".
var params = {
CollectionId: collectionId,
Image: {
Bytes: new Buffer(imageBytes, 'base64')
}
};
In normal JS, you'd want can convert with atob and pass the Array buffer using this code:
function getBinary(base64Image) {
var binaryImg = Buffer.from(base64Image, 'base64').toString();
var length = binaryImg.length;
var ab = new ArrayBuffer(length);
var ua = new Uint8Array(ab);
for (var i = 0; i < length; i++) {
ua[i] = binaryImg.charCodeAt(i);
}
return ab;
}
add a comment |
It seems that converting the string to a buffer works more consistently but documentation on it is very hard to find.
For Node, you can use this to convert the params from the string (make sure you take off the data... up to the ",".
var params = {
CollectionId: collectionId,
Image: {
Bytes: new Buffer(imageBytes, 'base64')
}
};
In normal JS, you'd want can convert with atob and pass the Array buffer using this code:
function getBinary(base64Image) {
var binaryImg = Buffer.from(base64Image, 'base64').toString();
var length = binaryImg.length;
var ab = new ArrayBuffer(length);
var ua = new Uint8Array(ab);
for (var i = 0; i < length; i++) {
ua[i] = binaryImg.charCodeAt(i);
}
return ab;
}
add a comment |
It seems that converting the string to a buffer works more consistently but documentation on it is very hard to find.
For Node, you can use this to convert the params from the string (make sure you take off the data... up to the ",".
var params = {
CollectionId: collectionId,
Image: {
Bytes: new Buffer(imageBytes, 'base64')
}
};
In normal JS, you'd want can convert with atob and pass the Array buffer using this code:
function getBinary(base64Image) {
var binaryImg = Buffer.from(base64Image, 'base64').toString();
var length = binaryImg.length;
var ab = new ArrayBuffer(length);
var ua = new Uint8Array(ab);
for (var i = 0; i < length; i++) {
ua[i] = binaryImg.charCodeAt(i);
}
return ab;
}
It seems that converting the string to a buffer works more consistently but documentation on it is very hard to find.
For Node, you can use this to convert the params from the string (make sure you take off the data... up to the ",".
var params = {
CollectionId: collectionId,
Image: {
Bytes: new Buffer(imageBytes, 'base64')
}
};
In normal JS, you'd want can convert with atob and pass the Array buffer using this code:
function getBinary(base64Image) {
var binaryImg = Buffer.from(base64Image, 'base64').toString();
var length = binaryImg.length;
var ab = new ArrayBuffer(length);
var ua = new Uint8Array(ab);
for (var i = 0; i < length; i++) {
ua[i] = binaryImg.charCodeAt(i);
}
return ab;
}
edited Jan 4 at 8:45
Daut
1,24011025
1,24011025
answered Jan 10 '18 at 14:18
Vannak ChhayVannak Chhay
32
32
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f43494736%2faws-rekognition-javascript-sdk-using-bytes%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
I am also looking for an answer to how to do this as I have been unable to do this. I have tried using Base64 encoded string with same result as above as well have tried converting it to a Uint8array, Blob, & ArrayBuffer still with no success. Does anyone have an example that works? My source data is in a HTML5 Canvas object.
– Michael Dennis
May 26 '17 at 16:50
Related and Solved: stackoverflow.com/questions/43599556/…
– srikanth Nutigattu
Jul 30 '18 at 19:47