欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android基于虹軟(ArcSoft)實現人臉識別

 更新時間:2021年12月14日 11:27:48   作者:Great_7  
人工智能時代快速來臨,其中人臉識別是當前比較熱門的技術,在國內也越來越多的運用,例如刷臉打卡,刷臉APP,身份識別,人臉門禁等。本文將為大家介紹Android基于虹軟(ArcSoft)實現人臉識別的demo,快來跟隨小編一起學習吧

1、在虹軟的開發(fā)者中心創(chuàng)建一個自己的應用,將APP_ID與SDK_KEY記錄下來,后面會用到。創(chuàng)建完后就可以下載SDK了。

在這里插入圖片描述

2、下載完后,就可以根據SDK包里的開發(fā)說明文檔和代碼進行參考和學習。以下是開發(fā)說明文檔中的SDK包結構的截圖。

在這里插入圖片描述

3、創(chuàng)建一個空項目,將SDK包里的.jar文件和.so文件復制到該項目的如下包下。接下來的配置十分重要,稍微沒處理一個,就是一個頭大的bug。

在這里插入圖片描述

4、“在app里的build.gradle” 第一個紅框原本是androidx的,與support是不兼容的,所以要改,因此,整個項目用到androidx的地方都需要改。第二個紅框是ndk,加了這個才能找到剛才復制進去的.so文件。第三個紅框也要改成如下。下面的dependencies要注意把androidx的改掉。

在這里插入圖片描述

在這里插入圖片描述

5、“在整個項目里的build.gradle” 記得加上jcenter()。

在這里插入圖片描述

6、在gradle.properties里可能會有androidx的東西,也要刪掉。

在這里插入圖片描述

7、在AndroidManifest.xml中的中添加權限申請,在中添加。

manifest:

<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.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

provider:

<provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
        </provider>

在添加后要在res下創(chuàng)建一個xml包,里面添加一個provider_paths.xml文件,里面的代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
    <root-path
        name="root_path"
        path="." />
</paths>

8、從SDK包中引入如下功能包模塊和BaseActivity,并將common包下的Constants中的APP_ID,SDK_KEY改成剛才所記錄下來的內容。

在這里插入圖片描述

9、創(chuàng)建3個acvitity,一個是主界面,一個是人臉庫的管理界面,一個是人臉識別功能界面。

在這里插入圖片描述

10、layout包下需要引入以下5個布局文件。

在這里插入圖片描述

11、主界面主要的功能就是激活權限、連接動態(tài)庫和激活引擎,我通過修改onCreate()和util包下的ConfigUtil.class的代碼,讓其能夠自動激活和自動修改為全方向人臉檢查(其他選擇好像不能夠實現人臉識別)。以下是激活引擎的代碼。

public void activeEngine(final View view) {
        if (!libraryExists) {
            Toast.makeText(this, "未找到庫文件!", Toast.LENGTH_SHORT).show();
            return;
        }
        if (!checkPermissions(NEEDED_PERMISSIONS)) {
            ActivityCompat.requestPermissions(this, NEEDED_PERMISSIONS, ACTION_REQUEST_PERMISSIONS);
            return;
        }
        if (view != null) {
            view.setClickable(false);
        }
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) {
                int activeCode = FaceEngine.activeOnline(MainActivity.this, Constants.APP_ID, Constants.SDK_KEY);
                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) {
                            Toast.makeText(MainActivity.this, "激活成功!", Toast.LENGTH_SHORT).show();
                        } else if (activeCode == ErrorInfo.MERR_ASF_ALREADY_ACTIVATED){
                            Toast.makeText(MainActivity.this, "已激活!", Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(MainActivity.this, "激活失??!", Toast.LENGTH_SHORT).show();
                        }

                        if (view != null) {
                            view.setClickable(true);
                        }
                        ActiveFileInfo activeFileInfo = new ActiveFileInfo();
                    }

                    @Override
                    public void onError(Throwable e) {
                        Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
                        if (view != null) {
                            view.setClickable(true);
                        }
                    }

                    @Override
                    public void onComplete() {

                    }
                });

    }

