diff --git a/project-oxford/project-oxford-tests.ts b/project-oxford/project-oxford-tests.ts
new file mode 100644
index 0000000000..3d662d5040
--- /dev/null
+++ b/project-oxford/project-oxford-tests.ts
@@ -0,0 +1,480 @@
+///
+///
+///
+///
+
+import oxford = require("project-oxford");
+
+import assert = require('assert');
+import _Promise = require('bluebird');
+import fs = require('fs');
+
+var client = new oxford.Client(process.env.OXFORD_KEY);
+
+// Store variables, no point in calling the api too often
+var billFaces = [];
+var personGroupId = "uuid.v4()";
+var personGroupId2 = "uuid.v4()";
+var billPersonId: string;
+
+describe('Project Oxford Face API Test', function () {
+ afterEach(function() {
+ // delay after each test to prevent throttling
+ var now = +new Date() + 250;
+ while(now > +new Date());
+ });
+
+ describe('#detect()', function () {
+ it('detects a face in a stream', function (done) {
+ client.face.detect({
+ stream: fs.createReadStream('./test/images/face1.jpg'),
+ analyzesFaceLandmarks: true,
+ analyzesAge: true,
+ analyzesGender: true,
+ analyzesHeadPose: true
+ }).then(function (response) {
+ assert.ok(response[0].faceId);
+ assert.ok(response[0].faceRectangle);
+ assert.ok(response[0].faceLandmarks);
+ assert.ok(response[0].attributes.gender);
+ assert.ok(response[0].attributes.headPose);
+
+ assert.equal(response[0].attributes.gender, 'male');
+ done();
+ });
+ });
+
+ it('detects a face in a local file', function (done) {
+ client.face.detect({
+ path: './test/images/face1.jpg',
+ analyzesFaceLandmarks: true,
+ analyzesAge: true,
+ analyzesGender: true,
+ analyzesHeadPose: true
+ }).then(function (response) {
+ assert.ok(response[0].faceId);
+ assert.ok(response[0].faceRectangle);
+ assert.ok(response[0].faceLandmarks);
+ assert.ok(response[0].attributes.gender);
+ assert.ok(response[0].attributes.headPose);
+
+ assert.equal(response[0].attributes.gender, 'male');
+ done();
+ });
+ });
+
+ it('detects a face in a remote file', function (done) {
+ client.face.detect({
+ url: 'https://upload.wikimedia.org/wikipedia/commons/1/19/Bill_Gates_June_2015.jpg',
+ analyzesFaceLandmarks: true,
+ analyzesAge: true,
+ analyzesGender: true,
+ analyzesHeadPose: true
+ }).then(function (response) {
+ assert.ok(response[0].faceId);
+ assert.ok(response[0].faceRectangle);
+ assert.ok(response[0].faceLandmarks);
+ assert.ok(response[0].attributes.gender);
+ assert.ok(response[0].attributes.headPose);
+
+ assert.equal(response[0].attributes.gender, 'male');
+ done();
+ });
+ });
+ });
+
+ describe('#similar()', function () {
+ it('detects similar faces', function (done) {
+ var detects = [];
+
+ this.timeout(10000);
+
+ detects.push(client.face.detect({
+ path: './test/images/face1.jpg',
+ }).then(function(response) {
+ assert.ok(response[0].faceId)
+ billFaces.push(response[0].faceId);
+ }));
+
+ detects.push(client.face.detect({
+ path: './test/images/face2.jpg',
+ }).then(function(response) {
+ assert.ok(response[0].faceId)
+ billFaces.push(response[0].faceId);
+ }));
+
+ _Promise.all(detects).then(function() {
+ client.face.similar(billFaces[0], [billFaces[1]]).then(function(response) {
+ done();
+ });
+ });
+ });
+ });
+
+ describe('#grouping()', function () {
+ it('detects groups faces', function (done) {
+ var faceIds = [];
+
+ this.timeout(10000);
+
+ client.face.detect({
+ path: './test/images/face-group.jpg',
+ }).then(function(response) {
+ response.forEach(function (face) {
+ faceIds.push(face.faceId);
+ });
+
+ assert.equal(faceIds.length, 6);
+ }).then(function() {
+ client.face.grouping(faceIds).then(function (response) {
+ assert.ok(response.messyGroup);
+ done();
+ });
+ });
+ });
+ });
+
+ describe('#verify()', function () {
+ it('verifies a face against another face', function (done) {
+ this.timeout(10000);
+
+ assert.equal(billFaces.length, 2);
+
+ client.face.verify(billFaces).then(function (response) {
+ assert.ok(response);
+ assert.ok((response.isIdentical === true || response.isIdentical === false));
+ assert.ok(response.confidence);
+ done();
+ });
+ });
+ });
+
+ describe('#PersonGroup', function () {
+ before(function(done) {
+ this.timeout(5000);
+ // In order to test the
+ // training feature, we have to start trainign - sadly, we can't
+ // delete the group then. So we clean up before we run tests - and to wait
+ // for cleanup to finish, we're just using done().
+ client.face.personGroup.list().then(function (response) {
+ var promises = [];
+
+ response.forEach(function (personGroup) {
+ if (personGroup.name.indexOf('po-node-test-group') > -1) {
+ promises.push(client.face.personGroup.delete(personGroup.personGroupId));
+ }
+ });
+
+ _Promise.all(promises).then(function () {
+ done();
+ });
+ });
+ });
+
+ it('creates a PersonGroup', function (done) {
+ client.face.personGroup.create(personGroupId, 'po-node-test-group', 'test-data').then(function (response) {
+ assert.ok(true, "void response expected");
+ done();
+ })
+ .catch(function (error) {
+ assert.ok(false, JSON.stringify(error));
+ done();
+ });
+ });
+
+ it('lists PersonGroups', function (done) {
+ client.face.personGroup.list().then(function (response) {
+ assert.ok(response);
+ assert.ok((response.length > 0));
+ assert.ok(response[0].personGroupId);
+ done();
+ });
+ });
+
+ it('gets a PersonGroup', function (done) {
+ client.face.personGroup.get(personGroupId).then(function (response) {
+ assert.equal(response.personGroupId, personGroupId);
+ assert.equal(response.name, 'po-node-test-group');
+ assert.equal(response.userData, 'test-data');
+ done();
+ });
+ });
+
+ it('updates a PersonGroup', function (done) {
+ client.face.personGroup.update(personGroupId, 'po-node-test-group2', 'test-data2').then(function (response) {
+ assert.ok(true, "void response expected");;
+ done();
+ }).catch(function (response) {
+ assert.equal(response, 'PersonGroupTrainingNotFinished')
+ });
+ });
+
+ it('gets a PersonGroup\'s training status', function (done) {
+ client.face.personGroup.trainingStatus(personGroupId).then(function (response) {
+ done();
+ }).catch(function (response) {
+ assert.equal(response.code, 'PersonGroupNotTrained');
+ done();
+ });
+ });
+
+ it('starts a PersonGroup\'s training', function (done) {
+ client.face.personGroup.trainingStart(personGroupId).then(function (response) {
+ assert.equal(response.status, 'running');
+ done();
+ }).catch(function (response) {
+ assert.equal(response.status, 'running');
+ done();
+ });
+ });
+
+ it('deletes a PersonGroup', function (done) {
+ client.face.personGroup.delete(personGroupId).then(function (response) {
+ assert.ok(true, "void response");
+ done();
+ }).catch(function (response) {
+ assert.equal(response.code, 'PersonGroupTrainingNotFinished');
+ done();
+ });
+ });
+ });
+
+ describe('#Person', function () {
+
+ it('creates a PersonGroup for the Person', function (done) {
+ client.face.personGroup.create(personGroupId2, 'po-node-test-group', 'test-data')
+ .then(function (response) {
+ assert.ok(true, "void response expected");
+ done();
+ })
+ .catch(function (error) {
+ assert.ok(false, JSON.stringify(error));
+ done();
+ });
+ });
+
+ it('creates a Person', function (done) {
+ client.face.person.create(personGroupId2, [billFaces[0]], 'test-bill', 'test-data')
+ .then(function (response) {
+ assert.ok(response.personId);
+ billPersonId = response.personId;
+ done();
+ })
+ .catch(function (error) {
+ assert.ok(false, JSON.stringify(error));
+ done();
+ });
+ });
+
+ it('gets a Person', function (done) {
+ client.face.person.get(personGroupId2, billPersonId).then(function (response) {
+ assert.ok(response.personId);
+ done();
+ })
+ .catch(function (error) {
+ assert.ok(false, JSON.stringify(error));
+ done();
+ });
+ });
+
+ it('updates a Person', function (done) {
+ client.face.person.update(personGroupId2, billPersonId, [billFaces[0]], 'test-bill', 'test-data')
+ .then(function (response) {
+ assert.ok(true, "void response expected");
+ done();
+ })
+ });
+
+ it('adds a face to a Person', function (done) {
+ client.face.person.addFace(personGroupId2, billPersonId, billFaces[1], 'test-data')
+ .then(function (response) {
+ assert.ok(true, "void response expected");
+ done();
+ })
+ .catch(function (error) {
+ assert.ok(false, JSON.stringify(error));
+ done();
+ });
+ });
+
+ it('gets a face from a Person', function (done) {
+ client.face.person.getFace(personGroupId2, billPersonId, billFaces[1])
+ .then(function (response) {
+ assert.ok(response.userData);
+ assert.equal(response.userData, 'test-data');
+ done();
+ })
+ .catch(function (error) {
+ assert.ok(false, JSON.stringify(error));
+ done();
+ });
+ });
+
+ it('updates a face on a Person', function (done) {
+ client.face.person.updateFace(personGroupId2, billPersonId, billFaces[1], 'test-data')
+ .then(function (response) {
+ assert.ok(true, "void response expected");
+ done();
+ })
+ .catch(function (error) {
+ assert.ok(false, JSON.stringify(error));
+ done();
+ });
+ });
+
+ it('deletes a face on a Person', function (done) {
+ client.face.person.deleteFace(personGroupId2, billPersonId, billFaces[1])
+ .then(function (response) {
+ assert.ok(true, "void response expected");
+ done();
+ })
+ .catch(function (error) {
+ assert.ok(false, JSON.stringify(error));
+ done();
+ });
+ });
+
+ it('lists Persons', function (done) {
+ client.face.person.list(personGroupId2)
+ .then(function (response) {
+ assert.ok(response[0].personId);
+ done();
+ })
+ .catch(function (error) {
+ assert.ok(false, JSON.stringify(error));
+ done();
+ });
+ });
+
+ it('deletes a Person', function (done) {
+ client.face.person.delete(personGroupId2, billPersonId)
+ .then(function (response) {
+ assert.ok(true, "void response expected");
+ done();
+ })
+ .catch(function (error) {
+ assert.ok(false, JSON.stringify(error));
+ done();
+ });
+ });
+ });
+});
+
+describe('Project Oxford Vision API Test', function () {
+ before(function() {
+ // ensure the output directory exists
+ if(!fs.existsSync('./test/output')){
+ fs.mkdirSync('./test/output', 0766);
+ }
+ });
+
+ afterEach(function() {
+ // delay after each test to prevent throttling
+ var now = +new Date() + 250;
+ while(now > +new Date());
+ });
+
+ it('analyzes a local image', function (done) {
+ this.timeout(10000);
+ client.vision.analyzeImage({
+ path: './test/images/vision.jpg',
+ ImageType: true,
+ Color: true,
+ Faces: true,
+ Adult: true,
+ Categories: true
+ })
+ .then(function (response) {
+ assert.ok(response);
+ assert.ok(response.categories);
+ assert.ok(response.adult);
+ assert.ok(response.metadata);
+ assert.ok(response.faces);
+ assert.ok(response.color);
+ assert.ok(response.imageType);
+ done();
+ })
+ });
+
+ it('analyzes an online image', function (done) {
+ this.timeout(10000);
+ client.vision.analyzeImage({
+ url: 'https://upload.wikimedia.org/wikipedia/commons/1/19/Bill_Gates_June_2015.jpg',
+ ImageType: true,
+ Color: true,
+ Faces: true,
+ Adult: true,
+ Categories: true
+ })
+ .then(function (response) {
+ assert.ok(response);
+ assert.ok(response.categories);
+ assert.ok(response.adult);
+ assert.ok(response.metadata);
+ assert.ok(response.faces);
+ assert.ok(response.color);
+ assert.ok(response.imageType);
+ done();
+ });
+ });
+
+ it('creates a thumbnail for a local image', function (done) {
+ this.timeout(10000);
+ client.vision.thumbnail({
+ path: './test/images/vision.jpg',
+ pipe: fs.createWriteStream('./test/output/thumb2.jpg'),
+ width: 100,
+ height: 100,
+ smartCropping: true
+ })
+ .then(function (response) {
+ var stats = fs.statSync('./test/output/thumb2.jpg');
+ assert.ok((stats.size > 0));
+ done();
+ });
+ });
+
+ it('creates a thumbnail for an online image', function (done) {
+ this.timeout(10000);
+ client.vision.thumbnail({
+ url: 'https://upload.wikimedia.org/wikipedia/commons/1/19/Bill_Gates_June_2015.jpg',
+ pipe: fs.createWriteStream('./test/output/thumb1.jpg'),
+ width: 100,
+ height: 100,
+ smartCropping: true
+ })
+ .then(function (response) {
+ var stats = fs.statSync('./test/output/thumb1.jpg');
+ assert.ok((stats.size > 0));
+ done();
+ });
+ });
+
+ it('runs OCR on a local image', function (done) {
+ this.timeout(10000);
+ client.vision.ocr({
+ path: './test/images/vision.jpg',
+ language: 'en',
+ detectOrientation: true
+ })
+ .then(function (response) {
+ assert.ok(response.language);
+ assert.ok(response.regions);
+ done();
+ });
+ });
+
+ it('runs OCR on an online image', function (done) {
+ this.timeout(10000);
+ client.vision.ocr({
+ url: 'https://upload.wikimedia.org/wikipedia/commons/1/19/Bill_Gates_June_2015.jpg',
+ language: 'en',
+ detectOrientation: true
+ })
+ .then(function (response) {
+ assert.ok(response.language);
+ assert.ok(response.orientation);
+ done();
+ });
+ });
+});
\ No newline at end of file
diff --git a/project-oxford/project-oxford.d.ts b/project-oxford/project-oxford.d.ts
new file mode 100644
index 0000000000..dffecc3615
--- /dev/null
+++ b/project-oxford/project-oxford.d.ts
@@ -0,0 +1,522 @@
+// Type definitions for project-oxford v0.1.3
+// Project: https://github.com/felixrieseberg/project-oxford
+// Definitions by: Scott Southwood
+// Definitions: https://github.com/borisyankov/DefinitelyTyped
+
+///
+///
+
+declare module "project-oxford" {
+ import Promise = require("bluebird");
+ import stream = require("stream");
+
+ export class Client {
+ constructor(apiKey: string);
+ private _key: string;
+ public face: FaceAPI;
+ public vision: VisionAPI;
+ }
+
+ export class FaceAPI {
+
+ /**
+ * Call the Face Detected API
+ * Detects human faces in an image and returns face locations, face landmarks, and
+ * optional attributes including head-pose, gender, and age. Detection is an essential
+ * API that provides faceId to other APIs like Identification, Verification,
+ * and Find Similar.
+ *
+ * @param {object} options - Options object
+ * @param {string} options.url - URL to image to be used
+ * @param {string} options.path - Path to image to be used
+ * @param {stream} options.stream - Stream for image to be used
+ * @param {boolean} options.analyzesFaceLandmarks - Analyze face landmarks?
+ * @param {boolean} options.analyzesAge - Analyze age?
+ * @param {boolean} options.analyzesGender - Analyze gender?
+ * @param {boolean} options.analyzesHeadPose - Analyze headpose?
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public detect(options: Options.Detect): Promise<[FaceResponses.Detect]>;
+
+ /**
+ * Detect similar faces using faceIds (as returned from the detect API)
+ * @param {string} sourceFace - String of faceId for the source face
+ * @param {string[]} candidateFaces - Array of faceIds to use as candidates
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public similar(sourceFaceId: string, candidateFacesIds: string[]): Promise;
+
+ /**
+ * Divides candidate faces into groups based on face similarity using faceIds.
+ * The output is one or more disjointed face groups and a MessyGroup.
+ * A face group contains the faces that have similar looking, often of the same person.
+ * There will be one or more face groups ranked by group size, i.e. number of face.
+ * Faces belonging to the same person might be split into several groups in the result.
+ * The MessyGroup is a special face group that each face is not similar to any other
+ * faces in original candidate faces. The messyGroup will not appear in the result if
+ * all faces found their similar counterparts. The candidate face list has a
+ * limit of 100 faces.
+ *
+ * @param {string[]} faces - Array of faceIds to use
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public grouping(faces: string[]): Promise;
+
+ /**
+ * Identifies persons from a person group by one or more input faces.
+ * To recognize which person a face belongs to, Face Identification needs a person group
+ * that contains number of persons. Each person contains one or more faces. After a person
+ * group prepared, it should be trained to make it ready for identification. Then the
+ * identification API compares the input face to those persons' faces in person group and
+ * returns the best-matched candidate persons, ranked by confidence.
+ *
+ * @param {string[]} faces - Array of faceIds to use
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public identify(faceIDs: string[], options: Options.Identify): Promise;
+
+ /**
+ * Analyzes two faces and determine whether they are from the same person.
+ * Verification works well for frontal and near-frontal faces.
+ * For the scenarios that are sensitive to accuracy please use with own judgment.
+ * @param {string[]} faces - Array containing two faceIds to use
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public verify(faces: string[]): Promise;
+
+ /**
+ * @namespace
+ * @memberof face
+ */
+ public personGroup: PersonGroup;
+ public person: Person;
+ }
+
+ export class VisionAPI {
+ /**
+ * This operation does a deep analysis on the given image and then extracts a
+ * set of rich visual features based on the image content.
+ *
+ * @param {Object} options - Options object describing features to extract
+ * @param {string} options.url - Url to image to be analyzed
+ * @param {string} options.path - Path to image to be analyzed
+ * @param {boolean} options.ImageType - Detects if image is clipart or a line drawing.
+ * @param {boolean} options.Color - Determines the accent color, dominant color, if image is black&white.
+ * @param {boolean} options.Faces - Detects if faces are present. If present, generate coordinates, gender and age.
+ * @param {boolean} options.Adult - Detects if image is pornographic in nature (nudity or sex act). Sexually suggestive content is also detected.
+ * @param {boolean} options.Categories - Image categorization; taxonomy defined in documentation.
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public analyzeImage(options: Options.Analyze): Promise;
+
+ /**
+ * Generate a thumbnail image to the user-specified width and height. By default, the
+ * service analyzes the image, identifies the region of interest (ROI), and generates
+ * smart crop coordinates based on the ROI. Smart cropping is designed to help when you
+ * specify an aspect ratio that differs from the input image.
+ *
+ * @param {Object} options - Options object describing features to extract
+ * @param {string} options.url - Url to image to be thumbnailed
+ * @param {string} options.path - Path to image to be thumbnailed
+ * @param {number} options.width - Width of the thumb in pixels
+ * @param {number} options.height - Height of the thumb in pixels
+ * @param {boolean} options.smartCropping - Should SmartCropping be enabled?
+ * @param {Object} options.pipe - We'll pipe the returned image to this object
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public thumbnail(options: Options.Thumbnail): Promise;
+
+ /**
+ * Optical Character Recognition (OCR) detects text in an image and extracts the recognized
+ * characters into a machine-usable character stream.
+ *
+ * @param {Object} options - Options object describing features to extract
+ * @param {string} options.url - Url to image to be analyzed
+ * @param {string} options.path - Path to image to be analyzed
+ * @param {string} options.language - BCP-47 language code of the text to be detected in the image. Default value is "unk", then the service will auto detect the language of the text in the image.
+ * @param {string} options.detectOrientation - Detect orientation of text in the image
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public ocr(options: Options.Ocr): Promise;
+ }
+
+ export class PersonGroup {
+ /**
+ * Creates a new person group with a user-specified ID.
+ * A person group is one of the most important parameters for the Identification API.
+ * The Identification searches person faces in a specified person group.
+ *
+ * @param {string} personGroupId - Numbers, en-us letters in lower case, '-', '_'. Max length: 64
+ * @param {string} name - Person group display name. The maximum length is 128.
+ * @param {string} userData - User-provided data attached to the group. The size limit is 16KB.
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public create(personGroupId: string, name: string, userData: string): Promise;
+
+ /**
+ * Deletes an existing person group.
+ *
+ * @param {string} personGroupId - Name of person group to delete
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public delete(personGroupId: string): Promise;
+
+ /**
+ * Gets an existing person group.
+ *
+ * @param {string} personGroupId - Name of person group to get
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public get(personGroupId: string): Promise;
+
+ /**
+ * Retrieves the training status of a person group. Training is triggered by the Train PersonGroup API.
+ * The training will process for a while on the server side. This API can query whether the training
+ * is completed or ongoing.
+ *
+ * @param {string} personGroupId - Name of person group to get
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public trainingStatus(personGroupId: string): Promise;
+
+ /**
+ * Starts a person group training.
+ * Training is a necessary preparation process of a person group before identification.
+ * Each person group needs to be trained in order to call Identification. The training
+ * will process for a while on the server side even after this API has responded.
+ *
+ * @param {string} personGroupId - Name of person group to get
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public trainingStart(personGroupId: string): Promise;
+
+ /**
+ * Updates an existing person group's display name and userData.
+ *
+ * @param {string} personGroupId - Numbers, en-us letters in lower case, '-', '_'. Max length: 64
+ * @param {string} name - Person group display name. The maximum length is 128.
+ * @param {string} userData - User-provided data attached to the group. The size limit is 16KB.
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public update(personGroupId: string, name: string, userData: string): Promise;
+
+ /**
+ * Lists all person groups in the current subscription.
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public list(): Promise;
+ }
+
+ export class Person {
+ /**
+ * Adds a face to a person for identification. The maximum face count for each person is 32.
+ * The face ID must be added to a person before its expiration. Typically a face ID expires
+ * 24 hours after detection.
+ *
+ * @param {string} personGroupId - The target person's person group.
+ * @param {string} personId - The target person that the face is added to.
+ * @param {string} faceId - The ID of the face to be added. The maximum face amount for each person is 32.
+ * @param {string} userData - Optional. Attach user data to person's face. The maximum length is 1024.
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public addFace(personGroupId: string, personId: string, faceId: string, userData?: string): Promise;
+
+ /**
+ * Deletes a face from a person.
+ *
+ * @param {string} personGroupId - The target person's person group.
+ * @param {string} personId - The target person that the face is removed from.
+ * @param {string} faceId - The ID of the face to be deleted.
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public deleteFace(personGroupId: string, personId: string, faceId: string): Promise;
+
+ /**
+ * Updates a face for a person.
+ *
+ * @param {string} personGroupId - The target person's person group.
+ * @param {string} personId - The target person that the face is updated on.
+ * @param {string} faceId - The ID of the face to be updated.
+ * @param {string} userData - Optional. Attach user data to person's face. The maximum length is 1024.
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public updateFace(personGroupId: string, personId: string, faceId: string, userData: string): Promise;
+
+ /**
+ * Get a face for a person.
+ *
+ * @param {string} personGroupId - The target person's person group.
+ * @param {string} personId - The target person that the face is to get from.
+ * @param {string} faceId - The ID of the face to get.
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public getFace(personGroupId: string, personId: string, faceId: string): Promise;
+
+ /**
+ * Creates a new person in a specified person group for identification.
+ * The number of persons has a subscription limit. Free subscription amount is 1000 persons.
+ * The maximum face count for each person is 32.
+ *
+ * @param {string} personGroupId - The target person's person group.
+ * @param {string[]} faces - Array of face id's for the target person
+ * @param {string} name - Target person's display name. The maximum length is 128.
+ * @param {string} userData - Optional fields for user-provided data attached to a person. Size limit is 16KB.
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public create(personGroupId: string, faces: string[], name: string, userData: string): Promise<{ personId: string }>;
+
+ /**
+ * Deletes an existing person from a person group.
+ *
+ * @param {string} personGroupId - The target person's person group.
+ * @param {string} personId - The target person to delete.
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public delete(personGroupId: string, personId: string): Promise;
+
+ /**
+ * Gets an existing person from a person group.
+ *
+ * @param {string} personGroupId - The target person's person group.
+ * @param {string} personId - The target person to get.
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public get(personGroupId: string, personId: string): Promise;
+
+ /**
+ * Updates a person's information.
+ *
+ * @param {string} personGroupId - The target person's person group.
+ * @param {string[]} faces - Array of face id's for the target person
+ * @param {string} name - Target person's display name. The maximum length is 128.
+ * @param {string} userData - Optional fields for user-provided data attached to a person. Size limit is 16KB.
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public update(personGroupId: string, personId: string, faces: string[], name: string, userData: string): Promise;
+
+ /**
+ * Lists all persons in a person group, with the person information.
+ *
+ * @param {string} personGroupId - The target person's person group.
+ * @return {Promise} - Promise resolving with the resulting JSON
+ */
+ public list(personGroupId: string): Promise;
+ }
+
+ module Options {
+ interface Detect {
+ url?: string; // URL to image to be used
+ path?: string; // Path to image to be used
+ stream?: stream.Stream; // Stream of an image to be used
+ analyzesFaceLandmarks?: boolean; // Analyze face landmarks?
+ analyzesAge?: boolean; // Analyze age?
+ analyzesGender?: boolean; // Analyze gender?
+ analyzesHeadPose?: boolean; //Analyze headpose?
+ }
+
+ interface Identify {
+ personGroupId: string;
+ maxNumOfCandidatesReturned: number; // range is 1-10
+ }
+
+ interface Analyze {
+ url?: string; // Url to image to be analyzed
+ path?: string; // Path to image to be analyzed
+ ImageType?: boolean; // Detects if image is clipart or a line drawing.
+ Color?: boolean; // Determines the accent color, dominant color, if image is black& white.
+ Faces?: boolean; // Detects if faces are present.If present, generate coordinates, gender and age.
+ Adult?: boolean; // Detects if image is pornographic in nature(nudity or sex act).Sexually suggestive content is also detected.
+ Categories?: boolean; // Image categorization; taxonomy defined in documentation.
+ }
+
+ interface Thumbnail {
+ url?: string; // Url to image to be thumbnailed
+ path?: string; // Path to image to be thumbnailed
+ width?: number; // Width of the thumb in pixels
+ height?: number; // Height of the thumb in pixels
+ smartCropping?: boolean; // Should SmartCropping be enabled?
+ pipe?: stream.Writable; // We'll pipe the returned image to this object
+ }
+
+ interface Ocr {
+ url?: string; // URL to image to be analyzed
+ path?: string; // Path to image to be analyzed
+ language?: string; //BCP - 47 language code of the text to be detected in the image.Default value is "unk", then the service will auto detect the language of the text in the image.
+ detectOrientation?: boolean; // Detect orientation of text in the image
+ }
+ }
+
+ module FaceResponses {
+ interface FaceRectangle {
+ top: number;
+ left: number;
+ width: number;
+ height: number;
+ }
+
+ interface point {
+ x: number;
+ y: number;
+ }
+
+ interface FaceLandmarks {
+ "pupilLeft": point;
+ "pupilRight": point;
+ "noseTip": point;
+ "mouthLeft": point;
+ "mouthRight": point;
+ "eyebrowLeftOuter": point;
+ "eyebrowLeftInner": point;
+ "eyeLeftOuter": point;
+ "eyeLeftTop": point;
+ "eyeLeftBottom": point;
+ "eyeLeftInner": point;
+ "eyebrowRightInner": point;
+ "eyebrowRightOuter": point;
+ "eyeRightInner": point;
+ "eyeRightTop": point;
+ "eyeRightBottom": point;
+ "eyeRightOuter": point;
+ "noseRootLeft": point;
+ "noseRootRight": point;
+ "noseLeftAlarTop": point;
+ "noseRightAlarTop": point;
+ "noseLeftAlarOutTip": point;
+ "noseRightAlarOutTip": point;
+ "upperLipTop": point;
+ "upperLipBottom": point;
+ "underLipTop": point;
+ "underLipBottom": point;
+ }
+
+ interface Attributes {
+ "headPose": { "pitch": number, "roll": number, "yaw": number };
+ "gender": string;
+ "age": number;
+ }
+
+ export interface Detect {
+ "faceId": string;
+ "faceRectangle": FaceRectangle;
+ "faceLandmarks": FaceLandmarks;
+ "attributes": Attributes;
+ }
+
+ export interface Similar {
+ "faceIds": string[];
+ }
+
+ export interface Grouping {
+ "groups": string[];
+ "messyGroup": string[];
+ }
+
+ export interface Identify {
+ "faceId": string;
+ "candidates": [{
+ personId: string;
+ confidence: number;
+ }];
+ }
+
+ export interface Verify {
+ "isIdentical": boolean;
+ "confidence": number;
+ }
+ }
+
+ module PersonGroupResponses {
+
+ export interface PersonGroup {
+ "personGroupId": string;
+ "name": string;
+ "userData": string;
+ }
+
+ export interface TrainingStatus {
+ "personGroupId": string;
+ "status": string;
+ "startTime": string;
+ "endTime": string;
+ }
+ }
+
+ module PersonResponses {
+ export interface Create {
+ "personId": string;
+ }
+
+ export interface Person {
+ "personId": string;
+ "faceIds": string[];
+ "name": string;
+ "userData": string;
+ }
+
+ export interface Face {
+ "faceId": string;
+ "userData": string;
+ }
+ }
+
+ module VisionResponses {
+ export interface Analyze {
+ "categories": [{
+ "name": string;
+ "score": number;
+ }],
+ "adult": {
+ "isAdultContent": boolean;
+ "isRacyContent": boolean;
+ "adultScore": number;
+ "racyScore": number;
+ },
+ "requestId": string;
+ "metadata": {
+ "width": number;
+ "height": number;
+ "format": string;
+ },
+ "faces": [
+ {
+ "age": number;
+ "gender": string;
+ "faceRectangle": {
+ "left": number;
+ "top": number;
+ "width": number;
+ "height": number;
+ }
+ }
+ ],
+ "color": {
+ "dominantColorForeground": string;
+ "dominantColorBackground": string;
+ "dominantColors": string[];
+ "accentColor": string;
+ "isBWImg": boolean;
+ },
+ "imageType": {
+ "clipArtType": number;
+ "lineDrawingType": number;
+ }
+ }
+
+
+ export interface Ocr {
+ "language": string;
+ "textAngle": number;
+ "orientation": string;
+ "regions": [{
+ "boundingBox": string;
+ "lines": [{
+ "boundingBox": string;
+ "words": [{
+ "boundingBox": string;
+ "text": string;
+ }]
+ }]
+ }]
+ }
+ }
+}
\ No newline at end of file