android 通過原生api(不需要opencv和第三方sdk)實現Camera人臉檢測
阿新 • • 發佈:2019-03-02
支援技術分享,轉載或複製,請指出文章來源 此部落格作者為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() 方法
/** * 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);
}
}