12、人臉識別界面是最復雜的。其中不僅有人臉識別的功能,還有注冊人臉和活體檢測的功能。

通過手機自帶的攝像頭來實現人臉識別和活體檢測的邏輯:

private void initCamera() {
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);

        final FaceListener faceListener = new FaceListener() {
            @Override
            public void onFail(Exception e) {
                Log.e(TAG, "onFail: " + e.getMessage());
            }

            //請求FR的回調
            @Override
            public void onFaceFeatureInfoGet(@Nullable final FaceFeature faceFeature, final Integer requestId, final Integer errorCode) {
                //FR成功
                if (faceFeature != null) {
//                    Log.i(TAG, "onPreview: fr end = " + System.currentTimeMillis() + " trackId = " + requestId);
                    Integer liveness = livenessMap.get(requestId);
                    //不做活體檢測的情況,直接搜索
                    if (!livenessDetect) {
                        searchFace(faceFeature, requestId);
                    }
                    //活體檢測通過,搜索特征
                    else if (liveness != null && liveness == LivenessInfo.ALIVE) {
                        searchFace(faceFeature, requestId);
                    }
                    //活體檢測未出結果,或者非活體,延遲執(zhí)行該函數
                    else {
                        if (requestFeatureStatusMap.containsKey(requestId)) {
                            Observable.timer(WAIT_LIVENESS_INTERVAL, TimeUnit.MILLISECONDS)
                                    .subscribe(new Observer<Long>() {
                                        Disposable disposable;

                                        @Override
                                        public void onSubscribe(Disposable d) {
                                            disposable = d;
                                            getFeatureDelayedDisposables.add(disposable);
                                        }

                                        @Override
                                        public void onNext(Long aLong) {
                                            onFaceFeatureInfoGet(faceFeature, requestId, errorCode);
                                        }

                                        @Override
                                        public void onError(Throwable e) {

                                        }

                                        @Override
                                        public void onComplete() {
                                            getFeatureDelayedDisposables.remove(disposable);
                                        }
                                    });
                        }
                    }

                }
                //特征提取失敗
                else {
                    if (increaseAndGetValue(extractErrorRetryMap, requestId) > MAX_RETRY_TIME) {
                        extractErrorRetryMap.put(requestId, 0);

                        String msg;
                        // 傳入的FaceInfo在指定的圖像上無法解析人臉,此處使用的是RGB人臉數據,一般是人臉模糊
                        if (errorCode != null && errorCode == ErrorInfo.MERR_FSDK_FACEFEATURE_LOW_CONFIDENCE_LEVEL) {
                            msg = "人臉置信度低!";
                        } else {
                            msg = "ExtractCode:" + errorCode;
                        }
                        faceHelper.setName(requestId, "未通過!");
                        // 在嘗試最大次數后,特征提取仍然失敗,則認為識別未通過
                        requestFeatureStatusMap.put(requestId, RequestFeatureStatus.FAILED);
                        retryRecognizeDelayed(requestId);
                    } else {
                        requestFeatureStatusMap.put(requestId, RequestFeatureStatus.TO_RETRY);
                    }
                }
            }

            @Override
            public void onFaceLivenessInfoGet(@Nullable LivenessInfo livenessInfo, final Integer requestId, Integer errorCode) {
                if (livenessInfo != null) {
                    int liveness = livenessInfo.getLiveness();
                    livenessMap.put(requestId, liveness);
                    // 非活體,重試
                    if (liveness == LivenessInfo.NOT_ALIVE) {
                        faceHelper.setName(requestId, "未通過!非活體!");
                        // 延遲 FAIL_RETRY_INTERVAL 后,將該人臉狀態(tài)置為UNKNOWN,幀回調處理時會重新進行活體檢測
                        retryLivenessDetectDelayed(requestId);
                    }
                } else {
                    if (increaseAndGetValue(livenessErrorRetryMap, requestId) > MAX_RETRY_TIME) {
                        livenessErrorRetryMap.put(requestId, 0);
                        String msg;
                        // 傳入的FaceInfo在指定的圖像上無法解析人臉,此處使用的是RGB人臉數據,一般是人臉模糊
                        if (errorCode != null && errorCode == ErrorInfo.MERR_FSDK_FACEFEATURE_LOW_CONFIDENCE_LEVEL) {
                            msg = "人臉置信度低!";
                        } else {
                            msg = "ProcessCode:" + errorCode;
                        }
                        faceHelper.setName(requestId, "未通過!");
                        retryLivenessDetectDelayed(requestId);
                    } else {
                        livenessMap.put(requestId, LivenessInfo.UNKNOWN);
                    }
                }
            }


        };


        CameraListener cameraListener = new CameraListener() {
            @Override
            public void onCameraOpened(Camera camera, int cameraId, int displayOrientation, boolean isMirror) {
                Camera.Size lastPreviewSize = previewSize;
                previewSize = camera.getParameters().getPreviewSize();
                drawHelper = new DrawHelper(previewSize.width, previewSize.height, previewView.getWidth(), previewView.getHeight(), displayOrientation
                        , cameraId, isMirror, false, false);
                Log.i(TAG, "onCameraOpened: " + drawHelper.toString());
                // 切換相機的時候可能會導致預覽尺寸發(fā)生變化
                if (faceHelper == null ||
                        lastPreviewSize == null ||
                        lastPreviewSize.width != previewSize.width || lastPreviewSize.height != previewSize.height) {
                    Integer trackedFaceCount = null;
                    // 記錄切換時的人臉序號
                    if (faceHelper != null) {
                        trackedFaceCount = faceHelper.getTrackedFaceCount();
                        faceHelper.release();
                    }
                    faceHelper = new FaceHelper.Builder()
                            .ftEngine(ftEngine)
                            .frEngine(frEngine)
                            .flEngine(flEngine)
                            .frQueueSize(MAX_DETECT_NUM)
                            .flQueueSize(MAX_DETECT_NUM)
                            .previewSize(previewSize)
                            .faceListener(faceListener)
                            .trackedFaceCount(trackedFaceCount == null ? ConfigUtil.getTrackedFaceCount(FaceRegisterAndRecognise.this.getApplicationContext()) : trackedFaceCount)
                            .build();
                }
            }


            @Override
            public void onPreview(final byte[] nv21, Camera camera) {
                if (faceRectView != null) {
                    faceRectView.clearFaceInfo();
                }
                List<FacePreviewInfo> facePreviewInfoList = faceHelper.onPreviewFrame(nv21);
                if (facePreviewInfoList != null && faceRectView != null && drawHelper != null) {
                    drawPreviewInfo(facePreviewInfoList);
                }
                registerFace(nv21, facePreviewInfoList);
                clearLeftFace(facePreviewInfoList);

                if (facePreviewInfoList != null && facePreviewInfoList.size() > 0 && previewSize != null) {
                    for (int i = 0; i < facePreviewInfoList.size(); i++) {
                        Integer status = requestFeatureStatusMap.get(facePreviewInfoList.get(i).getTrackId());
                        /**
                         * 在活體檢測開啟,在人臉識別狀態(tài)不為成功或人臉活體狀態(tài)不為處理中(ANALYZING)且不為處理完成(ALIVE、NOT_ALIVE)時重新進行活體檢測
                         */
                        if (livenessDetect && (status == null || status != RequestFeatureStatus.SUCCEED)) {
                            Integer liveness = livenessMap.get(facePreviewInfoList.get(i).getTrackId());
                            if (liveness == null
                                    || (liveness != LivenessInfo.ALIVE && liveness != LivenessInfo.NOT_ALIVE && liveness != RequestLivenessStatus.ANALYZING)) {
                                livenessMap.put(facePreviewInfoList.get(i).getTrackId(), RequestLivenessStatus.ANALYZING);
                                faceHelper.requestFaceLiveness(nv21, facePreviewInfoList.get(i).getFaceInfo(), previewSize.width, previewSize.height, FaceEngine.CP_PAF_NV21, facePreviewInfoList.get(i).getTrackId(), LivenessType.RGB);
                            }
                        }
                        /**
                         * 對于每個人臉,若狀態(tài)為空或者為失敗,則請求特征提?。筛鶕枰砑悠渌袛嘁韵拗铺卣魈崛〈螖担?,
                         * 特征提取回傳的人臉特征結果在{@link FaceListener#onFaceFeatureInfoGet(FaceFeature, Integer, Integer)}中回傳
                         */
                        if (status == null
                                || status == RequestFeatureStatus.TO_RETRY) {
                            requestFeatureStatusMap.put(facePreviewInfoList.get(i).getTrackId(), RequestFeatureStatus.SEARCHING);
                            faceHelper.requestFaceFeature(nv21, facePreviewInfoList.get(i).getFaceInfo(), previewSize.width, previewSize.height, FaceEngine.CP_PAF_NV21, facePreviewInfoList.get(i).getTrackId());
//                            Log.i(TAG, "onPreview: fr start = " + System.currentTimeMillis() + " trackId = " + facePreviewInfoList.get(i).getTrackedFaceCount());
                        }
                    }
                }
            }

            @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(getWindowManager().getDefaultDisplay().getRotation())
                .specificCameraId(rgbCameraID != null ? rgbCameraID : Camera.CameraInfo.CAMERA_FACING_FRONT)
                .isMirror(false)
                .previewOn(previewView)
                .cameraListener(cameraListener)
                .build();
        cameraHelper.init();
        cameraHelper.start();
    }

