Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Cloud Vision face detection sample. #109

Merged
merged 1 commit into from
May 12, 2016
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
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ This repository holds Node.js samples used throughout [cloud.google.com]().
* [Google Cloud Logging](#google-cloud-logging)
* [Google Cloud Pub/Sub](#google-cloud-pubsub)
* [Google Cloud Storage](#google-cloud-storage)
* [Google Cloud Vision](#google-cloud-vision)
* [Google Prediction API](#google-prediction-api)
* [Other Example Apps](#other-example-apps)
* [More Information](#more-information)
Expand Down Expand Up @@ -106,6 +107,10 @@ __Other Examples__

- Auth sample - [Source code][storage_1] | [Documentation][storage_2]

## Google Cloud Vision

- Face detection - [Source code][vision_1] | [Documentation][vision_2]

## Google Prediction API

- Hosted Models sample - [Source code][predictionapi_1] | [Documentation][predictionapi_2]
Expand Down Expand Up @@ -307,6 +312,9 @@ See [LICENSE](https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/ma
[storage_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/storage/authSample.js
[storage_2]: https://cloud.google.com/storage/docs/authentication#acd-examples

[vision_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/vision/faceDetection.js
[vision_2]: https://cloud.google.com/vision/docs/face-tutorial

[predictionapi_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/prediction/hostedmodels.js
[predictionapi_2]: https://cloud.google.com/prediction/docs/developer-guide#predictionfromappengine

Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,15 @@
"deps_storage": "cd storage; npm i; cd ../",
"deps_prediction": "cd prediction; npm i; cd ../",
"deps_logging": "cd logging; npm i; cd ../",
"deps_vision": "cd vision; npm i; cd ../",
"deps_functions": "cd functions/uuid; npm i; cd ../..",
"pretest_geddy": "cd appengine/geddy; npm i geddy; GEDDY_SECRET=config/secrets.json; [[ -f $GEDDY_SECRET ]] || echo '{}' > $GEDDY_SECRET && node node_modules/.bin/geddy gen secret; cd ../..;",
"pretest": "npm run deps_gce; npm run deps_bigquery; npm run deps_datastore; npm run deps_monitoring; npm run deps_storage; npm run deps_pubsub; npm run deps_prediction; npm run deps_logging; npm run deps_functions; npm run pretest_geddy",
"pretest": "npm run deps_vision; npm run deps_gce; npm run deps_bigquery; npm run deps_datastore; npm run deps_monitoring; npm run deps_storage; npm run deps_pubsub; npm run deps_prediction; npm run deps_logging; npm run deps_functions; npm run pretest_geddy",
"test": "npm run jshint && npm run cover"
},
"ava": {
"files": [
"test/appengine/**/*.test.js"
"test/**/*.test.js"
]
},
"devDependencies": {
Expand Down
65 changes: 65 additions & 0 deletions test/vision/faceDetection.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2016, 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

var test = require('ava');
var fs = require('fs');
var path = require('path');

function MockCanvas () {
this.getContext = function () {
return {
drawImage: function () {},
beginPath: function () {},
lineTo: function () {},
stroke: function () {}
};
};
this.pngStream = function () {
return {
on: function (event, cb) {
if (event === 'end') {
setTimeout(function () {
cb();
}, 1000);
} else if (event === 'data') {
cb('test');
cb('foo');
cb('bar');
}
}
};
};
}

MockCanvas.Image = function () {};

var faceDetectionExample = require('../../vision/faceDetection');
var inputFile = path.resolve(path.join('../../vision', 'face.png'));
var outputFile = path.resolve(path.join('../../vision', 'out.png'));

test.cb('should detect faces', function (t) {
faceDetectionExample.main(
inputFile,
outputFile,
MockCanvas,
function (err, faces) {
t.ifError(err);
t.is(faces.length, 1);
var image = fs.readFileSync(outputFile);
t.is(image.toString('utf8'), 'testfoobar');
t.end();
}
);
});
1 change: 1 addition & 0 deletions vision/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
out.*
30 changes: 30 additions & 0 deletions vision/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## Cloud Vision API samples

These samples require two environment variables to be set:

- `GOOGLE_APPLICATION_CREDENTIALS` - Path to a service account file. You can
download one from your Google project's "credentials" page.
- `GCLOUD_PROJECT` - ID of your Google project.

See [gcloud-node authentication][auth] for more details.

[auth]: https://googlecloudplatform.github.io/gcloud-node/#/docs/guides/authentication

## Run a sample

Install dependencies first:

npm install

### Face detection sample

This sample uses [node-canvas](https://github.com/Automattic/node-canvas) to
draw an output image. node-canvas depends on Cairo, which may require separate
installation. See the node-canvas [installation section][canvas-install] for
details.

[canvas-install]: https://github.com/Automattic/node-canvas#installation

Execute the sample:

node faceDetection "/path/to/image.jpg"
Binary file added vision/face.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
120 changes: 120 additions & 0 deletions vision/faceDetection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Copyright 2016, 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

// [START auth]
// You must set the GOOGLE_APPLICATION_CREDENTIALS and GCLOUD_PROJECT
// environment variables to run this sample. See:
// https://github.com/GoogleCloudPlatform/gcloud-node/blob/master/docs/authentication.md
var projectId = process.env.GCLOUD_PROJECT;

// Initialize gcloud
var gcloud = require('gcloud')({
projectId: projectId
});

// Get a reference to the vision component
var vision = gcloud.vision();
// [END auth]

var fs = require('fs');

/**
* Uses the Vision API to detect faces in the given file.
*/
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);
});
}

/**
* Draws a polygon around the faces, then saves to outputFile.
*/
function highlightFaces(inputFile, faces, outputFile, Canvas, callback) {
fs.readFile(inputFile, function (err, image) {
if (err) {
return callback(err);
}

var Image = Canvas.Image;
// Open the original image into a canvas
var img = new Image();
img.src = image;
var canvas = new Canvas(img.width, img.height);
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0, img.width, img.height);

// Now draw boxes around all the faces
context.strokeStyle = 'rgba(0,255,0,0.8)';
context.lineWidth = '5';

faces.forEach(function (face) {
context.beginPath();
face.bounds.face.forEach(function (bounds) {
context.lineTo(bounds.x, bounds.y);
});
context.lineTo(face.bounds.face[0].x, face.bounds.face[0].y);
context.stroke();
});

// Write the result to a file
console.log('Writing to file ' + outputFile);
var writeStream = fs.createWriteStream(outputFile);
var pngStream = canvas.pngStream();

pngStream.on('data', function (chunk) {
writeStream.write(chunk);
});
pngStream.on('error', console.log);
pngStream.on('end', callback);
});
}

// Run the example
function main(inputFile, outputFile, Canvas, callback) {
outputFile = outputFile || 'out.png';
detectFaces(inputFile, function (err, faces) {
if (err) {
return callback(err);
}

console.log('Highlighting...');
highlightFaces(inputFile, faces, outputFile, Canvas, function (err) {
if (err) {
return callback(err);
}
console.log('Finished!');
callback(null, faces);
});
});
}

exports.main = main;

if (module === require.main) {
if (process.argv.length < 3) {
console.log('Usage: node faceDetection <inputFile> [outputFile]');
process.exit(1);
}
var inputFile = process.argv[2];
var outputFile = process.argv[3];
exports.main(inputFile, outputFile, require('canvas'), console.log);
}
17 changes: 17 additions & 0 deletions vision/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "cloud-vision-samples",
"description": "Node.js samples for Google Cloud Vision.",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"engines": {
"node": ">=0.10.x"
},
"scripts": {
"faceDetection": "node faceDetection.js"
},
"dependencies": {
"gcloud": "^0.32.0",
"canvas": "^1.3.15"
}
}