diff --git a/.gitignore b/.gitignore index a5677a4..9b74490 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ __pycache__/ modules/ node_modules config.js +config.json diff --git a/client/api/AWSRekognition.js b/client/api/AWSRekognition.js new file mode 100644 index 0000000..3113ee9 --- /dev/null +++ b/client/api/AWSRekognition.js @@ -0,0 +1,32 @@ +const express = require('express'); +const router = express.Router(); +const { detectFace } = require('../aws_rekognition/aws_rekognition_client'); +const { OK, BAD_REQUEST, NOT_FOUND } = require('../config/config'); +const { addSignLog } = require('../util/logging-helpers'); + +router.post('/AWS_rekognition', (req, res) => { + const { base64bytes } = req.body; + // const base64bytes = getBase64Image(faceImage); + // detectFace(faceImage) + detectFace(base64bytes) + .then((response) => { + return res.status(OK).send({ ...response }); + }) + .catch((error) => { + return res.status(BAD_REQUEST).send({ ...error }); + }); +}); + +// function getBase64Image(img) { +// let canvas = document.createElement('canvas'); +// canvas.width = img.width; +// canvas.height = img.height; +// let ctx = canvas.getContext('2d'); +// ctx.drawImage(img, 0, 0); + +// let dataURL = canvas.toDataURL('image/png'); + +// return dataURL.replace(/^data:image\/(png|jpg);base64,/, ''); +// } + +module.exports = router; diff --git a/client/api/SceRpcApiServer.js b/client/api/SceRpcApiServer.js index d714219..378bd20 100644 --- a/client/api/SceRpcApiServer.js +++ b/client/api/SceRpcApiServer.js @@ -29,14 +29,14 @@ class SceRpcApiServer { bodyParser.json({ // support JSON-encoded request bodies limit: '50mb', - strict: true + strict: true, }) ); this.app.use( bodyParser.urlencoded({ // support URL-encoded request bodies limit: '50mb', - extended: true + extended: true, }) ); } @@ -64,7 +64,7 @@ class SceRpcApiServer { openConnection() { this.server = http.createServer(this.app); const { port } = this; - this.server.listen(port, function() { + this.server.listen(port, function () { console.debug(`Now listening on port ${port}`); }); } @@ -93,10 +93,10 @@ if (typeof module !== 'undefined' && !module.parent) { const apiRoutes = [ __dirname + '/2DPrinting.js', __dirname + '/3DPrinting.js', - __dirname + '/LedSign.js' + __dirname + '/LedSign.js', + __dirname + '/AWSRekognition.js', ]; - const server = new SceRpcApiServer( - apiRoutes, 8083, '/SceRpcApi/'); + const server = new SceRpcApiServer(apiRoutes, 8083, '/SceRpcApi/'); server.initializeEndpoints().then(() => { server.openConnection(); }); diff --git a/client/aws_rekognition/aws_rekognition_client.js b/client/aws_rekognition/aws_rekognition_client.js new file mode 100644 index 0000000..028b3f0 --- /dev/null +++ b/client/aws_rekognition/aws_rekognition_client.js @@ -0,0 +1,24 @@ +const grpc = require('grpc'); +const messages = require('./aws_rekognition_pb'); +const services = require('./aws_rekognition_grpc_pb'); + +function detectFace(faceImageBytes) { + const client = new services.FaceImageClient( + 'localhost:50051', + grpc.credentials.createInsecure() + ); + + const faceCoordinateRequest = new messages.FaceCoordinateRequest(); + faceCoordinateRequest.setFaceimage(faceImageBytes); + return new Promise((resolve, reject) => { + client.requestFaceCoordinate(faceCoordinateRequest, (err, response) => { + if (err || !response) { + reject({ message: err, error: true }); + } else { + resolve({ message: response, error: false }); + } + }); + }); +} + +module.exports = { detectFace }; diff --git a/client/aws_rekognition/aws_rekognition_grpc_pb.js b/client/aws_rekognition/aws_rekognition_grpc_pb.js new file mode 100644 index 0000000..ffc3a86 --- /dev/null +++ b/client/aws_rekognition/aws_rekognition_grpc_pb.js @@ -0,0 +1,44 @@ +// GENERATED CODE -- DO NOT EDIT! + +'use strict'; +var grpc = require('grpc'); +var aws_rekognition_pb = require('./aws_rekognition_pb.js'); + +function serialize_FaceCoordinateRequest(arg) { + if (!(arg instanceof aws_rekognition_pb.FaceCoordinateRequest)) { + throw new Error('Expected argument of type FaceCoordinateRequest'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_FaceCoordinateRequest(buffer_arg) { + return aws_rekognition_pb.FaceCoordinateRequest.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_FaceCoordinateResponse(arg) { + if (!(arg instanceof aws_rekognition_pb.FaceCoordinateResponse)) { + throw new Error('Expected argument of type FaceCoordinateResponse'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_FaceCoordinateResponse(buffer_arg) { + return aws_rekognition_pb.FaceCoordinateResponse.deserializeBinary(new Uint8Array(buffer_arg)); +} + + +var FaceImageService = exports.FaceImageService = { + requestFaceCoordinate: { + path: '/FaceImage/RequestFaceCoordinate', + requestStream: false, + responseStream: false, + requestType: aws_rekognition_pb.FaceCoordinateRequest, + responseType: aws_rekognition_pb.FaceCoordinateResponse, + requestSerialize: serialize_FaceCoordinateRequest, + requestDeserialize: deserialize_FaceCoordinateRequest, + responseSerialize: serialize_FaceCoordinateResponse, + responseDeserialize: deserialize_FaceCoordinateResponse, + }, +}; + +exports.FaceImageClient = grpc.makeGenericClientConstructor(FaceImageService); diff --git a/client/aws_rekognition/aws_rekognition_pb.js b/client/aws_rekognition/aws_rekognition_pb.js new file mode 100644 index 0000000..796d652 --- /dev/null +++ b/client/aws_rekognition/aws_rekognition_pb.js @@ -0,0 +1,655 @@ +/** + * @fileoverview + * @enhanceable + * @suppress {messageConventions} JS Compiler reports an error if a variable or + * field starts with 'MSG_' and isn't a translatable message. + * @public + */ +// GENERATED CODE -- DO NOT EDIT! + +var jspb = require('google-protobuf'); +var goog = jspb; +var global = Function('return this')(); + +goog.exportSymbol('proto.FaceCoordinateRequest', null, global); +goog.exportSymbol('proto.FaceCoordinateResponse', null, global); +goog.exportSymbol('proto.FaceCoordinateResponse.Face', null, global); + +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.FaceCoordinateRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.FaceCoordinateRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + proto.FaceCoordinateRequest.displayName = 'proto.FaceCoordinateRequest'; +} + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto suitable for use in Soy templates. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. + * @param {boolean=} opt_includeInstance Whether to include the JSPB instance + * for transitional soy proto support: http://goto/soy-param-migration + * @return {!Object} + */ +proto.FaceCoordinateRequest.prototype.toObject = function(opt_includeInstance) { + return proto.FaceCoordinateRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Whether to include the JSPB + * instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.FaceCoordinateRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.FaceCoordinateRequest.toObject = function(includeInstance, msg) { + var f, obj = { + faceimage: msg.getFaceimage_asB64() + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.FaceCoordinateRequest} + */ +proto.FaceCoordinateRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.FaceCoordinateRequest; + return proto.FaceCoordinateRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.FaceCoordinateRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.FaceCoordinateRequest} + */ +proto.FaceCoordinateRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setFaceimage(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.FaceCoordinateRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.FaceCoordinateRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.FaceCoordinateRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.FaceCoordinateRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getFaceimage_asU8(); + if (f.length > 0) { + writer.writeBytes( + 1, + f + ); + } +}; + + +/** + * optional bytes faceImage = 1; + * @return {!(string|Uint8Array)} + */ +proto.FaceCoordinateRequest.prototype.getFaceimage = function() { + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * optional bytes faceImage = 1; + * This is a type-conversion wrapper around `getFaceimage()` + * @return {string} + */ +proto.FaceCoordinateRequest.prototype.getFaceimage_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getFaceimage())); +}; + + +/** + * optional bytes faceImage = 1; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getFaceimage()` + * @return {!Uint8Array} + */ +proto.FaceCoordinateRequest.prototype.getFaceimage_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getFaceimage())); +}; + + +/** @param {!(string|Uint8Array)} value */ +proto.FaceCoordinateRequest.prototype.setFaceimage = function(value) { + jspb.Message.setProto3BytesField(this, 1, value); +}; + + + +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.FaceCoordinateResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.FaceCoordinateResponse.repeatedFields_, null); +}; +goog.inherits(proto.FaceCoordinateResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + proto.FaceCoordinateResponse.displayName = 'proto.FaceCoordinateResponse'; +} +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.FaceCoordinateResponse.repeatedFields_ = [1]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto suitable for use in Soy templates. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. + * @param {boolean=} opt_includeInstance Whether to include the JSPB instance + * for transitional soy proto support: http://goto/soy-param-migration + * @return {!Object} + */ +proto.FaceCoordinateResponse.prototype.toObject = function(opt_includeInstance) { + return proto.FaceCoordinateResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Whether to include the JSPB + * instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.FaceCoordinateResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.FaceCoordinateResponse.toObject = function(includeInstance, msg) { + var f, obj = { + facesList: jspb.Message.toObjectList(msg.getFacesList(), + proto.FaceCoordinateResponse.Face.toObject, includeInstance), + width: +jspb.Message.getFieldWithDefault(msg, 2, 0.0), + height: +jspb.Message.getFieldWithDefault(msg, 3, 0.0) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.FaceCoordinateResponse} + */ +proto.FaceCoordinateResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.FaceCoordinateResponse; + return proto.FaceCoordinateResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.FaceCoordinateResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.FaceCoordinateResponse} + */ +proto.FaceCoordinateResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.FaceCoordinateResponse.Face; + reader.readMessage(value,proto.FaceCoordinateResponse.Face.deserializeBinaryFromReader); + msg.addFaces(value); + break; + case 2: + var value = /** @type {number} */ (reader.readDouble()); + msg.setWidth(value); + break; + case 3: + var value = /** @type {number} */ (reader.readDouble()); + msg.setHeight(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.FaceCoordinateResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.FaceCoordinateResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.FaceCoordinateResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.FaceCoordinateResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getFacesList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 1, + f, + proto.FaceCoordinateResponse.Face.serializeBinaryToWriter + ); + } + f = message.getWidth(); + if (f !== 0.0) { + writer.writeDouble( + 2, + f + ); + } + f = message.getHeight(); + if (f !== 0.0) { + writer.writeDouble( + 3, + f + ); + } +}; + + + +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.FaceCoordinateResponse.Face = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.FaceCoordinateResponse.Face, jspb.Message); +if (goog.DEBUG && !COMPILED) { + proto.FaceCoordinateResponse.Face.displayName = 'proto.FaceCoordinateResponse.Face'; +} + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto suitable for use in Soy templates. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. + * @param {boolean=} opt_includeInstance Whether to include the JSPB instance + * for transitional soy proto support: http://goto/soy-param-migration + * @return {!Object} + */ +proto.FaceCoordinateResponse.Face.prototype.toObject = function(opt_includeInstance) { + return proto.FaceCoordinateResponse.Face.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Whether to include the JSPB + * instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.FaceCoordinateResponse.Face} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.FaceCoordinateResponse.Face.toObject = function(includeInstance, msg) { + var f, obj = { + name: jspb.Message.getFieldWithDefault(msg, 1, ""), + tlx: +jspb.Message.getFieldWithDefault(msg, 2, 0.0), + tly: +jspb.Message.getFieldWithDefault(msg, 3, 0.0), + brx: +jspb.Message.getFieldWithDefault(msg, 4, 0.0), + bry: +jspb.Message.getFieldWithDefault(msg, 5, 0.0) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.FaceCoordinateResponse.Face} + */ +proto.FaceCoordinateResponse.Face.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.FaceCoordinateResponse.Face; + return proto.FaceCoordinateResponse.Face.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.FaceCoordinateResponse.Face} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.FaceCoordinateResponse.Face} + */ +proto.FaceCoordinateResponse.Face.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setName(value); + break; + case 2: + var value = /** @type {number} */ (reader.readDouble()); + msg.setTlx(value); + break; + case 3: + var value = /** @type {number} */ (reader.readDouble()); + msg.setTly(value); + break; + case 4: + var value = /** @type {number} */ (reader.readDouble()); + msg.setBrx(value); + break; + case 5: + var value = /** @type {number} */ (reader.readDouble()); + msg.setBry(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.FaceCoordinateResponse.Face.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.FaceCoordinateResponse.Face.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.FaceCoordinateResponse.Face} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.FaceCoordinateResponse.Face.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getName(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getTlx(); + if (f !== 0.0) { + writer.writeDouble( + 2, + f + ); + } + f = message.getTly(); + if (f !== 0.0) { + writer.writeDouble( + 3, + f + ); + } + f = message.getBrx(); + if (f !== 0.0) { + writer.writeDouble( + 4, + f + ); + } + f = message.getBry(); + if (f !== 0.0) { + writer.writeDouble( + 5, + f + ); + } +}; + + +/** + * optional string name = 1; + * @return {string} + */ +proto.FaceCoordinateResponse.Face.prototype.getName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** @param {string} value */ +proto.FaceCoordinateResponse.Face.prototype.setName = function(value) { + jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional double tlx = 2; + * @return {number} + */ +proto.FaceCoordinateResponse.Face.prototype.getTlx = function() { + return /** @type {number} */ (+jspb.Message.getFieldWithDefault(this, 2, 0.0)); +}; + + +/** @param {number} value */ +proto.FaceCoordinateResponse.Face.prototype.setTlx = function(value) { + jspb.Message.setProto3FloatField(this, 2, value); +}; + + +/** + * optional double tly = 3; + * @return {number} + */ +proto.FaceCoordinateResponse.Face.prototype.getTly = function() { + return /** @type {number} */ (+jspb.Message.getFieldWithDefault(this, 3, 0.0)); +}; + + +/** @param {number} value */ +proto.FaceCoordinateResponse.Face.prototype.setTly = function(value) { + jspb.Message.setProto3FloatField(this, 3, value); +}; + + +/** + * optional double brx = 4; + * @return {number} + */ +proto.FaceCoordinateResponse.Face.prototype.getBrx = function() { + return /** @type {number} */ (+jspb.Message.getFieldWithDefault(this, 4, 0.0)); +}; + + +/** @param {number} value */ +proto.FaceCoordinateResponse.Face.prototype.setBrx = function(value) { + jspb.Message.setProto3FloatField(this, 4, value); +}; + + +/** + * optional double bry = 5; + * @return {number} + */ +proto.FaceCoordinateResponse.Face.prototype.getBry = function() { + return /** @type {number} */ (+jspb.Message.getFieldWithDefault(this, 5, 0.0)); +}; + + +/** @param {number} value */ +proto.FaceCoordinateResponse.Face.prototype.setBry = function(value) { + jspb.Message.setProto3FloatField(this, 5, value); +}; + + +/** + * repeated Face faces = 1; + * @return {!Array} + */ +proto.FaceCoordinateResponse.prototype.getFacesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.FaceCoordinateResponse.Face, 1)); +}; + + +/** @param {!Array} value */ +proto.FaceCoordinateResponse.prototype.setFacesList = function(value) { + jspb.Message.setRepeatedWrapperField(this, 1, value); +}; + + +/** + * @param {!proto.FaceCoordinateResponse.Face=} opt_value + * @param {number=} opt_index + * @return {!proto.FaceCoordinateResponse.Face} + */ +proto.FaceCoordinateResponse.prototype.addFaces = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.FaceCoordinateResponse.Face, opt_index); +}; + + +proto.FaceCoordinateResponse.prototype.clearFacesList = function() { + this.setFacesList([]); +}; + + +/** + * optional double width = 2; + * @return {number} + */ +proto.FaceCoordinateResponse.prototype.getWidth = function() { + return /** @type {number} */ (+jspb.Message.getFieldWithDefault(this, 2, 0.0)); +}; + + +/** @param {number} value */ +proto.FaceCoordinateResponse.prototype.setWidth = function(value) { + jspb.Message.setProto3FloatField(this, 2, value); +}; + + +/** + * optional double height = 3; + * @return {number} + */ +proto.FaceCoordinateResponse.prototype.getHeight = function() { + return /** @type {number} */ (+jspb.Message.getFieldWithDefault(this, 3, 0.0)); +}; + + +/** @param {number} value */ +proto.FaceCoordinateResponse.prototype.setHeight = function(value) { + jspb.Message.setProto3FloatField(this, 3, value); +}; + + +goog.object.extend(exports, proto); diff --git a/client/config/config.example.json b/client/config/config.example.json new file mode 100644 index 0000000..79a2688 --- /dev/null +++ b/client/config/config.example.json @@ -0,0 +1,8 @@ +{ + "AWSRekognition": { + "AWSACCESSKEYID": "XXXXXXXXXXXXXXXX", + "AWSSECRETKEY": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "BUCKET": "officer-faces", + "REGION": "us-west-1" + } +} diff --git a/package-lock.json b/package-lock.json index 74d6d74..ea1bc24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -167,9 +167,9 @@ } }, "@types/bytebuffer": { - "version": "5.0.41", - "resolved": "https://registry.npmjs.org/@types/bytebuffer/-/bytebuffer-5.0.41.tgz", - "integrity": "sha512-Mdrv4YcaHvpkx25ksqqFaezktx3yZRcd51GZY0rY/9avyaqZdiT/GiWRhfrJhMpgzXqTOSHgGvsumGxJFNiZZA==", + "version": "5.0.42", + "resolved": "https://registry.npmjs.org/@types/bytebuffer/-/bytebuffer-5.0.42.tgz", + "integrity": "sha512-lEgKojWUAc/MG2t649oZS5AfYFP2xRNPoDuwDBlBMjHXd8MaGPgFgtCXUK7inZdBOygmVf10qxc1Us8GXC96aw==", "requires": { "@types/long": "*", "@types/node": "*" @@ -384,6 +384,19 @@ "optjs": "~3.2.2" } }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -399,8 +412,17 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, "axios": { "version": "0.19.2", @@ -415,12 +437,39 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "big-integer": { + "version": "1.6.48", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", + "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==" + }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, "binary-extensions": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", "dev": true }, + "bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=" + }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -568,6 +617,16 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "buffer-indexof-polyfill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==" + }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" + }, "bytebuffer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", @@ -631,6 +690,11 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, "chai": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", @@ -660,6 +724,14 @@ "superagent": "^3.7.0" } }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "requires": { + "traverse": ">=0.3.0 <0.4" + } + }, "chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -782,6 +854,16 @@ "wrap-ansi": "^2.0.0" } }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" + }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -791,6 +873,21 @@ "mimic-response": "^1.0.0" } }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" + }, + "cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -820,7 +917,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -915,6 +1011,14 @@ "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -975,8 +1079,7 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "delegates": { "version": "1.0.0", @@ -1022,12 +1125,29 @@ "is-obj": "^2.0.0" } }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "requires": { + "readable-stream": "^2.0.2" + } + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -1313,8 +1433,7 @@ "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "external-editor": { "version": "3.1.0", @@ -1327,17 +1446,20 @@ "tmp": "^0.0.33" } }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "fast-levenshtein": { "version": "2.0.6", @@ -1450,6 +1572,11 @@ } } }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, "form-data": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", @@ -1497,6 +1624,17 @@ "dev": true, "optional": true }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -1545,6 +1683,14 @@ "pump": "^3.0.0" } }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -1586,9 +1732,9 @@ } }, "google-protobuf": { - "version": "3.12.4", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.12.4.tgz", - "integrity": "sha512-ItTn8YepDQMHEMHloUPH+FDaTPiHTnbsMvP50aXfbI65IK3AA5+wXlHSygJH8xz+h1g4gu7V+CK5X1/SaGITsA==" + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.13.0.tgz", + "integrity": "sha512-ZIf3qfLFayVrPvAjeKKxO5FRF1/NwRxt6Dko+fWEMuHwHbZx8/fcaAao9b0wCM6kr8qeg2te8XTpyuvKuD9aKw==" }, "got": { "version": "9.6.0", @@ -1612,8 +1758,7 @@ "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" }, "growl": { "version": "1.10.5", @@ -1647,6 +1792,33 @@ } } }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + } + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -1708,6 +1880,16 @@ "toidentifier": "1.0.0" } }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -2021,8 +2203,7 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "is-yarn-global": { "version": "0.3.0", @@ -2041,6 +2222,11 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2057,17 +2243,26 @@ "esprima": "^4.0.0" } }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", "dev": true }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -2075,6 +2270,22 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, "just-extend": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.0.tgz", @@ -2117,6 +2328,11 @@ "type-check": "~0.4.0" } }, + "listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=" + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -2469,9 +2685,9 @@ "dev": true }, "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" }, "natural-compare": { "version": "1.4.0", @@ -2480,9 +2696,9 @@ "dev": true }, "needle": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.0.tgz", - "integrity": "sha512-o/qITSDR0JCyCKEQ1/1bnUXMmznxabbwi/Y4WwJElf+evwJNFNwIDMCCt5IigFVxgeGBJESLohGtIS9gEzo1fA==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", + "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", "requires": { "debug": "^3.2.6", "iconv-lite": "^0.4.4", @@ -2566,6 +2782,11 @@ "tar": "^4.4.2" } }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=" + }, "nodemon": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.4.tgz", @@ -2661,6 +2882,11 @@ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2863,6 +3089,11 @@ "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", "dev": true }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", @@ -2912,6 +3143,30 @@ "long": "^4.0.0" } }, + "protoc": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/protoc/-/protoc-1.0.4.tgz", + "integrity": "sha512-2crtOP6xhacdWBW+lkhQJmzwg2cPmqSsh51FOHQmgTd8dKksO9sFzlhzteh6x+qPTfPU7h6smC1eg5d9bqGpTQ==", + "requires": { + "glob": "^7.1.6", + "mkdirp": "^0.5.1", + "node-uuid": "^1.4.8", + "request": "^2.88.0", + "rimraf": "^3.0.0", + "unzipper": "^0.10.5", + "vinyl": "^2.2.0" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + } + } + }, "proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -2921,6 +3176,11 @@ "ipaddr.js": "1.9.1" } }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, "pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", @@ -2940,8 +3200,7 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "pupa": { "version": "2.0.1", @@ -3031,6 +3290,65 @@ "rc": "^1.2.8" } }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==" + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3171,6 +3489,11 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, "setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", @@ -3259,6 +3582,22 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -3514,12 +3853,39 @@ } } }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=" + }, "tslib": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", "dev": true }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -3582,6 +3948,23 @@ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, + "unzipper": { + "version": "0.10.11", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", + "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", + "requires": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + } + }, "update-notifier": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.0.tgz", @@ -3659,7 +4042,6 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, "requires": { "punycode": "^2.1.0" } @@ -3694,6 +4076,29 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 4716187..36b961d 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,10 @@ "axios": "^0.19.2", "cors": "^2.8.5", "express": "^4.17.1", - "google-protobuf": "^3.12.4", + "google-protobuf": "^3.13.0", "grpc": "^1.24.3", - "http": "0.0.1-security" + "http": "0.0.1-security", + "protoc": "^1.0.4" }, "devDependencies": { "chai": "^4.2.0", diff --git a/proto/aws_rekognition.proto b/proto/aws_rekognition.proto new file mode 100644 index 0000000..8498d45 --- /dev/null +++ b/proto/aws_rekognition.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; + +service FaceImage { + rpc RequestFaceCoordinate (FaceCoordinateRequest) returns (FaceCoordinateResponse); +} + +message FaceCoordinateRequest { + bytes faceImage = 1; +} + +message FaceCoordinateResponse { + message Face { + string name = 1; + double tlx = 2; + double tly = 3; + double brx = 4; + double bry = 5; + } + + repeated Face faces = 1; + double width = 2; + double height = 3; +} \ No newline at end of file diff --git a/server/aws_rekognition/aws_rekognition_pb2.py b/server/aws_rekognition/aws_rekognition_pb2.py new file mode 100644 index 0000000..c99e65a --- /dev/null +++ b/server/aws_rekognition/aws_rekognition_pb2.py @@ -0,0 +1,219 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: aws_rekognition.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='aws_rekognition.proto', + package='', + syntax='proto3', + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x15\x61ws_rekognition.proto\"*\n\x15\x46\x61\x63\x65\x43oordinateRequest\x12\x11\n\tfaceImage\x18\x01 \x01(\x0c\"\xae\x01\n\x16\x46\x61\x63\x65\x43oordinateResponse\x12+\n\x05\x66\x61\x63\x65s\x18\x01 \x03(\x0b\x32\x1c.FaceCoordinateResponse.Face\x12\r\n\x05width\x18\x02 \x01(\x01\x12\x0e\n\x06height\x18\x03 \x01(\x01\x1aH\n\x04\x46\x61\x63\x65\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0b\n\x03tlx\x18\x02 \x01(\x01\x12\x0b\n\x03tly\x18\x03 \x01(\x01\x12\x0b\n\x03\x62rx\x18\x04 \x01(\x01\x12\x0b\n\x03\x62ry\x18\x05 \x01(\x01\x32U\n\tFaceImage\x12H\n\x15RequestFaceCoordinate\x12\x16.FaceCoordinateRequest\x1a\x17.FaceCoordinateResponseb\x06proto3' +) + + + + +_FACECOORDINATEREQUEST = _descriptor.Descriptor( + name='FaceCoordinateRequest', + full_name='FaceCoordinateRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='faceImage', full_name='FaceCoordinateRequest.faceImage', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=25, + serialized_end=67, +) + + +_FACECOORDINATERESPONSE_FACE = _descriptor.Descriptor( + name='Face', + full_name='FaceCoordinateResponse.Face', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='FaceCoordinateResponse.Face.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='tlx', full_name='FaceCoordinateResponse.Face.tlx', index=1, + number=2, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='tly', full_name='FaceCoordinateResponse.Face.tly', index=2, + number=3, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='brx', full_name='FaceCoordinateResponse.Face.brx', index=3, + number=4, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='bry', full_name='FaceCoordinateResponse.Face.bry', index=4, + number=5, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=172, + serialized_end=244, +) + +_FACECOORDINATERESPONSE = _descriptor.Descriptor( + name='FaceCoordinateResponse', + full_name='FaceCoordinateResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='faces', full_name='FaceCoordinateResponse.faces', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='width', full_name='FaceCoordinateResponse.width', index=1, + number=2, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='height', full_name='FaceCoordinateResponse.height', index=2, + number=3, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_FACECOORDINATERESPONSE_FACE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=70, + serialized_end=244, +) + +_FACECOORDINATERESPONSE_FACE.containing_type = _FACECOORDINATERESPONSE +_FACECOORDINATERESPONSE.fields_by_name['faces'].message_type = _FACECOORDINATERESPONSE_FACE +DESCRIPTOR.message_types_by_name['FaceCoordinateRequest'] = _FACECOORDINATEREQUEST +DESCRIPTOR.message_types_by_name['FaceCoordinateResponse'] = _FACECOORDINATERESPONSE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +FaceCoordinateRequest = _reflection.GeneratedProtocolMessageType('FaceCoordinateRequest', (_message.Message,), { + 'DESCRIPTOR' : _FACECOORDINATEREQUEST, + '__module__' : 'aws_rekognition_pb2' + # @@protoc_insertion_point(class_scope:FaceCoordinateRequest) + }) +_sym_db.RegisterMessage(FaceCoordinateRequest) + +FaceCoordinateResponse = _reflection.GeneratedProtocolMessageType('FaceCoordinateResponse', (_message.Message,), { + + 'Face' : _reflection.GeneratedProtocolMessageType('Face', (_message.Message,), { + 'DESCRIPTOR' : _FACECOORDINATERESPONSE_FACE, + '__module__' : 'aws_rekognition_pb2' + # @@protoc_insertion_point(class_scope:FaceCoordinateResponse.Face) + }) + , + 'DESCRIPTOR' : _FACECOORDINATERESPONSE, + '__module__' : 'aws_rekognition_pb2' + # @@protoc_insertion_point(class_scope:FaceCoordinateResponse) + }) +_sym_db.RegisterMessage(FaceCoordinateResponse) +_sym_db.RegisterMessage(FaceCoordinateResponse.Face) + + + +_FACEIMAGE = _descriptor.ServiceDescriptor( + name='FaceImage', + full_name='FaceImage', + file=DESCRIPTOR, + index=0, + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_start=246, + serialized_end=331, + methods=[ + _descriptor.MethodDescriptor( + name='RequestFaceCoordinate', + full_name='FaceImage.RequestFaceCoordinate', + index=0, + containing_service=None, + input_type=_FACECOORDINATEREQUEST, + output_type=_FACECOORDINATERESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), +]) +_sym_db.RegisterServiceDescriptor(_FACEIMAGE) + +DESCRIPTOR.services_by_name['FaceImage'] = _FACEIMAGE + +# @@protoc_insertion_point(module_scope) diff --git a/server/aws_rekognition/aws_rekognition_pb2_grpc.py b/server/aws_rekognition/aws_rekognition_pb2_grpc.py new file mode 100644 index 0000000..0beee42 --- /dev/null +++ b/server/aws_rekognition/aws_rekognition_pb2_grpc.py @@ -0,0 +1,66 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + +import aws_rekognition_pb2 as aws__rekognition__pb2 + + +class FaceImageStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.RequestFaceCoordinate = channel.unary_unary( + '/FaceImage/RequestFaceCoordinate', + request_serializer=aws__rekognition__pb2.FaceCoordinateRequest.SerializeToString, + response_deserializer=aws__rekognition__pb2.FaceCoordinateResponse.FromString, + ) + + +class FaceImageServicer(object): + """Missing associated documentation comment in .proto file.""" + + def RequestFaceCoordinate(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_FaceImageServicer_to_server(servicer, server): + rpc_method_handlers = { + 'RequestFaceCoordinate': grpc.unary_unary_rpc_method_handler( + servicer.RequestFaceCoordinate, + request_deserializer=aws__rekognition__pb2.FaceCoordinateRequest.FromString, + response_serializer=aws__rekognition__pb2.FaceCoordinateResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'FaceImage', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + + + # This class is part of an EXPERIMENTAL API. +class FaceImage(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def RequestFaceCoordinate(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/FaceImage/RequestFaceCoordinate', + aws__rekognition__pb2.FaceCoordinateRequest.SerializeToString, + aws__rekognition__pb2.FaceCoordinateResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/server/aws_rekognition/aws_rekognition_server.py b/server/aws_rekognition/aws_rekognition_server.py new file mode 100644 index 0000000..eee8ef8 --- /dev/null +++ b/server/aws_rekognition/aws_rekognition_server.py @@ -0,0 +1,153 @@ +import grpc +import concurrent +from concurrent import futures + +import aws_rekognition_pb2 +import aws_rekognition_pb2_grpc + +import boto3 +# from PIL import Image, ImageDraw, ImageFont +from PIL import Image +from io import BytesIO + +import json + +class FaceImageServicer(aws_rekognition_pb2_grpc.FaceImageServicer): + def RequestFaceCoordinate(self, request, context): + print('we got something') + response = aws_rekognition_pb2.FaceCoordinateResponse() + stream = BytesIO(request.faceImage) + image = Image.open(stream).convert("RGBA") + stream.close() + + imagesize = [image.size[0],image.size[1]] + + print("Reading configs") + + with open("../../client/config/config.json") as f: + AWSKEY = json.load(f)['AWSRekognition'] + + print("Loaded configs") + + bucket = AWSKEY['BUCKET'] + region = AWSKEY['REGION'] + accessid = AWSKEY['AWSACCESSKEYID'] + secretkey = AWSKEY['AWSSECRETKEY'] + + print("Creating clients") + + s3Client = boto3.client( + "s3", + aws_access_key_id=accessid, + aws_secret_access_key=secretkey, + region_name=region + ) + rekognitionClient = boto3.client( + "rekognition", + aws_access_key_id=accessid, + aws_secret_access_key=secretkey, + region_name=region + ) + + print("Going to do stuff with client") + imgnames = get_image_names(s3Client, bucket) + print(imgnames) + faces = get_face_coordinates(rekognitionClient, request.faceImage, imgnames, bucket, region) + print(faces) + for facename, faceBB in faces: + face = response.faces.add() + [face.name, face.tlx, face.tly, face.brx, face.bry] = get_bounding_box(facename, faceBB, imagesize) + response.width = image.size[0] + response.height = image.size[1] + print("sending back") + return response + + +def get_image_names(client, bucket): + # print("In image names") + response = client.list_objects_v2( + Bucket=bucket + ) + # print(response) + contents = response['Contents'] + imgnames = [obj["Key"] for obj in contents] + return imgnames + + +def get_bounding_box(name, bb, iz): + lx = round(bb["Left"] * iz[0]) + ly = round(bb["Top"] * iz[1]) + rx = round((bb["Left"] + bb["Width"]) * iz[0]) + ry = round((bb["Top"] + bb["Height"]) * iz[1]) + return [name,lx,ly,rx,ry] + + +def get_face_coordinates(client, target, source, bucket, region): + cid = "faces" + client.create_collection( + CollectionId=cid + ) + client.index_faces( + CollectionId=cid, + Image={'Bytes': target} + ) + + faces = [] + + for i in range(len(source)): + facename = source[i] + print("\nChecking " + str(i+1) + " / " + str(len(source)) + " : " + facename) + print("\twaiting response") + response = client.search_faces_by_image( + CollectionId=cid, + Image={'S3Object':{'Bucket':bucket,'Name':facename}}, + FaceMatchThreshold=90 + ) + print("got response") + + if len(response["FaceMatches"]) == 0: + print("\tNot In Picture") + continue + + matchface = max(response['FaceMatches'], key=lambda x: x['Similarity']) + bb = matchface['Face']['BoundingBox'] + + faces.append([facename,bb]) + + if matchface: + client.delete_faces( + CollectionId=cid, + FaceIds=[matchface['Face']['FaceId']] + ) + + client.delete_collection( + CollectionId=cid + ) + + return faces + + +def main(): + # with open("../../client/config/config.json") as f: + # AWSKEY = json.load(f)['AWSRekognition'] + # bucket = AWSKEY['BUCKET'] + # region = AWSKEY['REGION'] + # accessid = AWSKEY['AWSACCESSKEYID'] + # secretkey = AWSKEY['AWSSECRETKEY'] + # s3Client = boto3.client( + # "s3", + # aws_access_key_id=accessid, + # aws_secret_access_key=secretkey, + # region_name=region + # ) + # get_image_names(s3Client, bucket) + + + server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + aws_rekognition_pb2_grpc.add_FaceImageServicer_to_server(FaceImageServicer(), server) + print("server started") + server.add_insecure_port('[::]:50051') + server.start() + server.wait_for_termination() + +main() \ No newline at end of file