Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 87 additions & 101 deletions vision/detect.js

Large diffs are not rendered by default.

40 changes: 25 additions & 15 deletions vision/faceDetection.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,25 @@ var fs = require('fs');
*/
function detectFaces (inputFile, callback) {
// Make a call to the Vision API to detect the faces
vision.detectFaces(inputFile, function (err, faces) {
if (err) {
return callback(err);
}
var numFaces = faces.length;
console.log('Found ' + numFaces + (numFaces === 1 ? ' face' : ' faces'));
callback(null, faces);
});
const request = { source: { filename: inputFile } };
vision.faceDetection(request)
.then((results) => {
const faces = results[0].faceAnnotations;
var numFaces = faces.length;
console.log('Found ' + numFaces + (numFaces === 1 ? ' face' : ' faces'));
callback(null, faces);
})
.catch((err) => {
console.error('ERROR:', err);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add callback(err); below console.error

callback(err);
});
}

/**
* Draws a polygon around the faces, then saves to outputFile.
*/
function highlightFaces (inputFile, faces, outputFile, Canvas, callback) {
fs.readFile(inputFile, function (err, image) {
fs.readFile(inputFile, (err, image) => {
if (err) {
return callback(err);
}
Expand All @@ -64,12 +68,18 @@ function highlightFaces (inputFile, faces, outputFile, Canvas, callback) {
context.strokeStyle = 'rgba(0,255,0,0.8)';
context.lineWidth = '5';

faces.forEach(function (face) {
faces.forEach((face) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use an arrow function here if you're not going to convert the whole file to arrow functions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: I converted the whole file to arrow functions. 😛

context.beginPath();
face.bounds.face.forEach(function (bounds) {
let origX = 0;
let origY = 0;
face.boundingPoly.vertices.forEach((bounds, i) => {
if (i === 0) {
origX = bounds.x;
origY = bounds.y;
}
context.lineTo(bounds.x, bounds.y);
});
context.lineTo(face.bounds.face[0].x, face.bounds.face[0].y);
context.lineTo(origX, origY);
context.stroke();
});

Expand All @@ -78,7 +88,7 @@ function highlightFaces (inputFile, faces, outputFile, Canvas, callback) {
var writeStream = fs.createWriteStream(outputFile);
var pngStream = canvas.pngStream();

pngStream.on('data', function (chunk) {
pngStream.on('data', (chunk) => {
writeStream.write(chunk);
});
pngStream.on('error', console.log);
Expand All @@ -89,13 +99,13 @@ function highlightFaces (inputFile, faces, outputFile, Canvas, callback) {
// Run the example
function main (inputFile, outputFile, Canvas, callback) {
outputFile = outputFile || 'out.png';
detectFaces(inputFile, function (err, faces) {
detectFaces(inputFile, (err, faces) => {
if (err) {
return callback(err);
}

console.log('Highlighting...');
highlightFaces(inputFile, faces, outputFile, Canvas, function (err) {
highlightFaces(inputFile, faces, outputFile, Canvas, (err) => {
if (err) {
return callback(err);
}
Expand Down
2 changes: 1 addition & 1 deletion vision/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
},
"dependencies": {
"@google-cloud/storage": "1.1.0",
"@google-cloud/vision": "0.11.2",
"@google-cloud/vision": "^0.12.0",
"async": "2.3.0",
"natural": "0.5.1",
"redis": "2.7.1",
Expand Down
22 changes: 12 additions & 10 deletions vision/quickstart.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2016, Google, Inc.
* Copyright 2017, Google, Inc.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand All @@ -19,24 +19,26 @@
// Imports the Google Cloud client library
const Vision = require('@google-cloud/vision');

// Your Google Cloud Platform project ID
const projectId = 'YOUR_PROJECT_ID';

// Instantiates a client
const visionClient = Vision({
projectId: projectId
});
const vision = Vision();

// The name of the image file to annotate
const fileName = './resources/wakeupcat.jpg';

// Prepare the request object
const request = {
source: {
filename: fileName
}
};

// Performs label detection on the image file
visionClient.detectLabels(fileName)
vision.labelDetection(request)
.then((results) => {
const labels = results[0];
const labels = results[0].labelAnnotations;

console.log('Labels:');
labels.forEach((label) => console.log(label));
labels.forEach((label) => console.log(label.description));
})
.catch((err) => {
console.error('ERROR:', err);
Expand Down
4 changes: 2 additions & 2 deletions vision/system-test/detect.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,13 @@ test(`should detect logos in a remote file`, async (t) => {

test(`should detect properties in a local file`, async (t) => {
const output = await tools.runAsync(`${cmd} properties ${files[1].localPath}`, cwd);
t.true(output.includes(`Colors:`));
t.true(output.includes(`{ color: { red: 69, green: 42, blue: 27`));
t.true(output.split(`\n`).length > 4, `Multiple colors were detected.`);
});

test(`should detect properties in a remote file`, async (t) => {
const output = await tools.runAsync(`${cmd} properties-gcs ${bucketName} ${files[1].name}`, cwd);
t.true(output.includes(`Colors:`));
t.true(output.includes(`{ color: { red: 69, green: 42, blue: 27`));
t.true(output.split(`\n`).length > 4, `Multiple colors were detected.`);
});

Expand Down
43 changes: 7 additions & 36 deletions vision/system-test/quickstart.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2016, Google, Inc.
* Copyright 2017, Google, Inc.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand All @@ -16,46 +16,17 @@
'use strict';

const path = require(`path`);
const proxyquire = require(`proxyquire`).noPreserveCache();
const sinon = require(`sinon`);
const test = require(`ava`);
const tools = require(`@google-cloud/nodejs-repo-tools`);

const vision = proxyquire(`@google-cloud/vision`, {})();
const cmd = `node quickstart.js`;
const cwd = path.join(__dirname, `..`);

test.before(tools.stubConsole);
test.after.always(tools.restoreConsole);

test.cb(`should detect labels`, (t) => {
const filePath = path.join(__dirname, `../resources/wakeupcat.jpg`);
const expectedFileName = `./resources/wakeupcat.jpg`;
const visionMock = {
detectLabels: (_fileName) => {
t.is(_fileName, expectedFileName);

return vision.detectLabels(filePath)
.then(([labels]) => {
t.true(Array.isArray(labels));

setTimeout(() => {
try {
t.is(console.log.callCount, 6);
t.deepEqual(console.log.getCall(0).args, [`Labels:`]);
labels.forEach((label, i) => {
t.deepEqual(console.log.getCall(i + 1).args, [label]);
});
t.end();
} catch (err) {
t.end(err);
}
}, 200);

return [labels];
});
}
};

proxyquire(`../quickstart`, {
'@google-cloud/vision': sinon.stub().returns(visionMock)
});
test(`should detect labels in a remote file`, async (t) => {
const output = await tools.runAsync(`${cmd}`, cwd);
t.true(output.includes(`Labels:`));
t.true(output.includes(`cat`));
});
69 changes: 37 additions & 32 deletions vision/textDetection.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,14 @@ function lookup (words, callback) {
function extractDescription (texts) {
var document = '';
texts.forEach(function (text) {
document += (text.desc || '');
document += (text.description || '');
});
return document;
}

function extractDescriptions (filename, index, texts, callback) {
if (texts.length) {
index.add(filename, extractDescription(texts), callback);
function extractDescriptions (filename, index, response, callback) {
if (response.textAnnotations.length) {
index.add(filename, extractDescription(response.textAnnotations), callback);
} else {
console.log(filename + ' had no discernable text.');
index.setContainsNoText(filename, callback);
Expand All @@ -147,36 +147,41 @@ function extractDescriptions (filename, index, texts, callback) {

// [START get_text]
function getTextFromFiles (index, inputFiles, callback) {
var options = { verbose: true };

// Make a call to the Vision API to detect text
vision.detectText(inputFiles, options, function (err, detections) {
if (err) {
return callback(err);
}
var textResponse = {};
var tasks = [];
inputFiles.forEach(function (filename, i) {
var response = detections[i];
if (response.error) {
console.log('API Error for ' + filename, response.error);
return;
} else if (Array.isArray(response)) {
textResponse[filename] = 1;
} else {
textResponse[filename] = 0;
}
tasks.push(function (cb) {
extractDescriptions(filename, index, response, cb);
});
});
async.parallel(tasks, function (err) {
if (err) {
return callback(err);
}
callback(null, textResponse);
});
let requests = [];
inputFiles.forEach((filename) => {
let request = {
image: {content: fs.readFileSync(filename).toString('base64')},
features: {type: 'TEXT_DETECTION'}
};
requests.push(request);
});
vision.batchAnnotateImages({requests: requests})
.then((results) => {
let detections = results[0].responses;
var textResponse = {};
var tasks = [];
inputFiles.forEach(function (filename, i) {
var response = detections[i];
if (response.error) {
console.log('API Error for ' + filename, response.error);
return;
} else if (Array.isArray(response)) {
textResponse[filename] = 1;
} else {
textResponse[filename] = 0;
}
tasks.push(function (cb) {
extractDescriptions(filename, index, response, cb);
});
});
async.parallel(tasks, function (err) {
if (err) {
return callback(err);
}
callback(null, textResponse);
});
});
}

// Run the example
Expand Down
Loading