注冊人臉的邏輯:

private void registerFace(final byte[] nv21, final List<FacePreviewInfo> facePreviewInfoList) {
        if (registerStatus == REGISTER_STATUS_READY && facePreviewInfoList != null && facePreviewInfoList.size() > 0) {
            registerStatus = REGISTER_STATUS_PROCESSING;
            Observable.create(new ObservableOnSubscribe<Boolean>() {
                @Override
                public void subscribe(ObservableEmitter<Boolean> emitter) {

                    boolean success = FaceServer.getInstance().registerNv21(FaceRegisterAndRecognise.this, nv21.clone(), previewSize.width, previewSize.height,
                            facePreviewInfoList.get(0).getFaceInfo(), "registered " + faceHelper.getTrackedFaceCount());
                    emitter.onNext(success);
                }
            })
                    .subscribeOn(Schedulers.computation())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Observer<Boolean>() {
                        @Override
                        public void onSubscribe(Disposable d) {

                        }

                        @Override
                        public void onNext(Boolean success) {
                            String result = success ? "register success!" : "register failed!";
                            showToast(result);
                            registerStatus = REGISTER_STATUS_DONE;
                        }

                        @Override
                        public void onError(Throwable e) {
                            e.printStackTrace();
                            showToast("register failed!");
                            registerStatus = REGISTER_STATUS_DONE;
                        }

                        @Override
                        public void onComplete() {

                        }
                    });
        }
    }

