Face++(曠視)人臉檢測SDK開發流程

1. SDK下載

當前最新版SDK地址
其實整個SDK裏面只用到三個核心文件、三個util腳本,當然如果不想自己創建工程,它裏面有一個demo是可以直接跑的。

2. 核心文件導入

SDK包含三個核心文件:

  • MGFaceppSDK-0.5.2.aar :裏面包含SDK 的接口,一般使用最多的接口都封裝在這裏;
  • MGLicenseManagerSDK-0.3.1.aar :授權SDK,專門負責檢驗授權,每次應用啓動第一件事就是檢測授權;
  • megviifacepp_0_5_2_model :做人臉檢測的模型文件,曠視將其合併壓縮(很好奇爲什麼能做的這麼小)。

兩個.aar文件位於:~\MegviiFacepp_Android_0.5.2\Android-Demo\Android-Demo\faceppdemo\libs,將它們拷貝到YourProject\app\libs;模型文件位於~\MegviiFacepp_Android_0.5.2\Android-Demo\Android-Demo\faceppdemo\src\main\res\raw,將其拷貝到YourProject\app\src\main\res\raw(文件夾raw可能並不存在,手動創建就好)。

在 AS 中修改module的配置文件build.gradle:在dependencies結構中添加如下兩行

compile(name: 'MGLicenseManagerSDK-0.3.1', ext: 'aar')
compile(name: 'MGFaceppSDK-0.5.2', ext: 'aar')

android結構中添加如下代碼

repositories {
    flatDir {
        dirs 'libs'
    }
}

注意:官方文檔給出的是compile命令,在最新的Android框架中可能會提示使用implementation去替代;name需要跟你使用的SDK版本保持一致,否則會報錯。接下來重新編譯工程即可:菜單欄Build -> Clean Project-> Rebuild Project。成功之後可以在工程中使用如下命令導入和使用SDK:

import com.megvii.facepp.sdk.Facepp;
import com.megvii.licensemanager.sdk.LicenseManager;

3. util腳本

這三個腳本其實並不是必需的,但是確實是要用到裏面的一些方法,那既然官方寫好了那我們直接用就好。

  • SharedUtil.java:用來存儲數據的
  • ConUtil.java:一些實用的方法
  • Util.java:你的API_Key、Secret_Key就放在這兒

直接將這三個文件拷貝到YourProject\app\src\main\java\com\**\**\util下面,然後修改每個文件頭部的package,修改Util.javakey值爲你自己就好。key值需要到官網註冊賬號,然後新建API,綁定Bundle(在“應用管理”中可以看到),Bundle的ID最好是跟項目的applicationId保持一致(我試過不一樣也能用好像~)。

4. 聯網授權

SDK分爲離線授權和聯網授權兩種,離線授權就是你買它的SDK,他給你的時候就把權限寫在SDK裏面了;聯網授權一般是在免費使用版本中,每一次使用SDK的時候需要通過網絡訪問來獲取權限,這裏以聯網授權的版本爲例。

  1. 聯網授權SDK(試用版)有效期爲 1 天,有效期內可免費授權五次,同一APP重複使用、不卸載安裝都只會在首次進行聯網授權(卸載重裝會佔用一次),之後會將License文件保存在本地,直到License過期。
  2. 聯網授權需要幾個權限:INTERNETACCESS_NETWORK_STATE,然後還有關於圖像數據的讀寫、相機權限等需要自己添加,最好是動態授權。

聯網授權最關鍵的代碼部分:

