All
Announcement
Events
Product News

Face++ 101: How Do I Find the One with Face Search?

Have you been wondering how do I find the right ONE with Face++ face search? Let’s take a look at this face search guide!

Within face recognition, there is a growing number of developers who are trying to engage in face search related applications. If you are one of them, having lots of great creative ideas but are just confused about where to start with, no worries! This post might become a help for you to start using Face++ for face search!

Face Search

Basic Concepts

  • Face: In facial recognition technologies, Face indicates the faces detected in images and videos. When performing face detection to an image, the detected faces will be recorded, along with relevant face information. Face will be marked by unique id called face_token.
  • FaceSet: FaceSet serves to store the detected faces, that is, face_token, which can be applied to subsequent face recognition functions.
  • Face Search: Face search is the process of finding one or more most similar faces from FaceSet, to a new face. Generally speaking, this feature is applied when one needs to identify who does a new face belongs to within a known set of faces. This is which we often refers to as 1:N application.

The Process of Face Search

To help users get familiar with the feature, the process is as follows:

  • Create one FaceSet to store all the faces.
  • Make face detect API request. Each detected face gets its face_token.
  • Add face_token to FaceSet.
  • Relate face_token to the real person, as we are more interested in who the person is from the result of the search.
  • Execute search, and acquire the face_token which most resembles.
  • User gets the person’s information that relates to the face_token.

How to Make API Request

After understanding the process, let’s start with the APIs!

  • API Request: Each API request must be a POST request, then just follow the official documents and pass the appropriate parameters. Here we use Objective-C as a demonstration. There are POST request samples for other programming languages, which you can find in the link at the end of this article.
  • API Authentication: Each API request should provide a set of api_key and api_secret, which is used to verify whether the request is authenticated.
    Now let’s start to create one api_key and api_secret.
  • First, we need to sign up an account on Face++.

With the account, we can start to create api_key and api_secret. Click me and start creating one.

There are standard and free API key types, there is no difference in terms of what you can do with these two. However, free API key do have limited availability during peak hours, and you can create only one free API key. As for standard API key, you are able to make queries stably (guaranteed 10 QPS capacity) and create unlimited amount of API key. So don’t hastate to top-up and try out what you are capable of!

After getting preparation done, now we are ready to deal with the codes!

Codes

Let us go step by step with the codes:

