1. 程式人生 > >android 通過原生api(不需要opencv和第三方sdk)實現Camera人臉檢測

android 通過原生api(不需要opencv和第三方sdk)實現Camera人臉檢測

浪費了“黃金五年”的Java程式設計師,還有救嗎? >>>   

支援技術分享,轉載或複製,請指出文章來源 此部落格作者為Jack__0023

1、背景

最近甲方提出個東西,希望能夠檢測到是否有人觀看過我們投放的內容,那麼這種的話,在我看來只需要能粗糙檢測到人就可以了,那麼也就不需要去使用opencv或者第三方SDK,直接使用Camera自帶的提供檢測功能即可。

bak:人臉檢測不是人臉識別,識別還要對比,檢測只是看看有沒有人。

2、簡介和程式碼區

2-1、簡介區域
2-1-1、提供檢測的類:其實原始碼裡面已經有提供檢測的類 android.media.FaceDetector(可以看原始碼或者自行百度一下)
2-1-2、注意事項:
2-1-2-1、android.media.FaceDetector 好像對檢查的圖片格式有要求,只能檢測 RGB_565 格式的圖片,所以如果沒效果,注意是不是沒注意格式
2-1-2-2、我是基於android 5.1的版本的,別的版本我沒去測試,如果效果不好的話可以私信我
2-1-2-3、我是在 onPreviewFrame 方法裡面實現的 (小字型的是幀數設定的方式)

如果嫌 幀數過多,你可以通過 Camera.Parameters 類的 getSupportedPreviewFpsRange() 方法

獲取每秒的獲取幀數區間(下面會有貼程式碼的),然後通過 Camera.Parameters 類的 setPreviewFpsRange() 方法 設定幀數區間,(setPreviewFrameRate 方法官方已經不建議使用了),可以看看 setPreviewFpsRange 說了什麼

/**
         * Sets the minimum and maximum preview fps. This controls the rate of
         * preview frames received in {[@link](https://my.oschina.net/u/393) PreviewCallback}. The minimum and
         * maximum preview fps must be one of the elements from {[@link](https://my.oschina.net/u/393)
         * #getSupportedPreviewFpsRange}.
         *
         * [@param](https://my.oschina.net/u/2303379) min the minimum preview fps (scaled by 1000).
         * [@param](https://my.oschina.net/u/2303379) max the maximum preview fps (scaled by 1000).
         * [@throws](https://my.oschina.net/throws) RuntimeException if fps range is invalid.
         * @see #setPreviewCallbackWithBuffer(Camera.PreviewCallback)
         * @see #getSupportedPreviewFpsRange()
         */
        public void setPreviewFpsRange(int min, int max) {
            set(KEY_PREVIEW_FPS_RANGE, "" + min + "," + max);
        }
大概的意思就是 設定最小和最大預覽fps。這可以控制{@link PreviewCallback}中收到的預覽幀的速率。最小和最大預覽fps必須是{@ link#getSupportedPreviewFpsRange}中的元素之一。
比如想設定每秒為1到3,那麼你要填入的是最小值1000和最大值3000(沒錯,數量*1000),雖然我 getSupportedPreviewFpsRange 裡面是15000到20000,但是我設定為最大值最小值是3000,結果每秒是5張(也算滿意吧)
2-2、程式碼區域
2-2-1、 幀數檢查和設定區域
WindowManager manager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
            Display display = manager.getDefaultDisplay();
            Camera.Parameters param = mCamera.getParameters();
            param.setPreviewSize(640, 480);
            //幀數設定區域
            param.setPreviewFpsRange(1000, 3000);
            List<int[]> range = param.getSupportedPreviewFpsRange();
            Log.d("zhaojing", "range:" + range.size());
            //幀數檢查,一般會有2個值,第一個是最小,第二個是最大,你這裡可以修改一下程式碼就好了
            for (int j = 0; j < range.size(); j++) {
                int[] r = range.get(j);
                for (int k = 0; k < r.length; k++) {
                    Log.d("zhaojing", "r["+k+"]:"+r[k]);
                }
            }
2-2-2、 人臉檢測區域 (這段程式碼可以繼續優化的,例如每秒5幀,你可以再進行運算變成3幀之內,還有其他的效能優化,程式碼優化,這段是我寫來測試的,就沒注意很多)
@Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        count++;
//        Log.v("yaoxumin123456789", "onPreviewFrame| 來了" + count);
        mCamera.addCallbackBuffer(data);
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        newOpts.inJustDecodeBounds = true;
        YuvImage yuvimage = new YuvImage(data, ImageFormat.NV21, 640, 480, null);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        yuvimage.compressToJpeg(new Rect(0, 0, 640, 480), 100, baos);// 80--JPG圖片的質量[0-100],100最高
        byte[] rawImage = baos.toByteArray();
        //將rawImage轉換成bitmap
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        Bitmap bitmap = BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length, options);
        //只有565格式才能被識別,這裡進行人臉檢測
        Bitmap tmpBmp = bitmap.copy(Bitmap.Config.RGB_565, true);
        FaceDetector faceDet = new FaceDetector(tmpBmp.getWidth(), tmpBmp.getHeight(), 10);
        //用來填裝人臉的個數
        FaceDetector.Face[] faceList = new FaceDetector.Face[10];
        int faceNumber = faceDet.findFaces(tmpBmp, faceList);
        if (faceNumber > 0) {//識別到人臉了,該怎麼做就看你的了少年
            Log.v("yaoxumin", "識別到的人的數量為:" + faceNumber);
        }
    }

效果如圖

基本上重要程式碼就在上面(人臉檢測區域 )了,有問題