I get this error when i try to compare two images from my s3 bucket, i follow the functions rules to get an image from S3Object with correct name and s3 bucket name but i throws the Invalid image format exception. Maybe it has to be as a base64 or bytebuffer? i dont understand then why there is a function to get from S3Object.
My code is simple and as follows:
String reference = "reference.jpg";
String target = "selfie.jpg";
String bucket = "pruebas";
CompareFacesRequest request = new CompareFacesRequest()
.withSourceImage(new Image().withS3Object(new S3Object()
.withName(reference).withBucket(bucket)))
.withTargetImage(new Image().withS3Object(new S3Object()
.withName(target).withBucket(bucket)))
.withSimilarityThreshold(similarityThreshold);
AmazonRekognition rekognitionClient = AmazonRekognitionClientBuilder.standard()
.withRegion(Regions.US_EAST_1).build();
CompareFacesResult compareFacesResult= rekognitionClient.compareFaces(request);
The exception is thrown in compareFaces(request) the last line.
this is main part of the error:
Exception in thread "main" com.amazonaws.services.rekognition.model.InvalidImageFormatException: Request has invalid image format (Service: AmazonRekognition; Status Code: 400; Error Code: InvalidImageFormatException;
The images are in AWS S3 and my credentials for rekognition have permission to read from S3. So in that part is not the error.
UPDATE CODE:
public static void main(String[] args) throws FileNotFoundException {
Float similarityThreshold = 70F;
String reference = "reference.jpg";
String target = "target.jpg";
String bucket = "pruebas";
ProfileCredentialsProvider credentialsProvider = ProfileCredentialsProvider.builder().profileName("S3").build();
Region region = Region.US_EAST_1;
S3Client s3 = S3Client.builder()
.region(region)
.credentialsProvider(credentialsProvider)
.build();
byte[] sourceStream = getObjectBytes(s3, bucket,reference);
byte[] tarStream = getObjectBytes(s3, bucket, target);
SdkBytes sourceBytes = SdkBytes.fromByteArrayUnsafe(sourceStream);
SdkBytes targetBytes = SdkBytes.fromByteArrayUnsafe(tarStream);
Image souImage = Image.builder()
.bytes(sourceBytes)
.build();
Image tarImage = Image.builder()
.bytes(targetBytes)
.build();
CompareFacesRequest request = CompareFacesRequest.builder()
.sourceImage(souImage)
.targetImage(tarImage)
.similarityThreshold(similarityThreshold).build();
RekognitionClient rekognitionClient = RekognitionClient.builder()
.region(Region.US_EAST_2).build();
CompareFacesResponse compareFacesResult= rekognitionClient.compareFaces(request);
List<CompareFacesMatch> faceDetails = compareFacesResult.faceMatches();
for (CompareFacesMatch match: faceDetails){
ComparedFace face= match.face();
BoundingBox position = face.boundingBox();
System.out.println("Face at " + position.left().toString()
+ " " + position.top()
+ " matches with " + face.confidence().toString()
+ "% confidence.");
}
List<ComparedFace> uncompared = compareFacesResult.unmatchedFaces();
System.out.println("There was " + uncompared.size()
+ " face(s) that did not match");
System.out.println("Source image rotation: " + compareFacesResult.sourceImageOrientationCorrection());
System.out.println("target image rotation: " + compareFacesResult.targetImageOrientationCorrection());
}
public static byte[] getObjectBytes (S3Client s3, String bucketName, String keyName) {
try {
GetObjectRequest objectRequest = GetObjectRequest
.builder()
.key(keyName)
.bucket(bucketName)
.build();
ResponseBytes<GetObjectResponse> objectBytes = s3.getObjectAsBytes(objectRequest);
return objectBytes.asByteArray();
} catch (S3Exception e) {
System.err.println(e.awsErrorDetails().errorMessage());
System.exit(1);
}
return null;
}
Try using AWS SDK for Java V2 - not the old V1 lib. Using V2 is strongly recommended over V1 and is best practice.
Here is the V2 code that works fine to compare faces. In this example, notice that you have to get the image into a SdkBytes object. It does not matter where the image is located as long as you get it into SDKBytes. The image can be in an S3 bucket, the local file system. etc.
You can find this V2 Reckonation example in the AWS Github repo here:
Also - you can use S3 Java V2 Service client to read an image in an S3 bucket and get the byte[]. From there, you can create an SDKBytes object to use in CompareFaces.
Here is the full Java example for Compare Faces. Notice there is an URL to the Java DEV Guide if you do not know how to get up and running with AWS SDK for Java V2 - including how to set up your creds.
package com.example.rekognition;
// snippet-start:[rekognition.java2.compare_faces.import]
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.rekognition.RekognitionClient;
import software.amazon.awssdk.services.rekognition.model.RekognitionException;
import software.amazon.awssdk.services.rekognition.model.Image;
import software.amazon.awssdk.services.rekognition.model.CompareFacesRequest;
import software.amazon.awssdk.services.rekognition.model.CompareFacesResponse;
import software.amazon.awssdk.services.rekognition.model.CompareFacesMatch;
import software.amazon.awssdk.services.rekognition.model.ComparedFace;
import software.amazon.awssdk.services.rekognition.model.BoundingBox;
import software.amazon.awssdk.core.SdkBytes;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;
// snippet-end:[rekognition.java2.compare_faces.import]
/**
* Before running this Java V2 code example, set up your development environment, including your credentials.
*
* For more information, see the following documentation topic:
*
* https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
*/
public class CompareFaces {
public static void main(String[] args) {
final String usage = "\n" +
"Usage: " +
" <pathSource> <pathTarget>\n\n" +
"Where:\n" +
" pathSource - The path to the source image (for example, C:\\AWS\\pic1.png). \n " +
" pathTarget - The path to the target image (for example, C:\\AWS\\pic2.png). \n\n";
if (args.length != 2) {
System.out.println(usage);
System.exit(1);
}
Float similarityThreshold = 70F;
String sourceImage = args[0];
String targetImage = args[1];
Region region = Region.US_EAST_1;
RekognitionClient rekClient = RekognitionClient.builder()
.region(region)
.credentialsProvider(ProfileCredentialsProvider.create())
.build();
compareTwoFaces(rekClient, similarityThreshold, sourceImage, targetImage);
rekClient.close();
}
// snippet-start:[rekognition.java2.compare_faces.main]
public static void compareTwoFaces(RekognitionClient rekClient, Float similarityThreshold, String sourceImage, String targetImage) {
try {
InputStream sourceStream = new FileInputStream(sourceImage);
InputStream tarStream = new FileInputStream(targetImage);
SdkBytes sourceBytes = SdkBytes.fromInputStream(sourceStream);
SdkBytes targetBytes = SdkBytes.fromInputStream(tarStream);
// Create an Image object for the source image.
Image souImage = Image.builder()
.bytes(sourceBytes)
.build();
Image tarImage = Image.builder()
.bytes(targetBytes)
.build();
CompareFacesRequest facesRequest = CompareFacesRequest.builder()
.sourceImage(souImage)
.targetImage(tarImage)
.similarityThreshold(similarityThreshold)
.build();
// Compare the two images.
CompareFacesResponse compareFacesResult = rekClient.compareFaces(facesRequest);
List<CompareFacesMatch> faceDetails = compareFacesResult.faceMatches();
for (CompareFacesMatch match: faceDetails){
ComparedFace face= match.face();
BoundingBox position = face.boundingBox();
System.out.println("Face at " + position.left().toString()
+ " " + position.top()
+ " matches with " + face.confidence().toString()
+ "% confidence.");
}
List<ComparedFace> uncompared = compareFacesResult.unmatchedFaces();
System.out.println("There was " + uncompared.size() + " face(s) that did not match");
System.out.println("Source image rotation: " + compareFacesResult.sourceImageOrientationCorrection());
System.out.println("target image rotation: " + compareFacesResult.targetImageOrientationCorrection());
} catch(RekognitionException | FileNotFoundException e) {
System.out.println("Failed to load source image " + sourceImage);
System.exit(1);
}
}
// snippet-end:[rekognition.java2.compare_faces.main]
}
This code works fine too with JPG images -- as shown in the following image of an IDE debugging the code displaying the results:
UPDATE
I normally do not touch V1 code at all; however, i was curious. This code worked....
package aws.example.rekognition.image;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.rekognition.AmazonRekognition;
import com.amazonaws.services.rekognition.AmazonRekognitionClientBuilder;
import com.amazonaws.services.rekognition.model.Image;
import com.amazonaws.services.rekognition.model.BoundingBox;
import com.amazonaws.services.rekognition.model.CompareFacesMatch;
import com.amazonaws.services.rekognition.model.CompareFacesRequest;
import com.amazonaws.services.rekognition.model.CompareFacesResult;
import com.amazonaws.services.rekognition.model.ComparedFace;
import java.util.List;
import com.amazonaws.services.rekognition.model.S3Object;
public class CompareFacesBucket {
public static void main(String[] args) throws Exception{
Float similarityThreshold = 70F;
AmazonRekognition rekognitionClient = AmazonRekognitionClientBuilder.standard()
.withRegion(Regions.US_WEST_2)
.build();
String reference = "Lam1.jpg";
String target = "Lam2.jpg";
String bucket = "<MyBucket>";
CompareFacesRequest request = new CompareFacesRequest()
.withSourceImage(new Image().withS3Object(new S3Object()
.withName(reference).withBucket(bucket)))
.withTargetImage(new Image().withS3Object(new S3Object()
.withName(target).withBucket(bucket)))
.withSimilarityThreshold(similarityThreshold);
// Call operation
CompareFacesResult compareFacesResult = rekognitionClient.compareFaces(request);
// Display results
List <CompareFacesMatch> faceDetails = compareFacesResult.getFaceMatches();
for (CompareFacesMatch match: faceDetails){
ComparedFace face= match.getFace();
BoundingBox position = face.getBoundingBox();
System.out.println("Face at " + position.getLeft().toString()
+ " " + position.getTop()
+ " matches with " + face.getConfidence().toString()
+ "% confidence.");
}
List<ComparedFace> uncompared = compareFacesResult.getUnmatchedFaces();
System.out.println("There was " + uncompared.size()
+ " face(s) that did not match");
System.out.println("Source image rotation: " + compareFacesResult.getSourceImageOrientationCorrection());
System.out.println("target image rotation: " + compareFacesResult.getTargetImageOrientationCorrection());
}
}
Output:
The last thing that i can think of as my V1 code works with JPG images and yours does not is your JPG image files may be corrupt or something. I would like to test this code with your images.