13、人臉庫的管理界面。

public class FaceLibs extends BaseActivity {
    private ExecutorService executorService;
    private TextView textView;

    private TextView tvNotificationRegisterResult;

    ProgressDialog progressDialog = null;
    private static final int ACTION_REQUEST_PERMISSIONS = 0x001;
    private static String[] NEEDED_PERMISSIONS = new String[]{
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_face_libs);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        executorService = Executors.newSingleThreadExecutor();
        tvNotificationRegisterResult = findViewById(R.id.notification_register_result);
        progressDialog = new ProgressDialog(this);
        int faceLibNum = FaceServer.getInstance().getFaceNumber(this);
        textView = findViewById(R.id.number);
        textView.setText(faceLibNum + "");
        FaceServer.getInstance().init(this);
    }

    @Override
    protected void onDestroy() {
        if (executorService != null && !executorService.isShutdown()) {
            executorService.shutdownNow();
        }
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
        }

        FaceServer.getInstance().unInit();
        super.onDestroy();
    }

    @Override
    void afterRequestPermission(int requestCode, boolean isAllGranted) {

    }

    public void clearFaces(View view) {
        int faceNum = FaceServer.getInstance().getFaceNumber(this);
        if (faceNum == 0) {
            showToast("人臉庫已空!");
        } else {
            AlertDialog dialog = new AlertDialog.Builder(this)
                    .setTitle("通知")
                    .setMessage("確定要刪除" + faceNum + "個人臉嗎?")
                    .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            int deleteCount = FaceServer.getInstance().clearAllFaces(FaceLibs.this);
                            showToast(deleteCount + "個人臉已刪除!");
                            textView.setText("0");
                        }
                    })
                    .setNegativeButton("取消", null)
                    .create();
            dialog.show();
        }
    }
}

