$\color{DarkTurquoise}{溫馨提示}$
$\color{DarkTurquoise}{本篇就是針對小白寫的,小白不用怕
另外也需要一定的android原生基礎,入門能看懂程式碼即可,不需要精通}$
2、本篇用到的技術棧以及SDK
- 虹軟人臉識別SDK v3.0
- android
- vue
- uniapp
3、技術接入部分
1、去虹軟控制檯(要登入哦)下載人臉識別Demo,傳送陣,
注意需要新建一個應用,如下圖,SDK中包含Demo
2、 將Demo匯入AndroidStudio,下圖就是Demo的樣子:
$\color{DarkTurquoise}{注意:AndroidStudio匯入的專案路徑一定不要有中文}$
*
3、如果不出意外的話,執行專案就會出現如下介面了,至此虹軟Demo也就跑起來了
如果出意外了,請檢視該文章的$\color{DarkTurquoise}{可能遇到的錯誤}$章節
5、將Demo匯入AndroidStudio,下圖就是Demo的樣子:
$\color{DarkTurquoise}{注意:AndroidStudio匯入的專案路徑一定不要有中文}$
6、跑專案,會出現$\color{DarkTurquoise}{未配置appkey或配置錯誤}$字樣,解決方法請參考:如何申請appkey傳送陣\
$\color{DarkTurquoise}{注意解決這個問題還是稍微比較複雜點的,請認真閱讀官方文件,不要懷疑官方文件的正確性}$
//過程中需要用到的一個生成 sha1 值得命令,在 C:\Program Files\Java\jre1.8.0_291\bin 路徑下執行 cmd
keytool.exe -list -v -keystore 【keystore檔案的絕對路徑】
8、兩個 Demo 都跑起來了,接下來就是整合兩個 Demo 了,首先在 uniapp 的 Demo 中右擊建立一個Module
9、選擇 Android Library ,在右側填寫如下圖幾個屬性,注意 Package name 儘量與虹軟Demo中的一致,因為之後會避免解決一些不必要的錯誤,下一步
10、將虹軟 Demo 中的如下 資料夾中的所有內容(包括資料夾)複製到剛才建立的 Module 中的同樣位置
libs
java
jniLibs
res
11、將 Module 中的 build.gradle 中的 dependencies 全部刪除,加入下面的
compileOnly fileTree(dir: '../app/libs', include: ['uniapp-v8-release.aar'])
implementation 'com.alibaba:fastjson:1.1.46.android'
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
implementation 'com.github.bumptech.glide:glide:4.9.0'
implementation 'io.reactivex.rxjava2:rxjava:2.2.6'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
compileOnly "com.android.support:recyclerview-v7:28.0.0"
compileOnly "com.android.support:support-v4:28.0.0"
compileOnly "com.android.support:appcompat-v7:28.0.0"
implementation 'com.android.support.constraint:constraint-layout:2.0.1'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
12、截至目前步驟,我們所有的準備基本已經就緒,接下來我們需要建立一下三個檔案
FaceReco_AppProxy.java //用於初始化動態連結庫
FaceReco.java //用於啟用虹軟SDK
FaceRecoView.java //用於人臉檢測檢視
13、我們找到 FaceAttrPreviewActivity 檔案,將關於人臉識別的核心程式碼拷貝到 FaceRecoView 檔案中,核心程式碼如下:
* 初始化引擎
*/
private void initEngine() {
faceEngine = new FaceEngine();
afCode = faceEngine.init(getContext(), DetectMode.ASF_DETECT_MODE_VIDEO, ConfigUtil.getFtOrient(getContext()),
16, 20, FaceEngine.ASF_FACE_DETECT | FaceEngine.ASF_AGE | FaceEngine.ASF_FACE3DANGLE | FaceEngine.ASF_GENDER | FaceEngine.ASF_LIVENESS);
Log.i(TAG, "initEngine: init: " + afCode);
if (afCode != ErrorInfo.MOK) {
System.out.println(R.string.init_failed+":"+afCode);
}
}
/**
* 解除安裝引擎
*/
private void unInitEngine() {
if (afCode == 0) {
afCode = faceEngine.unInit();
Log.i(TAG, "unInitEngine: " + afCode);
}
}
/**
* 初始化攝像頭
*/
private void initCamera() {
DisplayMetrics metrics = new DisplayMetrics();
Activity activity = (Activity)getContext();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
CameraListener cameraListener = new CameraListener() {
@Override
public void onCameraOpened(Camera camera, int cameraId, int displayOrientation, boolean isMirror) {
Log.i(TAG, "onCameraOpened: " + cameraId + " " + displayOrientation + " " + isMirror);
previewSize = camera.getParameters().getPreviewSize();
drawHelper = new DrawHelper(previewSize.width, previewSize.height, previewView.getWidth(), previewView.getHeight(), displayOrientation
, cameraId, isMirror, false, false);
}
@Override
public void onPreview(byte[] nv21, Camera camera) {
if (faceRectView != null) {
faceRectView.clearFaceInfo();
}
List<FaceInfo> faceInfoList = new ArrayList<>();
long start = System.currentTimeMillis();
int code = faceEngine.detectFaces(nv21, previewSize.width, previewSize.height, FaceEngine.CP_PAF_NV21, faceInfoList);
if (code == ErrorInfo.MOK && faceInfoList.size() > 0) {
code = faceEngine.process(nv21, previewSize.width, previewSize.height, FaceEngine.CP_PAF_NV21, faceInfoList, processMask);
if (code != ErrorInfo.MOK) {
return;
}
} else {
return;
}
List<AgeInfo> ageInfoList = new ArrayList<>();
List<GenderInfo> genderInfoList = new ArrayList<>();
List<Face3DAngle> face3DAngleList = new ArrayList<>();
List<LivenessInfo> faceLivenessInfoList = new ArrayList<>();
int ageCode = faceEngine.getAge(ageInfoList);
int genderCode = faceEngine.getGender(genderInfoList);
int face3DAngleCode = faceEngine.getFace3DAngle(face3DAngleList);
int livenessCode = faceEngine.getLiveness(faceLivenessInfoList);
// 有其中一個的錯誤碼不為ErrorInfo.MOK,return
if ((ageCode | genderCode | face3DAngleCode | livenessCode) != ErrorInfo.MOK) {
return;
}
System.out.println("檢測成功");
if (faceRectView != null && drawHelper != null) {
List<DrawInfo> drawInfoList = new ArrayList<>();
for (int i = 0; i < faceInfoList.size(); i++) {
drawInfoList.add(new DrawInfo(drawHelper.adjustRect(faceInfoList.get(i).getRect()), genderInfoList.get(i).getGender(), ageInfoList.get(i).getAge(), faceLivenessInfoList.get(i).getLiveness(), RecognizeColor.COLOR_UNKNOWN, null));
}
drawHelper.draw(faceRectView, drawInfoList);
}
}
@Override
public void onCameraClosed() {
Log.i(TAG, "onCameraClosed: ");
}
@Override
public void onCameraError(Exception e) {
Log.i(TAG, "onCameraError: " + e.getMessage());
}
@Override
public void onCameraConfigurationChanged(int cameraID, int displayOrientation) {
if (drawHelper != null) {
drawHelper.setCameraDisplayOrientation(displayOrientation);
}
Log.i(TAG, "onCameraConfigurationChanged: " + cameraID + " " + displayOrientation);
}
};
cameraHelper = new CameraHelper.Builder()
.previewViewSize(new Point(previewView.getMeasuredWidth(), previewView.getMeasuredHeight()))
.rotation(activity.getWindowManager().getDefaultDisplay().getRotation())
.specificCameraId(rgbCameraId != null ? rgbCameraId : Camera.CameraInfo.CAMERA_FACING_FRONT)
.isMirror(false)
.previewOn(previewView)
.cameraListener(cameraListener)
.build();
cameraHelper.init();
cameraHelper.start();
}
14、此時人臉檢測頁面就整合到 uniapp 中了,當然還不可以使用,為什麼呢?當然是還有兩個檔案沒做完呢,一個用於啟用SDK的,一個用於初始化載入動態連結庫檔案的,最重要的兩步,開搞~\
15、首先將初始化動態連結庫檔案程式碼寫入 FaceReco_AppProxy 檔案中
* 檢查能否找到動態連結庫,如果找不到,請修改工程配置
*
* @param libraries 需要的動態連結庫
* @return 動態庫是否存在
*/
private boolean checkSoFile(String[] libraries,Application application) {
ApplicationInfo applicationInfo = application.getApplicationInfo();
File dir = new File(applicationInfo.nativeLibraryDir);
System.out.println("檔案路徑:"+dir.getAbsolutePath());
File[] files = dir.listFiles();
if (files == null || files.length == 0) {
return false;
}
List<String> libraryNameList = new ArrayList<>();
for (File file : files) {
System.out.println("檔名字:"+file.getName());
libraryNameList.add(file.getName());
}
boolean exists = true;
for (String library : libraries) {
exists &= libraryNameList.contains(library);
}
return exists;
}
16、然後啟用SDK檔案程式碼寫入 FaceReco 檔案中
/**
* 啟用裝置
*/
private void active(){
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) {
RuntimeABI runtimeABI = FaceEngine.getRuntimeABI();
Log.i(TAG, "subscribe: getRuntimeABI() " + runtimeABI);
int activeCode = FaceEngine.activeOnline(mUniSDKInstance.getContext(), CommonUtil.getAppId(), CommonUtil.getSdkKey());
emitter.onNext(activeCode);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer activeCode) {
if (activeCode == ErrorInfo.MOK) {
showToast(getString(R.string.active_success));
mJsCallback.invokeAndKeepAlive("啟用成功");
} else if (activeCode == ErrorInfo.MERR_ASF_ALREADY_ACTIVATED) {
showToast(getString(R.string.already_activated));
mJsCallback.invokeAndKeepAlive("該裝置已啟用");
} else {
showToast(getString(R.string.active_failed)+":"+activeCode);
mJsCallback.invokeAndKeepAlive("啟用失敗,錯誤碼:"+activeCode);
}
ActiveFileInfo activeFileInfo = new ActiveFileInfo();
int res = FaceEngine.getActiveFileInfo(mUniSDKInstance.getContext(), activeFileInfo);
if (res == ErrorInfo.MOK) {
Log.i(TAG, activeFileInfo.toString());
}
}
@Override
public void onError(Throwable e) {
showToast(e.getMessage());
}
@Override
public void onComplete() {
}
});
}
17、將 AndroidManifest.xml 檔案替換如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.arcsoft.arcfacedemo">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
18、至此,我們們外掛的所有的配置基本完成,接下來刪除兩個資料夾,為什麼要刪除這兩個資料夾呢,因為這兩個資料夾都是安卓原生的 activity 檢視,因為目前我們們的檢視是 uniapp 來驅動的,所以用不到這些東西了
activity
fragment
19、將 app 專案中引入我們們的外掛,在 app 專案中的 build.gradle 中配置
implementation project(':arcfacedemo')
20、將專案跑起來,沒有任何錯誤,漂亮,一切皆是那麼的完美,如下圖,呵呵,沒有任何變化,為什麼沒有變化呢?我們們繼續!
21、剛剛看到的是我們們的 uniapp 主介面,我們們目前只是把外掛部分做完了,接下來就是讓 uniapp 去調我們們的外掛,首先去寫一個介面,在這裡我就不寫介面了,我就直接說怎麼調外掛了,咦,對了,我們們的外掛還沒有打包,接下來打包外掛
22、在 Android Studio 中選擇 Build->Rebuild Project ,就將外掛打包好了,如圖:
23、怎麼用呢?在這裡我提供一下 package.json ,有了這個就不用我多說了吧!
{
"name": "虹軟SDK人臉檢測",
"id": "arc-face",
#### "version": "1.0.0",
"description": "基於虹軟SDK開發的人臉檢測外掛,外掛永久維護,歡迎提需求(qq群:785919513)",
"_dp_type":"nativeplugin",
"_dp_nativeplugin":{
"android": {
"plugins": [
{
"type": "module",
"name": "arc-faceReco",
"class": "com.arcsoft.arcfacedemo.FaceReco"
},
{
"type": "component",
"name": "arc-faceRecoView",
"class": "com.arcsoft.arcfacedemo.FaceRecoView"
}
],
"hooksClass": "com.arcsoft.arcfacedemo.FaceReco_AppProxy",
"integrateType": "aar",
"abis": [
"armeabi-v7a",
"arm64-v8a"
],
"minSdkVersion":23
}
}
}
24、至此外掛製作的全過程講解完畢\
4、可能遇到的錯誤
這個怎麼說呢!一般遇到編譯不通過的錯誤大部分都是環境問題,或者業務問題,這個需要對症下藥,博主說一下自己在整合的時候遇到的一些問題吧
1.找不到動態連結庫(.so檔案)
解決方法:忘記把 .so 檔案拷貝過來
2.忘記這個錯誤了,稍後補上
解決方法:建立 Module 時選擇 Android Library ,而不是選擇 Phone & Tablet
3.忘記這個錯誤了,稍後補上
解決方法:專案路徑中不要有中文
5、完結
瞭解更多人臉識別產品相關內容請到虹軟視覺開放平臺哦
|