From ef0897b15a8294c56735ee89fa0b438c81969839 Mon Sep 17 00:00:00 2001 From: Nikita Evdokimov <9944368+evdokimovn@users.noreply.github.com> Date: Mon, 30 Aug 2021 16:17:11 +0200 Subject: [PATCH] Control use of Rekognition via env variable --- source/constructs/lib/constructs-stack.ts | 9 ++- .../lib/serverless-image-handler.ts | 4 +- .../test/serverless-image-handler-test.json | 12 ++++ source/image-handler/image-handler.js | 66 ++++++++++--------- 4 files changed, 59 insertions(+), 32 deletions(-) diff --git a/source/constructs/lib/constructs-stack.ts b/source/constructs/lib/constructs-stack.ts index 544db62f7..515e3a698 100644 --- a/source/constructs/lib/constructs-stack.ts +++ b/source/constructs/lib/constructs-stack.ts @@ -82,6 +82,12 @@ export class ConstructsStack extends cdk.Stack { description: 'The name of the default fallback image object key including prefix. e.g. prefix/image.jpg', default: '' }); + const enableSmartCropRekognition = new CfnParameter(this, 'EnableSmartCropRekognition', { + type: 'String', + description: 'Use Rekognition as an object detection engine when smart cropping', + default: 'No', + allowedValues: ['Yes', 'No'] + }); // CFN descrption this.templateOptions.description = `(SO0023) - Serverless Image Handler with aws-solutions-constructs: This template deploys and configures a serverless architecture that is optimized for dynamic image manipulation and delivery at low latency and cost. Leverages SharpJS for image processing. Template version ${VERSION}`; @@ -147,7 +153,8 @@ export class ConstructsStack extends cdk.Stack { secretsManagerKeyParameter, enableDefaultFallbackImageParameter, fallbackImageS3BucketParameter, - fallbackImageS3KeyParameter + fallbackImageS3KeyParameter, + enableSmartCropRekognition }; // Serverless Image Handler Construct diff --git a/source/constructs/lib/serverless-image-handler.ts b/source/constructs/lib/serverless-image-handler.ts index 00aaa5ec6..2d6a7beb3 100644 --- a/source/constructs/lib/serverless-image-handler.ts +++ b/source/constructs/lib/serverless-image-handler.ts @@ -32,6 +32,7 @@ export interface ServerlessImageHandlerProps { readonly enableDefaultFallbackImageParameter: CfnParameter; readonly fallbackImageS3BucketParameter: CfnParameter; readonly fallbackImageS3KeyParameter: CfnParameter; + readonly enableSmartCropRekognition: CfnParameter; } /** @@ -181,7 +182,8 @@ export class ServerlessImageHandler extends Construct { SECRET_KEY: props.secretsManagerKeyParameter.valueAsString, ENABLE_DEFAULT_FALLBACK_IMAGE: props.enableDefaultFallbackImageParameter.valueAsString, DEFAULT_FALLBACK_IMAGE_BUCKET: props.fallbackImageS3BucketParameter.valueAsString, - DEFAULT_FALLBACK_IMAGE_KEY: props.fallbackImageS3KeyParameter.valueAsString + DEFAULT_FALLBACK_IMAGE_KEY: props.fallbackImageS3KeyParameter.valueAsString, + ENABLE_SMART_CROP_REKOGNITION: props.enableSmartCropRekognition.valueAsString } }); const cfnImageHandlerFunction = imageHandlerFunction.node.defaultChild as cdkLambda.CfnFunction; diff --git a/source/constructs/test/serverless-image-handler-test.json b/source/constructs/test/serverless-image-handler-test.json index 14a55be15..fc87eb481 100644 --- a/source/constructs/test/serverless-image-handler-test.json +++ b/source/constructs/test/serverless-image-handler-test.json @@ -168,6 +168,15 @@ "Type": "String", "Default": "", "Description": "The name of the default fallback image object key including prefix. e.g. prefix/image.jpg" + }, + "EnableSmartCropRekognition": { + "Type": "String", + "Default": "No", + "AllowedValues": [ + "Yes", + "No" + ], + "Description": "Use Rekognition as an object detection engine when smart cropping" } }, "Mappings": { @@ -449,6 +458,9 @@ }, "DEFAULT_FALLBACK_IMAGE_KEY": { "Ref": "FallbackImageS3Key" + }, + "ENABLE_SMART_CROP_REKOGNITION": { + "Ref": "EnableSmartCropRekognition" } } }, diff --git a/source/image-handler/image-handler.js b/source/image-handler/image-handler.js index b9344f445..b4acbebbb 100644 --- a/source/image-handler/image-handler.js +++ b/source/image-handler/image-handler.js @@ -210,48 +210,54 @@ class ImageHandler { options.height = cropHeight; } options.boost = [] - try { - const [faceRekognitionResult, detectLabelsResult] = await Promise.all([this.rekognition.detectFaces({Image: {Bytes: imageBuffer}}).promise(), this.rekognition.detectLabels({Image: {Bytes: imageBuffer}, MinConfidence: 85}).promise()]); - faceRekognitionResult.FaceDetails.forEach(instance => { - if (instance.BoundingBox) { - options.boost.push({ - x: instance.BoundingBox.Left * width, - y: instance.BoundingBox.Top * height, - width: instance.BoundingBox.Width * width, - height: instance.BoundingBox.Height * height, - weight: 0.6 - }) - } - }) - - for (const l of detectLabelsResult.Labels) {if (l.Name === 'Fish') { - l.Instances.forEach(instance => { + if (process.env.ENABLE_SMART_CROP_REKOGNITION === 'Yes') { + try { + const [faceRekognitionResult, detectLabelsResult] = await Promise.all([this.rekognition.detectFaces({Image: {Bytes: imageBuffer}}).promise(), this.rekognition.detectLabels({ + Image: {Bytes: imageBuffer}, + MinConfidence: 85 + }).promise()]); + faceRekognitionResult.FaceDetails.forEach(instance => { if (instance.BoundingBox) { - console.log(instance) options.boost.push({ x: instance.BoundingBox.Left * width, y: instance.BoundingBox.Top * height, width: instance.BoundingBox.Width * width, height: instance.BoundingBox.Height * height, - weight: 1 + weight: 0.6 }) } }) - }} - var crop = await smartcrop.crop(imageBuffer, {width: options.width, height: options.height, boost: options.boost}) - crop = crop.topCrop; + for (const l of detectLabelsResult.Labels) { + if (l.Name === 'Fish') { + l.Instances.forEach(instance => { + if (instance.BoundingBox) { + console.log(instance) + options.boost.push({ + x: instance.BoundingBox.Left * width, + y: instance.BoundingBox.Top * height, + width: instance.BoundingBox.Width * width, + height: instance.BoundingBox.Height * height, + weight: 1 + }) + } + }) + } + } + } catch (err) { + throw { + status: err.statusCode ? err.statusCode : 500, + code: err.code, + message: err.message + }; + } + } - return await sharp(imageBuffer) - .extract({width: crop.width, height: crop.height, left: crop.x, top: crop.y}).toBuffer(); + var crop = await smartcrop.crop(imageBuffer, {width: options.width, height: options.height, boost: options.boost}) + crop = crop.topCrop; - } catch (err) { - throw { - status: err.statusCode ? err.statusCode : 500, - code: err.code, - message: err.message - }; - } + return await sharp(imageBuffer) + .extract({width: crop.width, height: crop.height, left: crop.x, top: crop.y}).toBuffer(); } /**