14、以上就是大體的介紹,還有一些小的細枝末節(jié)需要同志們動手實操一下。下面就來看看實現的效果。

主界面:

在這里插入圖片描述

注冊成功并通過識別:

在這里插入圖片描述

通過手機照片識別出不是活體:

在這里插入圖片描述

清理人臉庫:

在這里插入圖片描述

以上就是Android基于虹軟(ArcSoft)實現人臉識別的詳細內容,更多關于Android人臉識別的資料請關注腳本之家其它相關文章!

相關文章

  • Android開發(fā)中關于組件導出的風險及防范

    Android開發(fā)中關于組件導出的風險及防范

    這篇文章主要介紹了Android開發(fā)中關于組件導出的風險及防范,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • RecyclerView下拉刷新上拉加載

    RecyclerView下拉刷新上拉加載

    本文主要介紹了RecyclerView下拉刷新上拉加載的具體實現代碼,具有一定的參考價值,下面跟著小編一起來看下吧
    2017-01-01
  • 一看就懂的Android APP開發(fā)入門教程

    一看就懂的Android APP開發(fā)入門教程

    這篇文章主要介紹了Android APP開發(fā)入門教程,從SDK下載、開發(fā)環(huán)境搭建、代碼編寫、APP打包等步驟一一講解,非常簡明的一個Android APP開發(fā)入門教程,需要的朋友可以參考下
    2014-05-05
  • Android-Service實現手機壁紙自動更換

    Android-Service實現手機壁紙自動更換

    這篇文章主要為大家詳細介紹了Android-Service實現手機壁紙自動更換,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • Android自定義控件RatingBar調整字體大小

    Android自定義控件RatingBar調整字體大小

    這篇文章主要為大家詳細介紹了Android自定義控件RatingBar調整字體大小的相關資料,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • Android studio 引用aar 進行java開發(fā)的操作步驟

    Android studio 引用aar 進行java開發(fā)的操作步驟

    這篇文章主要介紹了Android studio 引用aar 進行java開發(fā)的操作步驟,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-09-09
  • Android仿微信實現首字母導航條

    Android仿微信實現首字母導航條

    這篇文章主要為大家詳細介紹了Android仿微信實現首字母導航條的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-08-08
  • android不讀入內存獲取圖像寬高信息的方法

    android不讀入內存獲取圖像寬高信息的方法

    這篇文章主要介紹了android不讀入內存獲取圖像寬高信息的方法,涉及Android獲取圖像信息的相關技巧,需要的朋友可以參考下
    2015-04-04
  • Android學習筆記-保存文件(Saving Files)

    Android學習筆記-保存文件(Saving Files)

    這篇文章主要介紹了Android中保存文件(Saving Files)的方法,需要的朋友可以參考下
    2014-10-10
  • android?studio實現簡單的計算器小功能

    android?studio實現簡單的計算器小功能

    這篇文章主要為大家詳細介紹了android?studio實現簡單的計算器小功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05

最新評論