From 3f14b3c16b330e0ff743bdbd51ae4fb858fcc6d3 Mon Sep 17 00:00:00 2001 From: Eric Schmidt Date: Thu, 13 Feb 2020 12:08:02 -0800 Subject: [PATCH] fix: refactors person and face detection samples into separate files (#370) * fix: adds spaces to region tags, other fixes * fix: refactors people and face detection into separate files * fix: removes unneeded files * fix: switches copyright lines in samples --- video-intelligence/analyze.v1p3beta1.js | 365 ------------------ video-intelligence/analyze_face_detection.js | 97 +++++ .../analyze_face_detection_gcs.js | 94 +++++ .../analyze_person_detection.js | 110 ++++++ .../analyze_person_detection_gcs.js | 101 +++++ ...test.js => analyze_face_detection.test.js} | 28 +- .../analyze_face_detection_gcs.test.js | 31 ++ .../analyze_person_detection.test.js | 31 ++ .../analyze_person_detection_gcs.test.js | 31 ++ 9 files changed, 500 insertions(+), 388 deletions(-) delete mode 100644 video-intelligence/analyze.v1p3beta1.js create mode 100644 video-intelligence/analyze_face_detection.js create mode 100644 video-intelligence/analyze_face_detection_gcs.js create mode 100644 video-intelligence/analyze_person_detection.js create mode 100644 video-intelligence/analyze_person_detection_gcs.js rename video-intelligence/system-test/{analyze.v1p3beta1.test.js => analyze_face_detection.test.js} (52%) create mode 100644 video-intelligence/system-test/analyze_face_detection_gcs.test.js create mode 100644 video-intelligence/system-test/analyze_person_detection.test.js create mode 100644 video-intelligence/system-test/analyze_person_detection_gcs.test.js diff --git a/video-intelligence/analyze.v1p3beta1.js b/video-intelligence/analyze.v1p3beta1.js deleted file mode 100644 index 3fcb78eaaa..0000000000 --- a/video-intelligence/analyze.v1p3beta1.js +++ /dev/null @@ -1,365 +0,0 @@ -// Copyright 2020 Google LLC -// -// 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'; - -async function detectPerson(path) { - // [START video_detect_person_beta] - // Imports the Google Cloud Video Intelligence library + Node's fs library - const Video = require('@google-cloud/video-intelligence').v1p3beta1; - const fs = require('fs'); - // Creates a client - const video = new Video.VideoIntelligenceServiceClient(); - - /** - * TODO(developer): Uncomment the following line before running the sample. - */ - // const path = 'Local file to analyze, e.g. ./my-file.mp4'; - - // Reads a local video file and converts it to base64 - const file = fs.readFileSync(path); - const inputContent = file.toString('base64'); - - const request = { - inputContent: inputContent, - features: ['PERSON_DETECTION'], - videoContext: { - personDetectionConfig: { - // Must set includeBoundingBoxes to true to get poses and attributes. - includeBoundingBoxes: true, - includePoseLandmarks: true, - includeAttributes: true, - }, - }, - }; - // Detects people in a video - // We get the first result because only one video is processed. - const [operation] = await video.annotateVideo(request); - const results = await operation.promise(); - console.log('Waiting for operation to complete...'); - - // Gets annotations for video - const personAnnotations = - results[0].annotationResults[0].personDetectionAnnotations; - - for (const {tracks} of personAnnotations) { - console.log('Person detected:'); - for (const {segment, timestampedObjects} of tracks) { - if (segment.startTimeOffset.seconds === undefined) { - segment.startTimeOffset.seconds = 0; - } - if (segment.startTimeOffset.nanos === undefined) { - segment.startTimeOffset.nanos = 0; - } - if (segment.endTimeOffset.seconds === undefined) { - segment.endTimeOffset.seconds = 0; - } - if (segment.endTimeOffset.nanos === undefined) { - segment.endTimeOffset.nanos = 0; - } - console.log( - `\tStart: ${segment.startTimeOffset.seconds}.` + - `${(segment.startTimeOffset.nanos / 1e6).toFixed(0)}s` - ); - console.log( - `\tEnd: ${segment.endTimeOffset.seconds}.` + - `${(segment.endTimeOffset.nanos / 1e6).toFixed(0)}s` - ); - - // Each segment includes timestamped objects that - // include characteristic--e.g. clothes, posture - // of the person detected. - const [firstTimestampedObject] = timestampedObjects; - - // Attributes include unique pieces of clothing, - // poses, or hair color. - for (const {name, value} of firstTimestampedObject.attributes) { - console.log(`\tAttribute: ${name}; ` + `Value: ${value}`); - } - - // Landmarks in person detection include body parts. - for (const {name, point} of firstTimestampedObject.landmarks) { - console.log(`\tLandmark: ${name}; Vertex: ${point.x}, ${point.y}`); - } - } - } - // [END video_detect_person_beta] -} -async function detectPersonGCS(gcsUri) { - // [START video_detect_person_gcs_beta] - // Imports the Google Cloud Video Intelligence library - const Video = require('@google-cloud/video-intelligence').v1p3beta1; - // Creates a client - const video = new Video.VideoIntelligenceServiceClient(); - - /** - * TODO(developer): Uncomment the following line before running the sample. - */ - // const gcsUri = 'GCS URI of the video to analyze, e.g. gs://my-bucket/my-video.mp4'; - - const request = { - inputUri: gcsUri, - features: ['PERSON_DETECTION'], - videoContext: { - personDetectionConfig: { - // Must set includeBoundingBoxes to true to get poses and attributes. - includeBoundingBoxes: true, - includePoseLandmarks: true, - includeAttributes: true, - }, - }, - }; - // Detects people in a video - const [operation] = await video.annotateVideo(request); - const results = await operation.promise(); - console.log('Waiting for operation to complete...'); - - // Gets annotations for video - const personAnnotations = - results[0].annotationResults[0].personDetectionAnnotations; - - for (const {tracks} of personAnnotations) { - console.log('Person detected:'); - - for (const {segment, timestampedObjects} of tracks) { - if (segment.startTimeOffset.seconds === undefined) { - segment.startTimeOffset.seconds = 0; - } - if (segment.startTimeOffset.nanos === undefined) { - segment.startTimeOffset.nanos = 0; - } - if (segment.endTimeOffset.seconds === undefined) { - segment.endTimeOffset.seconds = 0; - } - if (segment.endTimeOffset.nanos === undefined) { - segment.endTimeOffset.nanos = 0; - } - console.log( - `\tStart: ${segment.startTimeOffset.seconds}` + - `.${(segment.startTimeOffset.nanos / 1e6).toFixed(0)}s` - ); - console.log( - `\tEnd: ${segment.endTimeOffset.seconds}.` + - `${(segment.endTimeOffset.nanos / 1e6).toFixed(0)}s` - ); - - // Each segment includes timestamped objects that - // include characteristic--e.g. clothes, posture - // of the person detected. - const [firstTimestampedObject] = timestampedObjects; - - // Attributes include unique pieces of clothing, - // poses, or hair color. - for (const {name, value} of firstTimestampedObject.attributes) { - console.log(`\tAttribute: ${name}; ` + `Value: ${value}`); - } - - // Landmarks in person detection include body parts. - for (const {name, point} of firstTimestampedObject.landmarks) { - console.log(`\tLandmark: ${name}; Vertex: ${point.x}, ${point.y}`); - } - } - } - // [END video_detect_person_gcs_beta] -} -async function detectFaces(path) { - // [START video_detect_faces_beta] - // Imports the Google Cloud Video Intelligence library + Node's fs library - const Video = require('@google-cloud/video-intelligence').v1p3beta1; - const fs = require('fs'); - // Creates a client - const video = new Video.VideoIntelligenceServiceClient(); - - /** - * TODO(developer): Uncomment the following line before running the sample. - */ - // const path = 'Local file to analyze, e.g. ./my-file.mp4'; - - // Reads a local video file and converts it to base64 - const file = fs.readFileSync(path); - const inputContent = file.toString('base64'); - - const request = { - inputContent: inputContent, - features: ['FACE_DETECTION'], - videoContext: { - faceDetectionConfig: { - // Must set includeBoundingBoxes to true to get facial attributes. - includeBoundingBoxes: true, - includeAttributes: true, - }, - }, - }; - // Detects faces in a video - const [operation] = await video.annotateVideo(request); - const results = await operation.promise(); - console.log('Waiting for operation to complete...'); - - // Gets annotations for video - const faceAnnotations = - results[0].annotationResults[0].faceDetectionAnnotations; - - for (const {tracks} of faceAnnotations) { - console.log('Face detected:'); - for (const {segment, timestampedObjects} of tracks) { - if (segment.startTimeOffset.seconds === undefined) { - segment.startTimeOffset.seconds = 0; - } - if (segment.startTimeOffset.nanos === undefined) { - segment.startTimeOffset.nanos = 0; - } - if (segment.endTimeOffset.seconds === undefined) { - segment.endTimeOffset.seconds = 0; - } - if (segment.endTimeOffset.nanos === undefined) { - segment.endTimeOffset.nanos = 0; - } - console.log( - `\tStart: ${segment.startTimeOffset.seconds}` + - `.${(segment.startTimeOffset.nanos / 1e6).toFixed(0)}s` - ); - console.log( - `\tEnd: ${segment.endTimeOffset.seconds}.` + - `${(segment.endTimeOffset.nanos / 1e6).toFixed(0)}s` - ); - - // Each segment includes timestamped objects that - // include characteristics of the face detected. - const [firstTimestapedObject] = timestampedObjects; - - for (const {name} of firstTimestapedObject.attributes) { - // Attributes include unique pieces of clothing, like glasses, - // poses, or hair color. - console.log(`\tAttribute: ${name}; `); - } - } - } - // [END video_detect_faces_beta] -} -async function detectFacesGCS(gcsUri) { - // [START video_detect_faces_gcs_beta] - // Imports the Google Cloud Video Intelligence library - const Video = require('@google-cloud/video-intelligence').v1p3beta1; - // Creates a client - const video = new Video.VideoIntelligenceServiceClient(); - - /** - * TODO(developer): Uncomment the following line before running the sample. - */ - // const gcsUri = 'GCS URI of the video to analyze, e.g. gs://my-bucket/my-video.mp4'; - - const request = { - inputUri: gcsUri, - features: ['FACE_DETECTION'], - videoContext: { - faceDetectionConfig: { - // Must set includeBoundingBoxes to true to get facial attributes. - includeBoundingBoxes: true, - includeAttributes: true, - }, - }, - }; - // Detects faces in a video - const [operation] = await video.annotateVideo(request); - const results = await operation.promise(); - console.log('Waiting for operation to complete...'); - - // Gets annotations for video - const faceAnnotations = - results[0].annotationResults[0].faceDetectionAnnotations; - - for (const {tracks} of faceAnnotations) { - console.log('Face detected:'); - - for (const {segment, timestampedObjects} of tracks) { - if (segment.startTimeOffset.seconds === undefined) { - segment.startTimeOffset.seconds = 0; - } - if (segment.startTimeOffset.nanos === undefined) { - segment.startTimeOffset.nanos = 0; - } - if (segment.endTimeOffset.seconds === undefined) { - segment.endTimeOffset.seconds = 0; - } - if (segment.endTimeOffset.nanos === undefined) { - segment.endTimeOffset.nanos = 0; - } - console.log( - `\tStart: ${segment.startTimeOffset.seconds}.` + - `${(segment.startTimeOffset.nanos / 1e6).toFixed(0)}s` - ); - console.log( - `\tEnd: ${segment.endTimeOffset.seconds}.` + - `${(segment.endTimeOffset.nanos / 1e6).toFixed(0)}s` - ); - - // Each segment includes timestamped objects that - // include characteristics of the face detected. - const [firstTimestapedObject] = timestampedObjects; - - for (const {name} of firstTimestapedObject.attributes) { - // Attributes include unique pieces of clothing, like glasses, - // poses, or hair color. - console.log(`\tAttribute: ${name}; `); - } - } - } - // [END video_detect_faces_gcs_beta] -} - -async function main() { - require(`yargs`) - .demand(1) - .command( - `video-person-gcs `, - `Detects people in a video stored in Google Cloud Storage using the Cloud Video Intelligence API.`, - {}, - opts => detectPersonGCS(opts.gcsUri) - ) - .command( - `video-person `, - `Detects people in a video stored in a local file using the Cloud Video Intelligence API.`, - {}, - opts => detectPerson(opts.path) - ) - .command( - `video-faces-gcs `, - `Detects faces in a video stored in Google Cloud Storage using the Cloud Video Intelligence API.`, - {}, - opts => detectFacesGCS(opts.gcsUri) - ) - .command( - `video-faces `, - `Detects faces in a video stored in a local file using the Cloud Video Intelligence API.`, - {}, - opts => detectFaces(opts.path) - ) - .example(`node $0 video-person ./resources/googlework_short.mp4`) - .example( - `node $0 video-person-gcs gs://cloud-samples-data/video/googlework_short.mp4` - ) - .example(`node $0 video-faces ./resources/googlework_short.mp4`) - .example( - `node $0 video-faces-gcs gs://cloud-samples-data/video/googlework_short.mp4` - ) - .wrap(120) - .recommendCommands() - .epilogue( - `For more information, see https://cloud.google.com/video-intelligence/docs` - ) - .help() - .strict().argv; -} - -main().catch(console.error); diff --git a/video-intelligence/analyze_face_detection.js b/video-intelligence/analyze_face_detection.js new file mode 100644 index 0000000000..cf2c9c8317 --- /dev/null +++ b/video-intelligence/analyze_face_detection.js @@ -0,0 +1,97 @@ +// Copyright 2020 Google LLC +// +// 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'; + +function main(path = 'YOUR_LOCAL_FILE') { + // [START video_detect_faces_beta] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const path = 'Local file to analyze, e.g. ./my-file.mp4'; + + // Imports the Google Cloud Video Intelligence library + Node's fs library + const Video = require('@google-cloud/video-intelligence').v1p3beta1; + const fs = require('fs'); + + // Creates a client + const video = new Video.VideoIntelligenceServiceClient(); + + // Reads a local video file and converts it to base64 + const file = fs.readFileSync(path); + const inputContent = file.toString('base64'); + + async function detectFaces() { + const request = { + inputContent: inputContent, + features: ['FACE_DETECTION'], + videoContext: { + faceDetectionConfig: { + // Must set includeBoundingBoxes to true to get facial attributes. + includeBoundingBoxes: true, + includeAttributes: true, + }, + }, + }; + // Detects faces in a video + // We get the first result because we only process 1 video + const [operation] = await video.annotateVideo(request); + const results = await operation.promise(); + console.log('Waiting for operation to complete...'); + + // Gets annotations for video + const faceAnnotations = + results[0].annotationResults[0].faceDetectionAnnotations; + for (const {tracks} of faceAnnotations) { + console.log('Face detected:'); + for (const {segment, timestampedObjects} of tracks) { + if (segment.startTimeOffset.seconds === undefined) { + segment.startTimeOffset.seconds = 0; + } + if (segment.startTimeOffset.nanos === undefined) { + segment.startTimeOffset.nanos = 0; + } + if (segment.endTimeOffset.seconds === undefined) { + segment.endTimeOffset.seconds = 0; + } + if (segment.endTimeOffset.nanos === undefined) { + segment.endTimeOffset.nanos = 0; + } + console.log( + `\tStart: ${segment.startTimeOffset.seconds}` + + `.${(segment.startTimeOffset.nanos / 1e6).toFixed(0)}s` + ); + console.log( + `\tEnd: ${segment.endTimeOffset.seconds}.` + + `${(segment.endTimeOffset.nanos / 1e6).toFixed(0)}s` + ); + + // Each segment includes timestamped objects that + // include characteristics of the face detected. + const [firstTimestapedObject] = timestampedObjects; + + for (const {name} of firstTimestapedObject.attributes) { + // Attributes include unique pieces of clothing, like glasses, + // poses, or hair color. + console.log(`\tAttribute: ${name}; `); + } + } + } + } + + detectFaces(); + // [END video_detect_faces_beta] +} + +main(...process.argv.slice(2)); diff --git a/video-intelligence/analyze_face_detection_gcs.js b/video-intelligence/analyze_face_detection_gcs.js new file mode 100644 index 0000000000..b28f64f373 --- /dev/null +++ b/video-intelligence/analyze_face_detection_gcs.js @@ -0,0 +1,94 @@ +// Copyright 2020 Google LLC +// +// 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'; + +function main(gcsUri = 'YOUR_STORAGE_URI') { + // [START video_detect_faces_gcs_beta] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const gcsUri = 'GCS URI of the video to analyze, e.g. gs://my-bucket/my-video.mp4'; + + // Imports the Google Cloud Video Intelligence library + Node's fs library + const Video = require('@google-cloud/video-intelligence').v1p3beta1; + + // Creates a client + const video = new Video.VideoIntelligenceServiceClient(); + + async function detectFacesGCS() { + const request = { + inputUri: gcsUri, + features: ['FACE_DETECTION'], + videoContext: { + faceDetectionConfig: { + // Must set includeBoundingBoxes to true to get facial attributes. + includeBoundingBoxes: true, + includeAttributes: true, + }, + }, + }; + // Detects faces in a video + // We get the first result because we only process 1 video + const [operation] = await video.annotateVideo(request); + const results = await operation.promise(); + console.log('Waiting for operation to complete...'); + + // Gets annotations for video + const faceAnnotations = + results[0].annotationResults[0].faceDetectionAnnotations; + + for (const {tracks} of faceAnnotations) { + console.log('Face detected:'); + + for (const {segment, timestampedObjects} of tracks) { + if (segment.startTimeOffset.seconds === undefined) { + segment.startTimeOffset.seconds = 0; + } + if (segment.startTimeOffset.nanos === undefined) { + segment.startTimeOffset.nanos = 0; + } + if (segment.endTimeOffset.seconds === undefined) { + segment.endTimeOffset.seconds = 0; + } + if (segment.endTimeOffset.nanos === undefined) { + segment.endTimeOffset.nanos = 0; + } + console.log( + `\tStart: ${segment.startTimeOffset.seconds}.` + + `${(segment.startTimeOffset.nanos / 1e6).toFixed(0)}s` + ); + console.log( + `\tEnd: ${segment.endTimeOffset.seconds}.` + + `${(segment.endTimeOffset.nanos / 1e6).toFixed(0)}s` + ); + + // Each segment includes timestamped objects that + // include characteristics of the face detected. + const [firstTimestapedObject] = timestampedObjects; + + for (const {name} of firstTimestapedObject.attributes) { + // Attributes include unique pieces of clothing, like glasses, + // poses, or hair color. + console.log(`\tAttribute: ${name}; `); + } + } + } + } + + detectFacesGCS(); + // [END video_detect_faces_gcs_beta] +} + +main(...process.argv.slice(2)); diff --git a/video-intelligence/analyze_person_detection.js b/video-intelligence/analyze_person_detection.js new file mode 100644 index 0000000000..69fb1b46aa --- /dev/null +++ b/video-intelligence/analyze_person_detection.js @@ -0,0 +1,110 @@ +// Copyright 2020 Google LLC +// +// 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'; + +function main(path = 'YOUR_LOCAL_FILE') { + // [START video_detect_person_beta] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const gcsUri = 'GCS URI of the video to analyze, e.g. gs://my-bucket/my-video.mp4'; + + // Imports the Google Cloud Video Intelligence library + Node's fs library + const Video = require('@google-cloud/video-intelligence').v1p3beta1; + const fs = require('fs'); + // Creates a client + const video = new Video.VideoIntelligenceServiceClient(); + + /** + * TODO(developer): Uncomment the following line before running the sample. + */ + // const path = 'Local file to analyze, e.g. ./my-file.mp4'; + + // Reads a local video file and converts it to base64 + const file = fs.readFileSync(path); + const inputContent = file.toString('base64'); + + async function detectPerson() { + const request = { + inputContent: inputContent, + features: ['PERSON_DETECTION'], + videoContext: { + personDetectionConfig: { + // Must set includeBoundingBoxes to true to get poses and attributes. + includeBoundingBoxes: true, + includePoseLandmarks: true, + includeAttributes: true, + }, + }, + }; + // Detects faces in a video + // We get the first result because we only process 1 video + const [operation] = await video.annotateVideo(request); + const results = await operation.promise(); + console.log('Waiting for operation to complete...'); + + // Gets annotations for video + const personAnnotations = + results[0].annotationResults[0].personDetectionAnnotations; + + for (const {tracks} of personAnnotations) { + console.log('Person detected:'); + + for (const {segment, timestampedObjects} of tracks) { + if (segment.startTimeOffset.seconds === undefined) { + segment.startTimeOffset.seconds = 0; + } + if (segment.startTimeOffset.nanos === undefined) { + segment.startTimeOffset.nanos = 0; + } + if (segment.endTimeOffset.seconds === undefined) { + segment.endTimeOffset.seconds = 0; + } + if (segment.endTimeOffset.nanos === undefined) { + segment.endTimeOffset.nanos = 0; + } + console.log( + `\tStart: ${segment.startTimeOffset.seconds}` + + `.${(segment.startTimeOffset.nanos / 1e6).toFixed(0)}s` + ); + console.log( + `\tEnd: ${segment.endTimeOffset.seconds}.` + + `${(segment.endTimeOffset.nanos / 1e6).toFixed(0)}s` + ); + + // Each segment includes timestamped objects that + // include characteristic--e.g. clothes, posture + // of the person detected. + const [firstTimestampedObject] = timestampedObjects; + + // Attributes include unique pieces of clothing, + // poses, or hair color. + for (const {name, value} of firstTimestampedObject.attributes) { + console.log(`\tAttribute: ${name}; Value: ${value}`); + } + + // Landmarks in person detection include body parts. + for (const {name, point} of firstTimestampedObject.landmarks) { + console.log(`\tLandmark: ${name}; Vertex: ${point.x}, ${point.y}`); + } + } + } + } + + detectPerson(); + // [END video_detect_person_beta] +} + +main(...process.argv.slice(2)); diff --git a/video-intelligence/analyze_person_detection_gcs.js b/video-intelligence/analyze_person_detection_gcs.js new file mode 100644 index 0000000000..d341590cd0 --- /dev/null +++ b/video-intelligence/analyze_person_detection_gcs.js @@ -0,0 +1,101 @@ +// Copyright 2020 Google LLC +// +// 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'; + +function main(gcsUri = 'YOUR_STORAGE_URI') { + // [START video_detect_person_gcs_beta] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const gcsUri = 'GCS URI of the video to analyze, e.g. gs://my-bucket/my-video.mp4'; + + // Imports the Google Cloud Video Intelligence library + Node's fs library + const Video = require('@google-cloud/video-intelligence').v1p3beta1; + + // Creates a client + const video = new Video.VideoIntelligenceServiceClient(); + + async function detectPersonGCS() { + const request = { + inputUri: gcsUri, + features: ['PERSON_DETECTION'], + videoContext: { + personDetectionConfig: { + // Must set includeBoundingBoxes to true to get poses and attributes. + includeBoundingBoxes: true, + includePoseLandmarks: true, + includeAttributes: true, + }, + }, + }; + // Detects faces in a video + // We get the first result because we only process 1 video + const [operation] = await video.annotateVideo(request); + const results = await operation.promise(); + console.log('Waiting for operation to complete...'); + + // Gets annotations for video + const personAnnotations = + results[0].annotationResults[0].personDetectionAnnotations; + + for (const {tracks} of personAnnotations) { + console.log('Person detected:'); + + for (const {segment, timestampedObjects} of tracks) { + if (segment.startTimeOffset.seconds === undefined) { + segment.startTimeOffset.seconds = 0; + } + if (segment.startTimeOffset.nanos === undefined) { + segment.startTimeOffset.nanos = 0; + } + if (segment.endTimeOffset.seconds === undefined) { + segment.endTimeOffset.seconds = 0; + } + if (segment.endTimeOffset.nanos === undefined) { + segment.endTimeOffset.nanos = 0; + } + console.log( + `\tStart: ${segment.startTimeOffset.seconds}` + + `.${(segment.startTimeOffset.nanos / 1e6).toFixed(0)}s` + ); + console.log( + `\tEnd: ${segment.endTimeOffset.seconds}.` + + `${(segment.endTimeOffset.nanos / 1e6).toFixed(0)}s` + ); + + // Each segment includes timestamped objects that + // include characteristic--e.g. clothes, posture + // of the person detected. + const [firstTimestampedObject] = timestampedObjects; + + // Attributes include unique pieces of clothing, + // poses, or hair color. + for (const {name, value} of firstTimestampedObject.attributes) { + console.log(`\tAttribute: ${name}; Value: ${value}`); + } + + // Landmarks in person detection include body parts. + for (const {name, point} of firstTimestampedObject.landmarks) { + console.log(`\tLandmark: ${name}; Vertex: ${point.x}, ${point.y}`); + } + } + } + } + + detectPersonGCS(); + // [END video_detect_person_gcs_beta] +} + +main(...process.argv.slice(2)); diff --git a/video-intelligence/system-test/analyze.v1p3beta1.test.js b/video-intelligence/system-test/analyze_face_detection.test.js similarity index 52% rename from video-intelligence/system-test/analyze.v1p3beta1.test.js rename to video-intelligence/system-test/analyze_face_detection.test.js index 2abc756882..2172af94de 100644 --- a/video-intelligence/system-test/analyze.v1p3beta1.test.js +++ b/video-intelligence/system-test/analyze_face_detection.test.js @@ -12,38 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -// https://cloud.google.com/video-intelligence/docs/ - 'use strict'; +const cp = require('child_process'); const {assert} = require('chai'); const {describe, it} = require('mocha'); -const cp = require('child_process'); const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); -const cmd = 'node analyze.v1p3beta1.js'; -const url = 'gs://cloud-samples-data/video/googlework_short.mp4'; +const cmd = `node analyze_face_detection.js`; const file = 'resources/googlework_short.mp4'; -describe('analyze v1p3beta1 samples', () => { - it('should detect people in a local file', async () => { - const output = execSync(`${cmd} video-person ${file}`); - assert.match(output, /Hair/); - }); - - it('should detect people in a GCS file', async () => { - const output = execSync(`${cmd} video-person-gcs ${url}`); - assert.match(output, /Hair/); - }); - - it('should detect faces in a local file', async () => { - const output = execSync(`${cmd} video-faces ${file}`); - assert.match(output, /glasses/); - }); - - it('should detect faces in a GCS file', async () => { - const output = execSync(`${cmd} video-faces-gcs ${url}`); +describe('analyzing faces in video', () => { + it('should identify faces in a local file', async () => { + const output = execSync(`${cmd} ${file}`); assert.match(output, /glasses/); }); }); diff --git a/video-intelligence/system-test/analyze_face_detection_gcs.test.js b/video-intelligence/system-test/analyze_face_detection_gcs.test.js new file mode 100644 index 0000000000..4cd9ae6a3c --- /dev/null +++ b/video-intelligence/system-test/analyze_face_detection_gcs.test.js @@ -0,0 +1,31 @@ +// Copyright 2020 Google LLC +// +// 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'; + +const cp = require('child_process'); +const {assert} = require('chai'); +const {describe, it} = require('mocha'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const cmd = `node analyze_face_detection_gcs.js`; +const gcsUri = 'gs://cloud-samples-data/video/googlework_short.mp4'; + +describe('analyzing faces in video', () => { + it('should identify faces in a file in Google Storage', async () => { + const output = execSync(`${cmd} ${gcsUri}`); + assert.match(output, /glasses/); + }); +}); diff --git a/video-intelligence/system-test/analyze_person_detection.test.js b/video-intelligence/system-test/analyze_person_detection.test.js new file mode 100644 index 0000000000..b802c3e1a6 --- /dev/null +++ b/video-intelligence/system-test/analyze_person_detection.test.js @@ -0,0 +1,31 @@ +// Copyright 2020 Google LLC +// +// 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'; + +const cp = require('child_process'); +const {assert} = require('chai'); +const {describe, it} = require('mocha'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const cmd = `node analyze_person_detection.js`; +const file = 'resources/googlework_short.mp4'; + +describe('analyzing people in video', () => { + it('should identify people in a local file', async () => { + const output = execSync(`${cmd} ${file}`); + assert.match(output, /Hair/); + }); +}); diff --git a/video-intelligence/system-test/analyze_person_detection_gcs.test.js b/video-intelligence/system-test/analyze_person_detection_gcs.test.js new file mode 100644 index 0000000000..1f359bf925 --- /dev/null +++ b/video-intelligence/system-test/analyze_person_detection_gcs.test.js @@ -0,0 +1,31 @@ +// Copyright 2020 Google LLC +// +// 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'; + +const cp = require('child_process'); +const {assert} = require('chai'); +const {describe, it} = require('mocha'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const cmd = `node analyze_person_detection_gcs.js`; +const gcsUri = 'gs://cloud-samples-data/video/googlework_short.mp4'; + +describe('analyzing people in video', () => { + it('should identify people in a file in Google Storage', async () => { + const output = execSync(`${cmd} ${gcsUri}`); + assert.match(output, /Hair/); + }); +});