How to use AWS Rekognition to Compare Face in Swift 3 - ios

I've been trying to use the AWSRekognition SDK in order to compare face. However, Amazon has no Documentation on how to integrate their SDK with iOS. They have links that show how to work with Recognition (Developer Guide) with examples only in Java and very limited.
I wanted to know if anyone knows how to integrate AWS Rekognition in Swift 3. How to Initialize it and make a request with an image, receiving a response with the labels.
I have AWS Signatures AccessKey, SecretKey, AWS Region, Service Name. also Body
{
"SourceImage": {
"S3Object": {
"Bucket": "bucketName",
"Name": "ios/sample.jpg"
}
},
"TargetImage": {
"S3Object": {
"Bucket": "buketName",
"Name": "ios/target.JPG"
}
}
}
how can I initialize Rekognition and build a Request.
Thanks you!

Instantiate the Rekognition Client, Here I'm using the client with the default configuration.
let rekognitionClient:AWSRekognition = AWSRekognition.default()
Otherwise, you can use the credentials as follows:
let credentialsProvider = AWSCognitoCredentialsProvider(
regionType: AWSRegionType.usEast2,
identityPoolId: "us-east-2_myPoolID")
let configuration = AWSServiceConfiguration(
region: AWSRegionType.usEast2,
credentialsProvider: credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
let rekognitionClient:AWSRekognition = AWSRekognition.default()
Now construct the request and set the image in it.
let image = UIImage(named: "MyImage")
let request = AWSRekognitionDetectLabelsRequest()
request.image = image
request.maxLabels = <num_labels_needed>
request.minConfidence = <confidence_interval_needed>
Now to compare faces, read about the CompareFacesRequest: https://github.com/aws/aws-sdk-ios/blob/master/AWSRekognition/AWSRekognitionService.m#L288
There is a sample test in the SDK that compares two faces in ObjC but you can translate that in Swift:
https://github.com/aws/aws-sdk-ios/blob/master/AWSRekognitionUnitTests/AWSGeneralRekognitionTests.m#L60
let key = "testCompareFaces"
let configuration = AWSServiceConfiguration(region: AWSRegionUSEast2, credentialsProvider: nil)
AWSRekognition.register(with: configuration, forKey: key)
AWSRekognition(for: key).compareFaces(AWSRekognitionCompareFacesRequest()).continue(withBlock: {(_ task: AWSTask) -> Any in
print("completed")

Swift 5.0
let key = "testCompareFaces"
let credentialsProvider = AWSStaticCredentialsProvider(accessKey: "Add_access_key_id", secretKey:"Add_secret_access_key_id")
let configuration = AWSServiceConfiguration(region:.USEast1, credentialsProvider:credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
AWSRekognition.register(with: configuration!, forKey: key)
let rekognition = AWSRekognition(forKey: key)
guard let request = AWSRekognitionCompareFacesRequest() else {
puts("Unable to initialize AWSRekognitionDetectLabelsRequest.")
return
}
let sourceImage = AWSRekognitionImage()
sourceImage!.bytes = sourceImage.jpegData(compressionQuality: 0.4)// Specify your source image
request.sourceImage = sourceImage
let targetImage = AWSRekognitionImage()
targetImage!.bytes = targetImage.jpegData(compressionQuality: 0.4) // Specify your target image
request.targetImage = targetImage
rekognition.compareFaces(request) { (respone, error) in
if error == nil {
if let response = respone {
if let first = response.faceMatches?.first {
print(first)
}
}
} else {
print(error?.localizedDescription)
}
}

Related

Upload image to S3 with Amazon Educate Starter Account

I just want to upload an image to S3, but I am using AWS Educate Account and I'm trying since 4 hours to get this done and have ZERO ideas what isn't working correctly.
So I've set up everything on the AWS console and the bucket is public to EVERYONE + Region US West N.Virginia like it should be with AWS Educate Accounts.
So here is my code:
let accessKey = "accessKey"
let secretKey = "secretKey"
let credentialsProvider = AWSStaticCredentialsProvider(accessKey: accessKey, secretKey: secretKey)
let configuration = AWSServiceConfiguration(region: AWSRegionType.USEast1, credentialsProvider: credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
let transferUtility = AWSS3TransferUtility.default()
let bucketname = "bucketname"
let expression = AWSS3TransferUtilityUploadExpression()
transferUtility.uploadData(jpegData, bucket: bucketname, key: "myTransferUtilityUpload.jpg", contentType: "image/jpg", expression: expression) { (task, error) in
if let error = error {
print(error.localizedDescription)
}
if let response = task.response {
print(response)
}
}
Can anyone tell me what I do wrong?
I get this error message:
The operation couldn’t be completed.
(com.amazonaws.AWSS3TransferUtilityErrorDomain error 2.)
accessKey + secretKey I got from Account Details + AWS CLI on the 'Welcome to AWS Educate Starter Account' Dashboard and obviously the bucket name is the same name like in my console
EDIT:
if let jpegData = image.jpegData(compressionQuality: 0.7) {
let fileManager = FileManager.default
if let documentDirectory = fileManager.urls(for: .documentDirectory,
in: .userDomainMask).first {
var sourceFolderURL = documentDirectory.appendingPathComponent("image.jpg")
do {
try jpegData.write(to: sourceFolderURL)
} catch {
print(error.localizedDescription)
completionHandler(nil)
return
}
let accessKey = "-"
let secretKey = "-"
let bucketname = "-"
let credentialsProvider = AWSStaticCredentialsProvider(accessKey: accessKey, secretKey: secretKey)
let configuration = AWSServiceConfiguration(region: AWSRegionType.USEast1, credentialsProvider: credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
let uploadRequest = AWSS3TransferManagerUploadRequest()!
uploadRequest.body = sourceFolderURL
uploadRequest.key = "image.jpg"
uploadRequest.bucket = bucketname
uploadRequest.contentType = "image/jpeg"
uploadRequest.acl = .publicReadWrite
let transferManager = AWSS3TransferManager.default()
transferManager.upload(uploadRequest).continueWith { [weak self] (task) -> Any? in
if let error = task.error {
print("Upload failed with error: (\(error.localizedDescription))")
completionHandler(nil)
return nil
}
if task.result != nil {
let url = AWSS3.default().configuration.endpoint.url
let publicURL = url?.appendingPathComponent(uploadRequest.bucket!).appendingPathComponent(uploadRequest.key!)
if let absoluteString = publicURL?.absoluteString {
print("Uploaded to:\(absoluteString)")
completionHandler(nil)
}
}
completionHandler(nil)
return nil
}
}
}
I have uploaded an image to S3 bucket with the following code:
First, save the image to a temporary directory.
func uploadImageToS3(imageName:String, completion:#escaping (Bool) -> Void) {
let accessKey = "accessKey"
let secretKey = "secretKey"
let credentialsProvider = AWSStaticCredentialsProvider(accessKey: accessKey, secretKey: secretKey)
let configuration = AWSServiceConfiguration(region:AWSRegionType.APSoutheast2, credentialsProvider:credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
let S3BucketName = "bucketname"
let uploadRequest = AWSS3TransferManagerUploadRequest()!
uploadRequest.body = self.getImageURLWithName(imageName:imageName)
uploadRequest.key = "\(imageName)"
uploadRequest.bucket = S3BucketName
uploadRequest.contentType = "image/jpeg"
//You can specify private or public here
uploadRequest.acl = .private
let transferManager = AWSS3TransferManager.default()
transferManager.upload(uploadRequest).continueWith { [weak self] (task) -> Any? in
ProgressIndicatorHelper.hideGlobalHUD()
if let error = task.error {
print("Upload failed with error: (\(error.localizedDescription))")
completion(false)
}
if task.result != nil {
let url = AWSS3.default().configuration.endpoint.url
let publicURL = url?.appendingPathComponent(uploadRequest.bucket!).appendingPathComponent(uploadRequest.key!)
if let absoluteString = publicURL?.absoluteString {
print("Uploaded to:\(absoluteString)")
completion(true)
}
}
return nil
}
}
For getting image from Path following code I have used:
func getImageURLWithName(imageName:String) -> URL {
var sourceImageURL: URL!
let fileManager = FileManager.default
if let documentDirectory = fileManager.urls(for: .documentDirectory,
in: .userDomainMask).first {
var sourceFolderURL:URL!
sourceFolderURL = documentDirectory.appendingPathComponent("YourTempFolder")
sourceImageURL = sourceFolderURL.appendingPathComponent(imageName)
}
return sourceImageURL
}
Hope this helps.
Moreover: Right now I don't think you can directly upload image from memory.
I searched for it. Following are links for same:
https://github.com/aws-amplify/aws-sdk-ios/issues/42
How to upload a UIImage to S3 with AWS iOS SDK v2
Let me know if you find any error.
Maybe it's a policy issue?
Try attaching this policy to your bucket (bucket policies)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::mybucketname/*"
]
}
]
}

AWS Recognition to Compare Face using IOS Swift

I have an issue with my logic trying to invoke the AWS Recognition Compare Faces api using IOS Swift. There isn't any documentation for Swift yet (as of this posting), but believe I may have the request set up correctly, just not invoking it correctly to receive the response object and confirm the results.
Any advice?
let sourceImage = AWSRekognitionImage()
let sourceImageS3Object = AWSRekognitionS3Object()
sourceImageS3Object?.bucket = "face-badges"
sourceImageS3Object?.name = "me.jpg"
sourceImage?.s3Object = sourceImageS3Object
let targetImage = AWSRekognitionImage()
let targetImageS3Object = AWSRekognitionS3Object()
targetImageS3Object?.bucket = "face-badges"
targetImageS3Object?.name = "me2.jpg"
targetImage?.s3Object = targetImageS3Object
let request = AWSRekognitionCompareFacesRequest()
request?.similarityThreshold = 90
request?.sourceImage = sourceImage
request?.targetImage = targetImage
let key = "testCompareFaces"
let credentialsProvider = AWSCognitoCredentialsProvider(regionType:.USEast1,
identityPoolId:"xxxxx")
let configuration = AWSServiceConfiguration(region:.USEast1, credentialsProvider:credentialsProvider)
AWSRekognition.register(with: configuration!, forKey: key)
AWSRekognition(forKey: key).compareFaces(AWSRekognitionCompareFacesRequest()).continueWith(block: {(_ task: AWSTask) -> Any in
print("completed")
return true;
}).waitUntilFinished()
The following sample test in the SDK demonstrated how to compare two faces in ObjC.
https://github.com/aws/aws-sdk-ios/blob/master/AWSRekognitionUnitTests/AWSGeneralRekognitionTests.m#L60
Corresponding snippet in Swift would look something like :
let key = "testCompareFaces"
let configuration = AWSServiceConfiguration(region: AWSRegionUSEast2, credentialsProvider: nil)
AWSRekognition.register(with: configuration, forKey: key)
AWSRekognition(for: key).compareFaces(AWSRekognitionCompareFacesRequest()).continue(withBlock: {(_ task: AWSTask) -> Any in
print("completed")
Hope that helps!

Error downloading from S3 bucket on IOS.

I'm having a hard time trying to Download a specific file I've uploaded in my S3 Bucket.
I created a bucket called "Photos" and uploaded the file named "test.png"
After setting my CredentialProvider in my AppDelegate I tried to make a download of that file with the following code:
let transferManager = AWSS3TransferManager.defaultS3TransferManager()
let downloadingFilePath = NSTemporaryDirectory().stringByAppendingString("test.png")
let downloadingFileUrl = NSURL(fileURLWithPath: downloadingFilePath)
let downloadRequest = AWSS3TransferManagerDownloadRequest()
downloadRequest.bucket = "photos"
downloadRequest.key = "test.png"
downloadRequest.downloadingFileURL = downloadingFileUrl
transferManager.download(downloadRequest).continueWithExecutor(AWSExecutor.mainThreadExecutor(), withBlock: { (AWSTask) -> AnyObject! in
//Handle errors
if AWSTask.error != nil
{
print("Error downloading: \(AWSTask.error)")
// Retrive information important for later downloading
}
else
{
print("Download succesful..")
var uploadResult: AnyObject! = AWSTask.result
print("Upload result: \(uploadResult)")
let downloadOutput = AWSTask.result as! AWSS3TransferManagerDownloadOutput
}
return nil
})
But it keeps giving me the error: "The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint"
I tried to change my downloaderRequest.bucket to the endpoint I found in my bucket properties . downloaderRequest.bucket = "photos.s3-website-sa-east-1.amazonaws.com"
But now it says "The specified bucket does not exist, Code=NoSuchBucket"
Any ideas of what Ive be doing wrong? thanks.
I finally figure it out.
So the problem here is that I created my bucket in a South American region and Amazon couldn't find it.
Even thought when I click in my Amazon region it tell me that "S3 does not require region selection." You need to create it in the "US Standard".
Before downloading, please set all required information related to access AWS service, Please apply below code first in your app delegate,
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
let credentialsProvider = AWSStaticCredentialsProvider(accessKey: YOUR_AWS_ACCESS_KEY, secretKey: YOUR_AWS_SECRET_KEY)
let defaultServiceConfiguration = AWSServiceConfiguration(region: AWSRegionType.SAEast1, credentialsProvider: credentialsProvider) //Your region endpoint
AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = defaultServiceConfiguration
AWSLogger.defaultLogger().logLevel = .Verbose
return true
}
NOTE: Please do care about bucket name spell with case sensitivity.
func downloadFile()
{
let transferManager = AWSS3TransferManager.defaultS3TransferManager()
let downloadingFilePath = NSTemporaryDirectory().stringByAppendingString("test.png")
let downloadingFileURL = NSURL(fileURLWithPath: downloadingFilePath as String )
let downloadReadRequest : AWSS3TransferManagerDownloadRequest = AWSS3TransferManagerDownloadRequest()
downloadReadRequest.bucket = "photos"
downloadReadRequest.key = "test.png"
downloadReadRequest.downloadingFileURL = downloadingFileURL
let task = transferManager.download(downloadReadRequest)
task.continueWithBlock { (task) -> AnyObject? in
if task.error != nil
{
// Success
}
else
{
// Error
}
return nil
}
}
this problem occur because of region mismatch of s3 bucket and region we use while configuring s3
here is the code :
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: cognitoRegion,
identityPoolId: cognitoIdentityPoolId,
identityProviderManager: customIdentityProvider)
so, here region type must be same your bucket region type. Ex.
if this is your bucket then , your regiontype in code must be : AWSRegionType.APSouth1

Issue Integrating Amazon Simple Email Services API in Swift

I want to use the "verifyEmailIdentity" action which is defined in Objective-C as part of the Amazon Simple Email Service API but I'm having trouble doing so in Swift. I want to call the action in Swift code and have the documentation of the action defined in a pod but I'm not really sure how to go about this.
Here is some sample code but my program doesn't recognize the return type.
func createRequest(verifyEmailIdentityRequest: SESVerifyEmailIdentityRequest) -> AmazonServiceRequest {
var request: AmazonServiceRequest = SESRequest()
request.setParameterValue("VerifyEmailIdentity", forKey: "Action")
request.setParameterValue("2010-12-01", forKey: "Version")
request.delegate = verifyEmailIdentityRequest.delegate
request.credentials = verifyEmailIdentityRequest.credentials()
request.endpoint = verifyEmailIdentityRequest.requestEndpoint()
request.requestTag = verifyEmailIdentityRequest.requestTag()
if verifyEmailIdentityRequest != nil {
if verifyEmailIdentityRequest.emailAddress != nil {
request.setParameterValue("\ (verifyEmailIdentityRequest.emailAddress)", forKey: "\("EmailAddress")")
}
}
return request
}
http://docs.aws.amazon.com/ses/latest/APIReference/API_VerifyEmailIdentity.html
You can achieve that by using the following snippet:
func verifyEmailIdentity(verifyEmailIdentityRequest: AWSSESVerifyEmailIdentityRequest) {
// You should ideally set your configuration in app delegate
// Set the region and cognito pool id
let credentialsProvider = AWSCognitoCredentialsProvider(
regionType: AWSRegionType.Unknown,
identityPoolId: "YOUR_POOL_ID")
let configuration = AWSServiceConfiguration(
region: AWSRegionType.Unknown,
credentialsProvider: credentialsProvider)
AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration
let ses = AWSSES.defaultSES()
ses.verifyEmailIdentity(verifyEmailIdentityRequest).continueWithBlock { (task: AWSTask) -> AnyObject? in
if let error = task.error {
// handle error here
} else if let result = task.result {
// handle result here
}
return nil
}
}
Thanks,
Rohan

Display UIImageView using Swift from AWS

I'm trying to render an image in UIImageView using Swift. The source object is located in an AWS S3 bucket. I could not find any example code on Google. So I tried to translate the code given in this link [AWS S3 SDK v2 for iOS - Download an image file to UIImage from Obj-C to Swift, but failed. I'm a beginner in iOS.
let accessKey = "ACCESS_CODE";
let secretKey = "SECRET_KEY";
// let credentialsProvider = AWSStaticCredentialsProvider.credentialsWithAccessKey(accessKey, secretKey: secretKey)
// ^ Xcode says - credentialsWithAccessKey is deprecated, use initWithAccessKey
let credentialsProvider = AWSStaticCredentialsProvider.initWithAccessKey(accessKey, secretKey: secretKey)
// ^ Xcode says - AWSStaticCredentialsProvider.Type does not have a member named ‘initWithAccessKey’
I could be doing very many things wrong here, even silly mistakes. The best help would be to point to some example code.
Have you tried like this
var credentialsProvider: AWSStaticCredentialsProvider = AWSStaticCredentialsProvider.credentialsWithAccessKey("MY_ACCESS_KEY", secretKey: "MY_SECRET_KEY")
var configuration: AWSServiceConfiguration = AWSServiceConfiguration.configurationWithRegion(AWSRegionUSWest1, credentialsProvider: credentialsProvider)
AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration
var transferManager: AWSS3 = AWSS3(configuration: configuration)
var getImageRequest: AWSS3GetObjectRequest = AWSS3GetObjectRequest.new()
getImageRequest.bucket = "MY_BUCKET"
getImageRequest.key = "MY_KEY"
transferManager.getObject(getImageRequest).continueWithExecutor(BFExecutor.mainThreadExecutor(), withBlock: {(task: BFTask) -> id in if task.error {
NSLog("Error: %#", task.error)
}
else {
NSLog("Got image")
var data: NSData = task.result.body()
dispatch_async(dispatch_get_main_queue(), {
var image: UIImage = UIImage.imageWithData(data)
myImageView.image = image
})
I created a custom class to download image. It worked for me.
class AWSImageDownloader {
init(AccessKey accessKey:String, SecretKey secretKey:String, andRegion region:AWSRegionType = .USEast1) {
let credentialsProvider = AWSStaticCredentialsProvider(accessKey: accessKey, secretKey: secretKey)
guard let configuration = AWSServiceConfiguration(region: region, credentialsProvider: credentialsProvider) else {
debugPrint("Failed to configure")
return
}
AWSServiceManager.default().defaultServiceConfiguration = configuration
}
func downloadImage(Name imageName:String, fromBucket bucketName:String, onDownload successCallback:#escaping AWSImageDownloadSuccess, andOnError errorCallback:#escaping AWSImageDownloadError){
let transferManager = AWSS3.default()
let getImageRequest = AWSS3GetObjectRequest()
getImageRequest?.bucket = bucketName
getImageRequest?.key = imageName
transferManager.getObject(getImageRequest!).continueWith(executor: AWSExecutor.mainThread()) { (anandt) -> Void in
if anandt.error == nil {
if let imageData = anandt.result?.body as? Data, let image = UIImage(data: imageData) {
successCallback(image)
} else {
errorCallback("Download failed")
}
} else {
let error = "Error \(anandt.error?.localizedDescription ?? "unknown by dev")"
errorCallback(error)
}
}
}
}

Resources