本篇博文记录如何使用Android的前置摄像头预览,并获取人脸部分,然后计算人脸区域的亮度,下面是程序运行截图:
下面上代码:
1、前置摄像头预览时需要用到的类CameraView:
复制代码
2、检测到人脸后将人脸区域画出来的FaceView类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259package test.com.getbright; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Point; import android.graphics.PointF; import android.hardware.Camera; import android.hardware.Camera.Size; import android.media.FaceDetector; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import java.io.IOException; import java.util.List; /** * Created by yubo on 2015/9/20. */ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback { private Context context; private Camera camera; private FaceView faceView; private OnFaceDetectedListener onFaceDetectedListener; /** * 摄像头最大的预览尺寸 */ private Size maxPreviewSize; /** * 预览时Frame的计数器 */ private int frameCount; /** * 是否正在检测人脸 */ private boolean isDetectingFace = false; /** * 是否已检测到人脸 */ private boolean detectedFace = false; public CameraView(Context context) { super(context); init(context); } public CameraView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } private void init(Context context) { this.context = context; getHolder().addCallback(this); } public void setFaceView(FaceView faceView) { if (faceView != null) { this.faceView = faceView; } } /** 摄像头重新开始预览 */ public void reset() { if(faceView != null) { faceView.setVisibility(View.GONE); } if(camera != null) { camera.setPreviewCallback(this); camera.startPreview(); } frameCount = 0; detectedFace = false; isDetectingFace = false; } @Override public void surfaceCreated(SurfaceHolder holder) { try { camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT); if(camera != null) { camera.setDisplayOrientation(90); camera.setPreviewDisplay(holder); camera.setPreviewCallback(this); } } catch (IOException e) { e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (camera != null) { maxPreviewSize = getMaxPreviewSize(camera); if (maxPreviewSize != null) { ViewGroup.LayoutParams params = getLayoutParams(); Point point = getScreenSize(); params.width = point.x; params.height = maxPreviewSize.width * point.x / maxPreviewSize.height; setLayoutParams(params); if(faceView != null) { faceView.setLayoutParams(params); } Camera.Parameters parameters = camera.getParameters(); parameters.setPreviewSize(maxPreviewSize.width, maxPreviewSize.height); camera.setParameters(parameters); } camera.startPreview(); frameCount = 0; detectedFace = false; } } @Override public void surfaceDestroyed(SurfaceHolder holder) { if (camera != null) { try { camera.stopPreview(); camera.setPreviewDisplay(null); camera.setPreviewCallback(null); camera.release(); camera = null; } catch (IOException e) { e.printStackTrace(); } } } /** * 获取手机屏幕的尺寸 * * @return */ private Point getScreenSize() { WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); manager.getDefaultDisplay().getMetrics(outMetrics); return new Point(outMetrics.widthPixels, outMetrics.heightPixels); } /** * 获取摄像头最大的预览尺寸 * * @param camera * @return */ private Size getMaxPreviewSize(Camera camera) { List<Size> list = camera.getParameters().getSupportedPreviewSizes(); if (list != null) { int max = 0; Size maxSize = null; for (Size size : list) { int n = size.width * size.height; if (n > max) { max = n; maxSize = size; } } return maxSize; } return null; } @Override public void onPreviewFrame(byte[] data, Camera camera) { Log.e("yubo", "onPreviewFrame..."); frameCount++; //前面15帧丢弃 if (frameCount > 15 && !isDetectingFace && !detectedFace) { Size size = camera.getParameters().getPreviewSize(); final byte[] byteArray = ImageUtils.yuv2Jpeg(data, size.width, size.height); isDetectingFace = true; new Thread() { @Override public void run() { detectFaces(byteArray); } }.start(); } } /** * 检测data数据中是否有人脸,这里需要先旋转一下图片,该方法执行在子线程中 * * @param data */ private void detectFaces(byte[] data) { Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); bitmap = ImageUtils.rotateBitmap(bitmap, -90); bitmap = bitmap.copy(Bitmap.Config.RGB_565, true); FaceDetectorUtils.detectFace(bitmap, new FaceDetectorUtils.Callback() { @Override public void onFaceDetected(final FaceDetector.Face[] faces, final Bitmap bm) { isDetectingFace = false; Log.e("yubo", "face detected..."); if (!detectedFace) { detectedFace = true; ((Activity) context).runOnUiThread(new Runnable() { @Override public void run() { if (camera != null) { camera.stopPreview(); } if (faceView != null) { float scaleRate = bm.getWidth() * 1.0f / getScreenSize().x; faceView.setScaleRate(scaleRate); faceView.setFaces(faces, bm); faceView.setVisibility(View.VISIBLE); } if (onFaceDetectedListener != null) { onFaceDetectedListener.onFaceDetected(bm); } } }); } } @Override public void onFaceNotDetected(Bitmap bm) { bm.recycle(); if (faceView != null) { faceView.clear(); } isDetectingFace = false; } }); } /** * 检测到人脸的监听器 */ public interface OnFaceDetectedListener { void onFaceDetected(Bitmap bm); } /** * 设置监听器,监听检测到人脸的动作 */ public void setOnFaceDetectedListener(OnFaceDetectedListener listener) { if (listener != null) { this.onFaceDetectedListener = listener; } } }
复制代码
3、人脸检测的工具类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140package test.com.getbright; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PointF; import android.media.FaceDetector; import android.util.AttributeSet; import android.util.Log; import android.widget.ImageView; /** * Created by yubo on 2015/9/5. * 画人脸区域的View */ public class FaceView extends ImageView { private FaceDetector.Face[] faces; private Paint paint; private Bitmap bitmap; private float left; private float top; private float right; private float bottom; private int x; private int y; private int width; public FaceView(Context context) { super(context); init(context); } public FaceView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public FaceView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private void init(Context context) { paint = new Paint(); paint.setColor(Color.GREEN); paint.setStrokeWidth(5); paint.setStyle(Paint.Style.STROKE);//设置话出的是空心方框而不是实心方块 } public void setFaces(FaceDetector.Face[] faces, Bitmap bitmap) { if(faces != null && faces.length > 0) { Log.e("yubo", "FaceView setFaces, face size = " + faces.length); this.faces = faces; this.bitmap = bitmap; setImageBitmap(bitmap); calculateFaceArea(); invalidate(); }else{ Log.e("yubo", "FaceView setFaces, faces == null"); } } /** 计算人脸区域 */ private void calculateFaceArea(){ float eyesDistance = 0;//两眼间距 for(int i = 0; i < faces.length; i++){ FaceDetector.Face face = faces[i]; if(face != null){ PointF pointF = new PointF(); face.getMidPoint(pointF);//获取人脸中心点 eyesDistance = face.eyesDistance();//获取人脸两眼的间距 //计算人脸的区域 float delta = eyesDistance / 2; left = (pointF.x - eyesDistance) / scaleRate; top = (pointF.y - eyesDistance + delta) / scaleRate; right = (pointF.x + eyesDistance) / scaleRate; bottom = (pointF.y + eyesDistance + delta) / scaleRate; x = (int) (pointF.x - eyesDistance); y = (int) (pointF.y - eyesDistance + delta); width = (int) (eyesDistance * 2); } } } private float scaleRate = 1.0f; public void setScaleRate(float rate) { this.scaleRate = rate; } /** 清除数据 */ public void clear(){ this.faces = null; postInvalidate(); } /** 获取人脸区域,适当扩大了一点人脸区域 */ public Bitmap getFaceArea(){ if(this.bitmap != null) { int bmWidth = bitmap.getWidth(); int bmHeight = bitmap.getHeight(); int delta = 50; width += 50; int height = width; x = (int) (left - delta); y = (int) (top - delta); if(x < 0) { x = 0; } if(y < 0) { y = 0; } if(width > bmWidth) { width = bmWidth; } if(height > bmHeight) { height = bmHeight; } return Bitmap.createBitmap(bitmap, x, y, width, height); } return null; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if(this.faces == null || faces.length == 0) { return ; } canvas.drawRect(left, top, right, bottom, paint); } }
复制代码
4、处理图像的工具类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49package test.com.getbright; import android.graphics.Bitmap; import android.media.FaceDetector; import android.media.FaceDetector.Face; /** * Created by yubo on 2015/9/5. * 人脸检测工具类 */ public class FaceDetectorUtils { private static FaceDetector faceDetector; private FaceDetectorUtils(){ } public interface Callback{ void onFaceDetected(Face[] faces, Bitmap bitmap); void onFaceNotDetected(Bitmap bitmap); } /** * 检测bitmap中的人脸,在callback中返回人脸数据 * @param bitmap * @param callback */ public static void detectFace(Bitmap bitmap, Callback callback){ try { faceDetector = new FaceDetector(bitmap.getWidth(), bitmap.getHeight(), 1); Face[] faces = new Face[1]; int faceNum = faceDetector.findFaces(bitmap, faces); if(faceNum > 0) { if(callback != null) { callback.onFaceDetected(faces, bitmap); } }else{ if(callback != null) { callback.onFaceNotDetected(bitmap); bitmap.recycle(); } } } catch (Exception e) { e.printStackTrace(); } } }
复制代码
5、最后是布局文件和主Activity代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51package test.com.getbright; import android.graphics.Bitmap; import android.graphics.ImageFormat; import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.YuvImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; /** * Created by yubo on 2015/8/31. * 图像处理的工具类 */ public class ImageUtils { /** 将yuv数据转换为jpeg */ public static byte[] yuv2Jpeg(byte[] yuvBytes, int width, int height) { YuvImage yuvImage = new YuvImage(yuvBytes, ImageFormat.NV21, width, height, null); ByteArrayOutputStream baos = new ByteArrayOutputStream(); yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, baos); return baos.toByteArray(); } /** 旋转图像 */ public static Bitmap rotateBitmap(Bitmap sourceBitmap, int degree) { Matrix matrix = new Matrix(); //旋转90度,并做镜面翻转 matrix.setRotate(degree); matrix.postScale(-1, 1); return Bitmap.createBitmap(sourceBitmap, 0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight(), matrix, true); } /** 保存bitmap到文件 */ public static void saveBitmap(Bitmap bitmap, String path) { if(bitmap != null) { try { bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(new File(path))); } catch (FileNotFoundException e) { e.printStackTrace(); } } } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:background="@color/black"> <test.com.getbright.CameraView android:id="@+id/camera_view" android:layout_gravity="center" android:layout_width="match_parent" android:layout_height="wrap_content"/> <test.com.getbright.FaceView android:id="@+id/face_view" android:layout_gravity="center" android:visibility="gone" android:layout_width="match_parent" android:layout_height="wrap_content"/> </FrameLayout>
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141package test.com.getbright; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.graphics.Bitmap; import android.hardware.Camera; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { CameraView cameraView; FaceView faceView; Bitmap fullBitmap; private SensorManager sensorManager; private Sensor sensor; private MySensorListener mySensorListener; private int sensorBright = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if(!hasFrontCamera()) { Toast.makeText(this, "没有前置摄像头", Toast.LENGTH_SHORT).show(); return ; } sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); mySensorListener = new MySensorListener(); sensorManager.registerListener(mySensorListener, sensor, SensorManager.SENSOR_DELAY_NORMAL); initView(); } private void initView(){ cameraView = (CameraView) findViewById(R.id.camera_view); faceView = (FaceView) findViewById(R.id.face_view); cameraView.setFaceView(faceView); cameraView.setOnFaceDetectedListener(new CameraView.OnFaceDetectedListener() { @Override public void onFaceDetected(Bitmap bm) { //检测到人脸后的回调方法 fullBitmap = bm; showDialog(); } }); } private class MySensorListener implements SensorEventListener { @Override public void onSensorChanged(SensorEvent sensorEvent) { //光线传感器亮度改变 sensorBright = (int) sensorEvent.values[0]; } @Override public void onAccuracyChanged(Sensor sensor, int i) { } } private void showDialog(){ AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("计算结果"); View contentView = LayoutInflater.from(this).inflate(R.layout.pop_win_layout, null); ImageView imageView = (ImageView) contentView.findViewById(R.id.imageview); TextView textView = (TextView) contentView.findViewById(R.id.textview); builder.setView(contentView); Bitmap bm = faceView.getFaceArea(); imageView.setImageBitmap(bm); textView.setText("人脸区域亮度:" + getBright(bm) + "n整幅图片亮度:" + getBright(fullBitmap) + "n光线传感器的值:" + sensorBright); builder.setPositiveButton("确定", new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialogInterface, int i) { cameraView.reset(); } }); builder.setCancelable(false); builder.create().show(); } public int getBright(Bitmap bm) { int width = bm.getWidth(); int height = bm.getHeight(); int r, g, b; int count = 0; int bright = 0; for(int i = 0; i < width; i++) { for(int j = 0; j < height; j++) { count++; int localTemp = bm.getPixel(i, j); r = (localTemp | 0xff00ffff) >> 16 & 0x00ff; g = (localTemp | 0xffff00ff) >> 8 & 0x0000ff; b = (localTemp | 0xffffff00) & 0x0000ff; bright = (int) (bright + 0.299 * r + 0.587 * g + 0.114 * b); } } return bright / count; } /** * 判断是否有前置摄像 * @return */ @SuppressLint("NewApi") public static boolean hasFrontCamera(){ Camera.CameraInfo info = new Camera.CameraInfo(); int count = Camera.getNumberOfCameras(); for(int i = 0; i < count; i++){ Camera.getCameraInfo(i, info); if(info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT){ return true; } } return false; } @Override protected void onDestroy() { super.onDestroy(); sensorManager.unregisterListener(mySensorListener); } }
代码下载点这里
最后
以上就是怡然汽车最近收集整理的关于Android前置摄像头预览并检测人脸,获取人脸区域亮度的全部内容,更多相关Android前置摄像头预览并检测人脸内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复