private void network() {
        // 獲取聯網授權類型
        int type = Facepp.getSDKAuthType(ConUtil.getFileContent(this, R.raw.megviifacepp_0_5_2_model));
        if ( type == 2) {// 非聯網授權
            authState(true,0,"");
            return;
        }

        // 開始聯網授權
        final LicenseManager licenseManager = new LicenseManager(this);

        String uuid = ConUtil.getUUIDString(this);      // 手機唯一序列號
        long apiName = Facepp.getApiName();             // 大概是SDK的版本名稱,API自己獲取不用管
        licenseManager.setAuthTimeBufferMillis(0);      // 設置時間緩衝,猜測可能跟SDK的License期限有關

        // 回調
        licenseManager.takeLicenseFromNetwork(
                Util.CN_LICENSE_URL,    // 聯網授權地址
                uuid,
                Util.API_KEY,
                Util.API_SECRET,
                apiName,
                "1",                    // 使用期限,試用版本只能是1天
                new LicenseManager.TakeLicenseCallback() {
                    @Override
                    public void onSuccess() {
                        authState(true,0,"");
                    } 

                    @Override
                    public void onFailed(int i, byte[] bytes) {
                        if (TextUtils.isEmpty(Util.API_KEY)||TextUtils.isEmpty(Util.API_SECRET)) {      
                            if (!ConUtil.isReadKey(MainActivity.this)) {
                                authState(false,1001,"");
                            }else{
                                authState(false,1001,"");
                            }
                        }else{
                            String msg="";
                            if (bytes!=null&&bytes.length>0){
                                msg=  new String(bytes);
                            }
                            authState(false,i,msg);
                        }
                    }
                });
    }

    private void authState(boolean isSuccess,int code,String msg) {
        if (isSuccess) {		// 聯網授權成功
            Log.d("聯網授權", "成功");
            
            Intent intent = new Intent();
            intent.setClass(this, FaceActionActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(intent);
            finish();
        } else {				// 聯網授權失敗
            Log.d(code, msg);
        }
    }

最爲關鍵的就是licenseManager.takeLicenseFromNetwork,它裏面重寫了onSuccessonFailed函數,分別會在授權成功/失敗時調用。授權成功的話我們會讓它跳轉至FaceActionActivity.class,同時銷燬當前的MainActivity,然後在FaceActionActivity裏進行人臉關鍵點的檢測,這樣做的原因是:聯網授權的network(其實就是裏面的licenseManager.takeLicenseFromNetwork)是一個異步事件,需要在它的OnSuccess裏面做檢測,如果在這之後做檢測可能會有問題。
官方給出的一些說明好像跟實際應用開發並不一致,比如關於權限次數:官方文檔寫明一個API_Key一天有五次機會,也就是說如果你把當前的API_Key刪除,重新創建一個API_Key會擁有新的五次機會,但實踐證明不會。可以能會得到以下的返回錯誤:

  • LICENSE_NOT_FOUND:刪除次數已滿的API_Key,使用新建的API_Key,可能會得到這個錯誤(它以爲你用了正式API_Key,但是本地並沒有找到);
  • MG_RETCODE_INVALID_LICENSE:授權失敗;
  • DAILY_QUOTA_EXCEEDED:當前API_Key免費使用次數達到上限。

5. 調用SDK實現人臉關鍵點檢測

(1)初始化實例,然後加載模型

Facepp facepp = new Facepp();
String errorCode = facepp.init(this, ConUtil.getFileContent(this, R.raw.megviifacepp_0_5_2_model),  1);

這裏可能會存在R.raw不存在的問題,關掉項目重新打開一下就好;最後一個參數表示是否只檢測單個人臉,0表示否,1表示是。一般如果聯網授權沒問題,這裏的errorCode返回值是null,否則會返回具體的錯誤信息。
(2)檢測參數設置

// 設置檢測器參數(這裏只列出一部分)
Facepp.FaceppConfig faceppConfig = new Facepp.FaceppConfig();
faceppConfig.detectionMode = Facepp.FaceppConfig.DETECTION_MODE_TRACKING_FAST;  // 檢測模式:FAST,ROUBUST
faceppConfig.minFaceSize = 1;           // 最小人臉尺寸
faceppConfig.roi_right = w;             // 感興趣區域
faceppConfig.roi_bottom = h;
facepp.setFaceppConfig(faceppConfig);

(3)人臉檢測,獲取數據

// 檢測人臉,最後一個參數是輸入圖像的格式
final Facepp.Face[] faces = facepp.detect(imgData, w, h, Facepp.IMAGEMODE_NV21);

// 獲取人臉數據
facepp.getLandmarkRaw(faces[0], Facepp.FPP_GET_LANDMARK106);
facepp.get3DPose(faces[0]);

檢測人臉的時候輸入數據類型是byte[],官方給出支持 NV21、BGR 格式的檢測(就是detect方法的最後一個參數),但是親測好像只支持NV21,所以最好是將圖像轉成 NV21 格式的byte[];如果把BGR數據送進去,最後檢測到的人臉數量爲0。

關於SDK能夠獲取到的數據可以看官方文檔,基本上就是關鍵點、頭部3D-pose、人臉屬性等,有些事收費才能獲取的,但是關鍵點和頭部3D-pose是免費的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章