Skip to content

Commit 4bc349b

Browse files
committed
Add Cloud Vision face detection sample.
1 parent 4fbaf10 commit 4bc349b

File tree

8 files changed

+213
-2
lines changed

8 files changed

+213
-2
lines changed

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ This repository holds Node.js samples used throughout [cloud.google.com]().
1414
* [Google Cloud Logging](#google-cloud-logging)
1515
* [Google Cloud Pub/Sub](#google-cloud-pubsub)
1616
* [Google Cloud Storage](#google-cloud-storage)
17+
* [Google Cloud Vision](#google-cloud-vision)
1718
* [Google Prediction API](#google-prediction-api)
1819
* [Other Example Apps](#other-example-apps)
1920
* [More Information](#more-information)
@@ -106,6 +107,10 @@ __Other Examples__
106107

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

110+
## Google Cloud Vision
111+
112+
- Face detection - [Source code][vision_1] | [Documentation][vision_2]
113+
109114
## Google Prediction API
110115

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

315+
[vision_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/vision/faceDetection.js
316+
[vision_2]: https://cloud.google.com/vision/docs/face-tutorial
317+
310318
[predictionapi_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/prediction/hostedmodels.js
311319
[predictionapi_2]: https://cloud.google.com/prediction/docs/developer-guide#predictionfromappengine
312320

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,15 @@
3939
"deps_storage": "cd storage; npm i; cd ../",
4040
"deps_prediction": "cd prediction; npm i; cd ../",
4141
"deps_logging": "cd logging; npm i; cd ../",
42+
"deps_vision": "cd vision; npm i; cd ../",
4243
"deps_functions": "cd functions/uuid; npm i; cd ../..",
4344
"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 ../..;",
44-
"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",
45+
"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",
4546
"test": "npm run jshint && npm run cover"
4647
},
4748
"ava": {
4849
"files": [
49-
"test/appengine/**/*.test.js"
50+
"test/**/*.test.js"
5051
]
5152
},
5253
"devDependencies": {

test/vision/faceDetection.test.js

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2016, Google, Inc.
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
'use strict';
15+
16+
var test = require('ava');
17+
var fs = require('fs');
18+
var path = require('path');
19+
var faceDetectionExample = require('../../vision/faceDetection');
20+
var inputFile = path.resolve(path.join('../../vision', 'face.png'));
21+
var outputFile = path.resolve(path.join('../../vision', 'out.png'));
22+
23+
test.cb('should detect faces', function (t) {
24+
faceDetectionExample.main(
25+
inputFile,
26+
outputFile,
27+
function (err, faces) {
28+
t.ifError(err);
29+
t.is(faces.length, 1);
30+
var image = fs.readFileSync(outputFile);
31+
t.ok(image);
32+
t.end();
33+
}
34+
);
35+
});

vision/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
out.*

vision/README.md

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
## Cloud Vision API samples
2+
3+
These samples require two environment variables to be set:
4+
5+
- `GOOGLE_APPLICATION_CREDENTIALS` - Path to a service account file. You can
6+
download one from your Google project's "credentials" page.
7+
- `GCLOUD_PROJECT` - ID of your Google project.
8+
9+
See [gcloud-node authentication][auth] for more details.
10+
11+
[auth]: https://googlecloudplatform.github.io/gcloud-node/#/docs/guides/authentication
12+
13+
## Run a sample
14+
15+
Install dependencies first:
16+
17+
npm install
18+
19+
### Face detection sample
20+
21+
This sample uses [node-canvas](https://github.com/Automattic/node-canvas) to
22+
draw an output image. node-canvas depends on Cairo, which may require separate
23+
installation. See the node-canvas [installation section][canvas-install] for
24+
details.
25+
26+
[canvas-install]: https://github.com/Automattic/node-canvas#installation
27+
28+
Execute the sample:
29+
30+
node faceDetection "/path/to/image.jpg"

vision/face.png

458 KB
Loading

vision/faceDetection.js

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// Copyright 2016, Google, Inc.
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
'use strict';
15+
16+
// [START auth]
17+
// You must set the GOOGLE_APPLICATION_CREDENTIALS and GCLOUD_PROJECT
18+
// environment variables to run this sample. See:
19+
// https://github.com/GoogleCloudPlatform/gcloud-node/blob/master/docs/authentication.md
20+
var projectId = process.env.GCLOUD_PROJECT;
21+
22+
// Initialize gcloud
23+
var gcloud = require('gcloud')({
24+
projectId: projectId
25+
});
26+
27+
// Get a reference to the vision component
28+
var vision = gcloud.vision();
29+
// [END auth]
30+
31+
var fs = require('fs');
32+
var Canvas = require('canvas');
33+
var Image = Canvas.Image;
34+
35+
/**
36+
* Uses the Vision API to detect faces in the given file.
37+
*/
38+
function detectFaces(inputFile, callback) {
39+
// Make a call to the Vision API to detect the faces
40+
vision.detectFaces(inputFile, function (err, faces) {
41+
if (err) {
42+
return callback(err);
43+
}
44+
var numFaces = faces.length;
45+
console.log('Found ' + numFaces + (numFaces === 1 ? ' face' : ' faces'));
46+
callback(null, faces);
47+
});
48+
}
49+
50+
/**
51+
* Draws a polygon around the faces, then saves to outputFile.
52+
*/
53+
function highlightFaces(inputFile, faces, outputFile, callback) {
54+
fs.readFile(inputFile, function (err, image) {
55+
if (err) {
56+
return callback(err);
57+
}
58+
59+
// Open the original image into a canvas
60+
var img = new Image();
61+
img.src = image;
62+
var canvas = new Canvas(img.width, img.height);
63+
var context = canvas.getContext('2d');
64+
context.drawImage(img, 0, 0, img.width, img.height);
65+
66+
// Now draw boxes around all the faces
67+
context.strokeStyle = 'rgba(0,255,0,0.8)';
68+
context.lineWidth = '5';
69+
70+
faces.forEach(function (face) {
71+
context.beginPath();
72+
face.bounds.face.forEach(function (bounds) {
73+
context.lineTo(bounds.x, bounds.y);
74+
});
75+
context.lineTo(face.bounds.face[0].x, face.bounds.face[0].y);
76+
context.stroke();
77+
});
78+
79+
// Write the result to a file
80+
console.log('Writing to file ' + outputFile);
81+
var writeStream = fs.createWriteStream(outputFile);
82+
var pngStream = canvas.pngStream();
83+
84+
pngStream.on('data', function (chunk) {
85+
writeStream.write(chunk);
86+
});
87+
pngStream.on('error', console.log);
88+
pngStream.on('end', callback);
89+
});
90+
}
91+
92+
// Run the example
93+
function main(inputFile, outputFile, callback) {
94+
outputFile = outputFile || 'out.png';
95+
detectFaces(inputFile, function (err, faces) {
96+
if (err) {
97+
return callback(err);
98+
}
99+
100+
console.log('Highlighting...');
101+
highlightFaces(inputFile, faces, outputFile, function (err) {
102+
if (err) {
103+
return callback(err);
104+
}
105+
console.log('Finished!');
106+
callback(null, faces);
107+
});
108+
});
109+
}
110+
111+
exports.main = main;
112+
113+
if (module === require.main) {
114+
if (process.argv.length < 3) {
115+
console.log('Usage: node faceDetection <inputFile> [outputFile]');
116+
process.exit(1);
117+
}
118+
exports.main(process.argv[2], process.argv[3], console.log);
119+
}

vision/package.json

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "cloud-vision-samples",
3+
"description": "Node.js samples for Google Cloud Vision.",
4+
"version": "0.0.1",
5+
"private": true,
6+
"license": "Apache Version 2.0",
7+
"engines": {
8+
"node": ">=0.10.x"
9+
},
10+
"scripts": {
11+
"faceDetection": "node faceDetection.js"
12+
},
13+
"dependencies": {
14+
"gcloud": "^0.32.0",
15+
"canvas": "^1.3.15"
16+
}
17+
}

0 commit comments

Comments
 (0)