Just My Life & My Work

此刻要記錄實作內容,才想起先前已寫過一篇,不過那篇是沒有原始碼,然而依舊可參考:[iOS] 使用Vision人臉偵測 (Face Detection Using Vision)。😎

這是2020年11月去陽明山二子坪的大合照
廣告

接下來簡單扼要,寫出核心程式碼~

/**
    Theme: Face Detection Using Vision
    Compiler: Xcode 12.4
    Date: 110/04/14
    Author: HappyMan
    Blog: https://cg2010studio.com/
*/

#import <Vision/Vision.h>

API_AVAILABLE(ios(11.0))
typedef void(^CompletionHandler)(VNRequest * _Nullable request, NSError * _Nullable error);

-(void)doFaceDetection
{
    NSString *name = [NSString stringWithFormat:@"happy group.JPG"];
    
    UIImage *image = [UIImage imageNamed:name];
    
    imageView.image = image;
    
    // 轉換CIImage
    CIImage *convertImage = [[CIImage alloc] initWithImage:image];

    // 創建處理 RequestHandler
    VNImageRequestHandler *detectRequestHandler = [[VNImageRequestHandler alloc] initWithCIImage:convertImage options:@{}];

    // 設置回調
    CompletionHandler completionHandler = ^(VNRequest *request, NSError * _Nullable error) {
    NSArray *observations = request.results;

        dispatch_async(dispatch_get_main_queue(), ^{
            for (VNFaceObservation *face in observations) {
                UIView *view = [self createBoxView:[UIColor redColor]];
                view.frame = [self transformFromRect:face.boundingBox toView:self->imageView];
                [self->imageView addSubview:view];
            }
        });
    };

    // 創建 BaseRequest
    VNImageBasedRequest *detectRequest = [[VNDetectFaceRectanglesRequest alloc] initWithCompletionHandler:completionHandler];

    // 發送識別請求
    [detectRequestHandler performRequests:@[detectRequest] error:nil];
}

-(UIView *)createBoxView:(UIColor *)color
{
    UIView *view = [[UIView alloc] init];
    view.layer.borderColor = color.CGColor;
    view.layer.borderWidth = 2;
    view.backgroundColor = [UIColor clearColor];
    return view;
}

-(CGRect)transformFromRect:(CGRect)fromRect toView:(UIView *)toView
{
    // Convert Vision Frame to UIKit Frame
    CGRect toRect = CGRectZero;
    toRect.size.width = fromRect.size.width * toView.frame.size.width;
    toRect.size.height = fromRect.size.height * toView.frame.size.height;
    toRect.origin.y = (toView.frame.size.height) - (toView.frame.size.height * fromRect.origin.y);
    toRect.origin.y = toRect.origin.y - toRect.size.height;
    toRect.origin.x = fromRect.origin.x * toView.frame.size.width;
    return toRect;
}

.

透過上面基本的程式碼,就可以進行其他進階應用,比如偵測人臉是否被「切臉」,有三種狀況:

  • 框內
  • 框外
  • 被框切

經過無數測試,發現神奇的現象,就是不管相片解析度大小,執行一次人臉偵測的時間都差不多呢!

另外人臉佔整張相片太小,也不容易被偵測出來,看來跟它的演算法參數設定有關係。這部分可參考我2011年寫的文章:[OpenCV] 人臉偵測 (Face Detection)

公司產品想要開發個新穎的功能,就是判斷有無被切臉,以免印製出來遭到用戶退貨~😌

廣告

由於可能要同時偵測大量相片(高達1000張),執行人臉偵測的時間就顯得很重要,因為會影響使用者體驗。這時候就要有所取捨,需要在使用者體驗亮眼功能取得平衡!

  • 目前新增的功能是做到不太影響原本體驗,來默默人臉偵測,好心提示有無切臉。
  • 若要掃描整份專案,可以在點「加入購物車」時,進行所有相片框偵測人臉。
  • 此時有兩種進行情況:
  • 1. 若「必要」,則需要擋UI,等到所有相片偵測結束,才能進行下單
    類似偵測到「相片遺失」
  • 2. 若「非必要」,則不需要擋UI,不等到所有相片偵測結束,就能進行下單
    類似偵測到「縮放比例過大,不符合印製需求」
  • 考量偵測人臉時間,處理單張相片:
    • iPhone 8,不分相片尺寸,平均處理時間:0.3s
    • iPhone 6,不分相片尺寸,平均處理時間:0.6s
  • 若以「同步」進行人臉偵測,處理最大數量情況1000張相片
    • iPhone 8,不分相片尺寸,平均處理時間:300s
    • iPhone 6,不分相片尺寸,平均處理時間:600s
  • 若以「非同步」進行人臉偵測,處理最大數量情況1000張相片
    • iPhone 8,不分相片尺寸,處理時間約:146s
    • iPhone 6,不分相片尺寸,處理時間約:432s
  • 接著若偵測到有被切頭,需要如何提示用戶,並快速讓用戶找到該相片,相片數量大不好找尋。
  • 於是會增加完稿時間與影響下單體驗。也許可以做個「選擇性」讓用戶看是否要進行所有相片人臉偵測有無切臉。
廣告

隨意留個言吧:)~

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google photo

您的留言將使用 Google 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

標籤雲

%d 位部落客按了讚: