人臉識別


最近在做一款商戶入網的應用,為防止不法商戶對公司渠道的接入,公司加大了對商戶的審核,人臉識別就是其中的一項。人臉識別的第一步是檢測商戶的張嘴動作,通過之后采集照片,上傳到服務器。第二步是檢測商戶的搖頭動作,通過之后采集照片,上傳到服務器。至此完成人臉識別。下面我對主干代碼進行分析:

首先導入jar包Msc(訊飛)。檢測人臉關鍵部位的坐標

private void setFaceDetection() {
        mThread = new Thread(new Runnable() {
            @Override
            public void run() {
                List<Object> previewDate = CameraInterface.getInstance()
                        .getPreviewDate();
                buffer = (byte[]) previewDate.get(0);
                nv21 = (byte[]) previewDate.get(1);
                while (!mStopTrack) {
                    if (null == nv21) {
                        continue;
                    }
                    synchronized (nv21) {
                        System.arraycopy(nv21, 0, buffer, 0, nv21.length);
                    }
                    // 獲取手機朝向,返回值0,1,2,3分別表示0,90,180和270度
                    int direction = Accelerometer.getDirection();
                    boolean frontCamera = (Camera.CameraInfo.CAMERA_FACING_FRONT == mCameraId);
                    // 前置攝像頭預覽顯示的是鏡像,需要將手機朝向換算成攝相頭視角下的朝向。
                    // 轉換公式:a' = (360 - a)%360,a為人眼視角下的朝向(單位:角度)
                    if (frontCamera) {
                        // SDK中使用0,1,2,3,4分別表示0,90,180,270和360度
                        direction = (4 - direction) % 4;
                    }
                    if (mFaceDetector == null) {
                        /**
                         * 離線視頻流檢測功能需要單獨下載支持離線人臉的SDK 請開發者前往語音雲官網下載對應SDK
                         */
                        ShowToast.showToast(getActivity(), "本SDK不支持離線視頻流檢測");
                        break;
                    }

                    String result = mFaceDetector.trackNV21(buffer,
                            PREVIEW_WIDTH, PREVIEW_HEIGHT, isAlign, direction);

                    FaceRect[] faces = ParseResult.parseResult(result);

                    drawRect(frontCamera, faces);

                }
            }

對人臉動作的檢測

if (isFace) {
                        // 進行活體檢測
                        if (rectLength >= 160 && rectLength < 180) {
                            // 判斷張嘴后進行拍照
                            if (mouth_bt >= 40 && !isOpenMouth) {
                                isOpenMouth = true;
                                isShakeHead = true;
                                mHandler.sendEmptyMessageDelayed(
                                        StaticArguments.FACE_OPEN_MOUTH, 1000);
                            }
                            // 進行搖頭判斷
                            if (eyebrow_mlr_y < 79 && eyebrow_mlr_y >= 0
                                    && isShakeHead) {
                                isOpenMouth = true;

                                countHead++;
                                if (countHead % 2 == 0) {
                                    mHandler.sendEmptyMessageDelayed(
                                            StaticArguments.FACE_SHAKE_HEAD,
                                            3000);
                                }
                            }

                        } else if (rectLength >= 180 && rectLength < 200) {
                            // 判斷張嘴后進行拍照
                            if (mouth_bt >= 45 && !isOpenMouth) {
                                isShakeHead = true;
                                isOpenMouth = true;
                                mHandler.sendEmptyMessageDelayed(
                                        StaticArguments.FACE_OPEN_MOUTH, 1000);
                            }
                            // 進行搖頭判斷
                            if (eyebrow_mlr_y < 89 && eyebrow_mlr_y >= 0
                                    && isShakeHead) {
                                isOpenMouth = true;

                                countHead++;
                                if (countHead % 2 == 0) {
                                    mHandler.sendEmptyMessageDelayed(
                                            StaticArguments.FACE_SHAKE_HEAD,
                                            1000);
                                }
                            }
                        } else if (rectLength >= 200 && rectLength < 340) {
                            // 判斷張嘴后進行拍照
                            if (mouth_bt >= 50 && !isOpenMouth) {
                                isShakeHead = true;
                                isOpenMouth = true;
                                mHandler.sendEmptyMessageDelayed(
                                        StaticArguments.FACE_OPEN_MOUTH, 500);
                            }
                            // 進行搖頭判斷
                            if (eyebrow_mlr_y < 95 && eyebrow_mlr_y >= 0
                                    && isShakeHead) {
                                isOpenMouth = true;

                                countHead++;
                                if (countHead % 2 == 0) {
                                    mHandler.sendEmptyMessageDelayed(
                                            StaticArguments.FACE_SHAKE_HEAD,
                                            1000);
                                }
                            }
                        } else if (rectLength < 160) {// 檢測臉部離手機太遠
                            mHandler.sendEmptyMessage(StaticArguments.FACE_LENGTH_LONG);
                        } else if (rectLength >= 340 && rectLength >= 0) {// 檢測臉部離手機太近
                            mHandler.sendEmptyMessage(StaticArguments.FACE_LENGTH_NEAR);
                        }
}

人臉張嘴或者搖頭的動作后捕獲視頻的幀數據

public void doStartPreview(SurfaceHolder holder, float previewRate) {

        if (isPreview) {
            mCamera.stopPreview();
            return;
        }

        if (mCamera != null) {
            mParams = mCamera.getParameters();
            mParams.setPictureFormat(PixelFormat.JPEG);// 設置拍照后存儲的圖片格式
            // 設置PreviewSize和PictureSize
            mParams.setPreviewFormat(ImageFormat.NV21);
            mParams.setPreviewSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);
            mCamera.setParameters(mParams);
            mCamera.setDisplayOrientation(90);
            List<String> focusModes = mParams.getSupportedFocusModes();
            if (focusModes.contains("continuous-video")) {
                mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
            }
            mCamera.setPreviewCallback(new PreviewCallback() {
                @Override
                public void onPreviewFrame(byte[] data, Camera camera) {
                    System.arraycopy(data, 0, nv21, 0, data.length);
                    if (takePictureFlag == 1) {
                        Bitmap mBitmap = null;
                        Camera.Parameters parameters = camera.getParameters();
                        int format = parameters.getPreviewFormat();
                        if (format == PixelFormat.YCbCr_420_SP
                                || format == PixelFormat.YCbCr_422_I) {
                            int w = parameters.getPreviewSize().width;
                            int h = parameters.getPreviewSize().height;
                            int[] i = new int[data.length];
                            decodeYUV420SP(i, data, w, h);
                            mBitmap = Bitmap.createBitmap(i, w, h,
                                    Bitmap.Config.RGB_565);
                        } else if (format == PixelFormat.JPEG
                                || format == PixelFormat.RGB_565) {
                            mBitmap = BitmapFactory.decodeByteArray(data, 0,
                                    data.length);
                        }
                        if (null != mBitmap) {
                            if (takePictureFlag == 1) {
                                takePictureFlag++;
                            } else {
                                return;
                            }
                            // 設置FOCUS_MODE_CONTINUOUS_VIDEO)之后,myParam.set("rotation",
                            // 90)失效。
                            // 圖片竟然不能旋轉了,故這里要旋轉下
                            Bitmap rotateImage = FaceUtil.rotateImage(270,
                                    mBitmap);

                            if (mListener != null) {
                                mListener.onTakePictuerResult(rotateImage);
                            }
                        }
                    }
                }
            });

            try {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            isPreview = true;
        }

    }

源碼下載地址:

https://github.com/reachchen/FaceRecognition


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM