【移动应用开发技术】Android中怎么实现动态人脸检测_第1页
【移动应用开发技术】Android中怎么实现动态人脸检测_第2页
【移动应用开发技术】Android中怎么实现动态人脸检测_第3页
【移动应用开发技术】Android中怎么实现动态人脸检测_第4页
【移动应用开发技术】Android中怎么实现动态人脸检测_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】Android中怎么实现动态人脸检测

Android中怎么实现动态人脸检测,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。第一步我们首先来定义一个surfaceview盖在我们Carmen使用的surfaceview上进行对人脸范围的绘制public

class

FindFaceView

extends

SurfaceView

implements

SurfaceHolder.Callback

{

private

SurfaceHolder

holder;

private

int

mWidth;

private

int

mHeight;

private

float

eyesDistance;

public

FindFaceView(Context

context,

AttributeSet

attrs)

{

super(context,

attrs);

holder

=

getHolder();

holder.addCallback(this);

holder.setFormat(PixelFormat.TRANSPARENT);

this.setZOrderOnTop(true);

}

@Override

public

void

surfaceChanged(SurfaceHolder

holder,

int

format,

int

width,

int

height)

{

mWidth

=

width;

mHeight

=

height;

}

@Override

public

void

surfaceCreated(SurfaceHolder

holder)

{

}

@Override

public

void

surfaceDestroyed(SurfaceHolder

holder)

{

}

public

void

drawRect(FaceDetector.Face[]

faces,

int

numberOfFaceDetected)

{

Canvas

canvas

=

holder.lockCanvas();

if

(canvas

!=

null)

{

Paint

clipPaint

=

new

Paint();

clipPaint.setAntiAlias(true);

clipPaint.setStyle(Paint.Style.STROKE);

clipPaint

.setXfermode(new

PorterDuffXfermode(PorterDuff.Mode.CLEAR));

canvas.drawPaint(clipPaint);

canvas.drawColor(getResources().getColor(color.transparent));

Paint

paint

=

new

Paint();

paint.setAntiAlias(true);

paint.setColor(Color.GREEN);

paint.setStyle(Style.STROKE);

paint.setStrokeWidth(5.0f);

for

(int

i

=

0;

i

<

numberOfFaceDetected;

i++)

{

Face

face

=

faces[i];

PointF

midPoint

=

new

PointF();

//

获得两眼之间的中间点

face.getMidPoint(midPoint);

//

获得两眼之间的距离

eyesDistance

=

face.eyesDistance();

//

换算出预览图片和屏幕显示区域的比例参数

float

scale_x

=

mWidth

/

500;

float

scale_y

=

mHeight

/

600;

Log.e("eyesDistance=",

eyesDistance

+

"");

Log.e("midPoint.x=",

midPoint.x

+

"");

Log.e("midPoint.y=",

midPoint.y

+

"");

//

因为拍摄的相片跟实际显示的图像是镜像关系,所以在图片上获取的两眼中间点跟手机上显示的是相反方向

canvas.drawRect((int)

(240

-

midPoint.x

-

eyesDistance)

*

scale_x,

(int)

(midPoint.y

*

scale_y),

(int)

(240

-

midPoint.x

+

eyesDistance)

*

scale_x,

(int)

(midPoint.y

+

3

*

eyesDistance)

*

scale_y,

paint);

}

holder.unlockCanvasAndPost(canvas);

}

}

}重要的地方1.holder=getHolder();获取surfaceholder与我们要绘制人脸范围的画布进行绑定Canvascanvas=holder.lockCanvas();这样我们就可以愉快的进行绘制了,当然前提是我们要拿到人脸的坐标位置。2.还有重要的一点,就是要让我们用来盖在Carema上的Surfaceview可以同名,并且设置起在视图树的层级为最高。

holder.setFormat(PixelFormat.TRANSPARENT);

this.setZOrderOnTop(true);第二步就是我们对人脸进行检测了,当然前提是我们要获得帧图public

class

FaceRecognitionDemoActivity

extends

Activity

implements

OnClickListener

{

private

SurfaceView

preview;

private

Camera

camera;

private

Camera.Parameters

parameters;

private

int

orientionOfCamera;//

前置摄像头的安装角度

private

int

faceNumber;//

识别的人脸数

private

FaceDetector.Face[]

faces;

private

FindFaceView

mFindFaceView;

private

ImageView

iv_photo;

private

Button

bt_camera;

TextView

mTV;

/**

*

Called

when

the

activity

is

first

created.

*/

@Override

public

void

onCreate(Bundle

savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

}

@Override

protected

void

onStart()

{

super.onStart();

iv_photo

=

(ImageView)

findViewById(R.id.iv_photo);

bt_camera

=

(Button)

findViewById(R.id.bt_camera);

mTV

=

(TextView)

findViewById(R.id.show_count);

bt_camera.setOnClickListener(this);

mFindFaceView

=

(FindFaceView)

findViewById(R.id.my_preview);

preview

=

(SurfaceView)

findViewById(R.id.preview);

//

设置缓冲类型(必不可少)

preview.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

//

设置surface的分辨率

preview.getHolder().setFixedSize(176,

144);

//

设置屏幕常亮(必不可少)

preview.getHolder().setKeepScreenOn(true);

preview.getHolder().addCallback(new

SurfaceCallback());

}

private

final

class

MyPictureCallback

implements

PictureCallback

{

@Override

public

void

onPictureTaken(byte[]

data,

Camera

camera)

{

try

{

Bitmap

bitmap

=

BitmapFactory.decodeByteArray(data,

0,

data.length);

Matrix

matrix

=

new

Matrix();

matrix.setRotate(-90);

Bitmap

bmp

=

Bitmap.createBitmap(bitmap,

0,

0,

bitmap

.getWidth(),

bitmap.getHeight(),

matrix,

true);

bitmap.recycle();

iv_photo.setImageBitmap(bmp);

camera.startPreview();

}

catch

(Exception

e)

{

e.printStackTrace();

}

}

}

private

final

class

SurfaceCallback

implements

Callback

{

@Override

public

void

surfaceChanged(SurfaceHolder

holder,

int

format,

int

width,

int

height)

{

if

(camera

!=

null)

{

parameters

=

camera.getParameters();

parameters.setPictureFormat(PixelFormat.JPEG);

//

设置预览区域的大小

parameters.setPreviewSize(width,

height);

//

设置每秒钟预览帧数

parameters.setPreviewFrameRate(20);

//

设置预览图片的大小

parameters.setPictureSize(width,

height);

parameters.setJpegQuality(80);

}

}

@Override

public

void

surfaceCreated(SurfaceHolder

holder)

{

int

cameraCount

=

0;

Camera.CameraInfo

cameraInfo

=

new

Camera.CameraInfo();

cameraCount

=

Camera.getNumberOfCameras();

//设置相机的参数

for

(int

i

=

0;

i

<

cameraCount;

i++)

{

Camera.getCameraInfo(i,

cameraInfo);

if

(cameraInfo.facing

==

Camera.CameraInfo.CAMERA_FACING_FRONT)

{

try

{

camera

=

Camera.open(i);

camera.setPreviewDisplay(holder);

setCameraDisplayOrientation(i,

camera);

//最重要的设置

帧图的回调

camera.setPreviewCallback(new

MyPreviewCallback());

camera.startPreview();

}

catch

(Exception

e)

{

e.printStackTrace();

}

}

}

}

@Override

public

void

surfaceDestroyed(SurfaceHolder

holder)

{

//记得释放,避免OOM和占用

if

(camera

!=

null)

{

camera.setPreviewCallback(null);

camera.stopPreview();

camera.release();

camera

=

null;

}

}

}

private

class

MyPreviewCallback

implements

PreviewCallback

{

@Override

public

void

onPreviewFrame(byte[]

data,

Camera

camera)

{

//这里需要注意,回调出来的data不是我们直接意义上的RGB图

而是YUV图,因此我们需要

//将YUV转化为bitmap再进行相应的人脸检测,同时注意必须使用RGB_565,才能进行人脸检测,其余无效

Camera.Size

size

=

camera.getParameters().getPreviewSize();

YuvImage

yuvImage

=

new

YuvImage(data,

ImageFormat.NV21,

size.width,

size.height,

null);

ByteArrayOutputStream

baos

=

new

ByteArrayOutputStream();

yuvIpressToJpeg(new

Rect(0,

0,

size.width,

size.height),

80,

baos);

byte[]

byteArray

=

baos.toByteArray();

detectionFaces(byteArray);

}

}

/**

*

检测人脸

*

*

@param

data

预览的图像数据

*/

private

void

detectionFaces(byte[]

data)

{

BitmapFactory.Options

options

=

new

BitmapFactory.Options();

Bitmap

bitmap1

=

BitmapFactory.decodeByteArray(data,

0,

data.length,

options);

int

width

=

bitmap1.getWidth();

int

height

=

bitmap1.getHeight();

Matrix

matrix

=

new

Matrix();

Bitmap

bitmap2

=

null;

FaceDetector

detector

=

null;

//设置各个角度的相机,这样我们的检测效果才是最好

switch

(orientionOfCamera)

{

case

0:

//初始化人脸检测(下同)

detector

=

new

FaceDetector(width,

height,

10);

matrix.postRotate(0.0f,

width

/

2,

height

/

2);

//

以指定的宽度和高度创建一张可变的bitmap(图片格式必须是RGB_565,不然检测不到人脸)

bitmap2

=

Bitmap.createBitmap(width,

height,

Bitmap.Config.RGB_565);

break;

case

90:

detector

=

new

FaceDetector(height,

width,

1);

matrix.postRotate(-270.0f,

height

/

2,

width

/

2);

bitmap2

=

Bitmap.createBitmap(height,

width,

Bitmap.Config.RGB_565);

break;

case

180:

detector

=

new

FaceDetector(width,

height,

1);

matrix.postRotate(-180.0f,

width

/

2,

height

/

2);

bitmap2

=

Bitmap.createBitmap(width,

height,

Bitmap.Config.RGB_565);

break;

case

270:

detector

=

new

FaceDetector(height,

width,

1);

matrix.postRotate(-90.0f,

height

/

2,

width

/

2);

bitmap2

=

Bitmap.createBitmap(height,

width,

Bitmap.Config.RGB_565);

break;

}

//设置支持的面数(最大支持检测多少人的脸

,可以根据需要调整,不过需要与findFaces中的参数数值相同,否则会抛出异常)

faces

=

new

FaceDetector.Face[10];

Paint

paint

=

new

Paint();

paint.setDither(true);

Canvas

canvas

=

new

Canvas();

canvas.setBitmap(bitmap2);

canvas.setMatrix(matrix);

//

将bitmap1画到bitmap2上(这里的偏移参数根据实际情况可能要修改)

canvas.drawBitmap(bitmap1,

0,

0,

paint);

//这里通过向findFaces中传递帧图转化后的bitmap和最大检测的人脸数face,返回检测后的人脸数

faceNumber

=

detector.findFaces(bitmap2,

faces);

mTV.setText("facnumber"

+

faceNumber);

mTV.setTextColor(Color.RED);

//这里就是我们的人脸识别,绘制识别后的人脸区域的类

if

(faceNumber

!=

0)

{

mFindFaceView.setVisibility(View.VISIBLE);

mFindFaceView.drawRect(faces,

faceNumber);

}

else

{

mFindFaceView.setVisibility(View.GONE);

}

bitmap2.recycle();

bitmap1.recycle();

}

/**

*

设置相机的显示方向(这里必须这么设置,不然检测不到人脸)

*

*

@param

cameraId

相机ID(0是后置摄像头,1是前置摄像头)

*

@param

camera

相机对象

*/

private

void

setCameraDisplayOrientation(int

cameraId,

Camera

camera)

{

Camera.CameraInfo

info

=

new

Camera.CameraInfo();

Camera.getCameraInfo(cameraId,

info);

int

r

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论