//outer_id is an id of faceSet and can be custom by yourself.
+ (void)createFaceSetWithDisplayName:(NSString *)displayName outerId:(NSString *)outerId tgas:(NSArray<NSString *> *)tags faceTokens:(NSArray *)tokens userData:(NSString *)userData forceMerge:(BOOL)forceMerge completion:(void(^)(id info,NSError *error))completion{
    NSString *url = [NSString stringWithFormat:@"%@/%@/%@",FACE_WEB_BASE,FACESET,FACESET_CREATE];
    NSMutableDictionary *param = [NSMutableDictionary dictionary];
    if (displayName.length) {
        param[@"display_name"]  = displayName;
    }
    if (outerId.length) {
        param[@"outer_id"]  = outerId;
    }
    if (userData.length) {
        param[@"user_data"]  = userData;
    }

    if (tags.count) {
        NSString *tagStr = [tags componentsJoinedByString:@","];
        param[@"tags"] = tagStr;
    }

    if (tokens) {
        NSString *tokenStr = [tokens componentsJoinedByString:@","];
        param[@"face_tokens"] = tokenStr;
    }
    NSNumber *force_merge = forceMerge ? @(1) : @(0);
    [param setObject:force_merge forKey:@"force_merge"];
    [FCPPApi POST:url param:param completion:completion];
}
  //The api can detect age,gender,facePower and son on,but here we only need face_token
  - (void)detectFaceWithReturnLandmark:(BOOL)return_landmark attributes:(NSArray<NSString *> *)attributes completion:(void(^)(id info,NSError *error))completion{

    NSString *url = [NSString stringWithFormat:@"%@/%@",FACE_WEB_BASE,FACE_DETECT];
    NSNumber *landmark = return_landmark ? @(1) : @(0);

    NSMutableDictionary *param = [NSMutableDictionary dictionary];
    [param setObject:landmark forKey:@"return_landmark"];

    NSString *att = [attributes componentsJoinedByString:@","];
    if (att.length) {
        [param setObject:att.copy forKey:@"return_attributes"];
    }

    if (self.image) {
        NSString *baseStr = self.image.base64String;
        [param setObject:baseStr forKey:@"image_base64"];
//        [param setObject:self.image.imageData forKey:@"image_file"];
    }else if (self.imageUrl){
        if ([self.imageUrl hasPrefix:@"http"]) {
            [param setObject:self.imageUrl forKey:@"image_url"];
        }else{
            NSLog(@"please input a vaild url");
        }
    }else{
        NSLog(@"please set a image object or url ");
    }
    [FCPPApi POST:url param:param completion:completion];
}
- (void)addFaceTokens:(NSArray<NSString *> *)tokens completion:(void(^)(id info,NSError *error))completion{
    NSString *url = [NSString stringWithFormat:@"%@/%@/%@",FACE_WEB_BASE,FACESET,FACESET_ADDFACE];
    NSMutableDictionary *param = [NSMutableDictionary dictionary];

    if (tokens.count) {
        NSString *tokenStr = [tokens componentsJoinedByString:@","];
        param[@"face_tokens"] = tokenStr;
    }

    if (self.faceset_token) {
        param[@"faceset_token"] = self.faceset_token;
    }else if(self.outer_id){
        param[@"outer_id"] = self.outer_id;
    }

    [FCPPApi POST:url param:param completion:completion];
}
  • Relate face_token to the real person, as we are mostly interested in who the person is and his information from the result of the search.To simplify, we use plist instead of a database. In reality, we should store the information of the person, such as picture and name, which relates to the face_token.
  • Execute SearchFinally the most important moment! As usual, here is the API document reference: https://console.faceplusplus.com/documents/5681455
    You can use a face_token, an image file or even a URL to execute face search. To simplify, here we define it as an object FCPPFace.
  //search
  - (void)searchFromFaceSet:(FCPPFaceSet *)faceSet returnCount:(int)returnCount completion:(void(^)(id info,NSError *error))completion{
    NSString *url = [NSString stringWithFormat:@"%@/%@",FACE_WEB_BASE,FACE_SEARCH];
    NSMutableDictionary *param = [NSMutableDictionary dictionary];

    if (self.faceToken){
        [param setObject:self.faceToken forKey:@"face_token"];
    }else if (self.image){
        NSString *baseStr = self.image.base64String;
        [param setObject:baseStr forKey:@"image_base64"];
    }else if (self.imageUrl) {
        [param setObject:self.imageUrl forKey:@"image_url"];
    }

    if (returnCount > 0 && returnCount < 6) {
        [param setObject:@(returnCount) forKey:@"return_result_count"];
    }

    if (faceSet.faceset_token) {
        [param setObject:faceSet.faceset_token forKey:@"faceset_token"];
    }else if (faceSet.outer_id){
        [param setObject:faceSet.outer_id forKey:@"outer_id"];
    }

    [FCPPApi POST:url param:param completion:completion];
}
  • User acquire the person’s information and his picture from the database (plist) that relates to the face_token. Please note that the returning face_token only tells us which is the most similar face, we still need to confirm with the result parameter “confidence” for its reliability.
 - (void)searchImage:(UIImage *)image{
    self.imageView.image = image;
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.label.text = @"Searching....";
    FCPPFace *face = [[FCPPFace alloc] initWithImage:image];
    self.faceIndex = -1;
    //4.do search
    [face searchFromFaceSet:self.faceSet returnCount:1 completion:^(id info, NSError *error) {
        if (info) {
            NSArray *faces = info[@"faces"];
            if (faces.count) {
                [hud hideAnimated:YES];
                NSDictionary *result = [info[@"results"] firstObject];
                NSDictionary *thresholds = info[@"thresholds"];
                NSString *faceToken = result[@"face_token"];
                CGFloat confidence = [result[@"confidence"] floatValue];
                CGFloat maxThreshold = [thresholds[@"1e-5"] floatValue];
                CGFloat midThreshold = [thresholds[@"1e-4"] floatValue];
                CGFloat minThreshold = [thresholds[@"1e-3"] floatValue];

                BOOL vaild = confidence > midThreshold;
                if (faceToken && vaild) {//find vaild face
                    NSLog(@"%@",faceToken);
                    //5.Get some info     
through the map relationship  
                    if ([self.dataArray containsObject:faceToken]) {
                        NSInteger index = [self.dataArray indexOfObject:faceToken];
                        self.faceIndex = index;
                        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
                        [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
                    }
                }else{
                    hud.label.text = @"NO vaild faces";
                    [hud hideAnimated:YES afterDelay:1.0];
                }
            }else{
                hud.label.text = @"No face found";
                [hud hideAnimated:YES afterDelay:1.0];
            }
        }else{
            hud.label.text = @"network error";
            [hud hideAnimated:YES afterDelay:1.0];
        }
        [self.collectionView reloadData];
    }];
}

Congratulations, the job’s done! Now feel free to bring all your fantastic ideas into reality with Face++ face search!

Other References

We are always dedicated to improve our services to fit your needs. If there is any problem, please do not hesitate to contact us.