【移動應(yīng)用開發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)動態(tài)人臉檢測_第1頁
【移動應(yīng)用開發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)動態(tài)人臉檢測_第2頁
【移動應(yīng)用開發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)動態(tài)人臉檢測_第3頁
【移動應(yīng)用開發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)動態(tài)人臉檢測_第4頁
【移動應(yīng)用開發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)動態(tài)人臉檢測_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

【移動應(yīng)用開發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)動態(tài)人臉檢測

Android中怎么實(shí)現(xiàn)動態(tài)人臉檢測,針對這個問題,這篇文章詳細(xì)介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。第一步我們首先來定義一個surfaceview蓋在我們Carmen使用的surfaceview上進(jìn)行對人臉范圍的繪制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();

//

獲得兩眼之間的中間點(diǎn)

face.getMidPoint(midPoint);

//

獲得兩眼之間的距離

eyesDistance

=

face.eyesDistance();

//

換算出預(yù)覽圖片和屏幕顯示區(qū)域的比例參數(shù)

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

+

"");

//

因為拍攝的相片跟實(shí)際顯示的圖像是鏡像關(guān)系,所以在圖片上獲取的兩眼中間點(diǎn)跟手機(jī)上顯示的是相反方向

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與我們要繪制人臉范圍的畫布進(jìn)行綁定Canvascanvas=holder.lockCanvas();這樣我們就可以愉快的進(jìn)行繪制了,當(dāng)然前提是我們要拿到人臉的坐標(biāo)位置。2.還有重要的一點(diǎn),就是要讓我們用來蓋在Carema上的Surfaceview可以同名,并且設(shè)置起在視圖樹的層級為最高。

holder.setFormat(PixelFormat.TRANSPARENT);

this.setZOrderOnTop(true);第二步就是我們對人臉進(jìn)行檢測了,當(dāng)然前提是我們要獲得幀圖public

class

FaceRecognitionDemoActivity

extends

Activity

implements

OnClickListener

{

private

SurfaceView

preview;

private

Camera

camera;

private

Camera.Parameters

parameters;

private

int

orientionOfCamera;//

前置攝像頭的安裝角度

private

int

faceNumber;//

識別的人臉數(shù)

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);

//

設(shè)置緩沖類型(必不可少)

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

//

設(shè)置surface的分辨率

preview.getHolder().setFixedSize(176,

144);

//

設(shè)置屏幕常亮(必不可少)

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);

//

設(shè)置預(yù)覽區(qū)域的大小

parameters.setPreviewSize(width,

height);

//

設(shè)置每秒鐘預(yù)覽幀數(shù)

parameters.setPreviewFrameRate(20);

//

設(shè)置預(yù)覽圖片的大小

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();

//設(shè)置相機(jī)的參數(shù)

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);

//最重要的設(shè)置

幀圖的回調(diào)

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)

{

//這里需要注意,回調(diào)出來的data不是我們直接意義上的RGB圖

而是YUV圖,因此我們需要

//將YUV轉(zhuǎn)化為bitmap再進(jìn)行相應(yīng)的人臉檢測,同時注意必須使用RGB_565,才能進(jìn)行人臉檢測,其余無效

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

預(yù)覽的圖像數(shù)據(jù)

*/

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;

//設(shè)置各個角度的相機(jī),這樣我們的檢測效果才是最好

switch

(orientionOfCamera)

{

case

0:

//初始化人臉檢測(下同)

detector

=

new

FaceDetector(width,

height,

10);

matrix.postRotate(0.0f,

width

/

2,

height

/

2);

//

以指定的寬度和高度創(chuàng)建一張可變的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;

}

//設(shè)置支持的面數(shù)(最大支持檢測多少人的臉

,可以根據(jù)需要調(diào)整,不過需要與findFaces中的參數(shù)數(shù)值相同,否則會拋出異常)

faces

=

new

FaceDetector.Face[10];

Paint

paint

=

new

Paint();

paint.setDither(true);

Canvas

canvas

=

new

Canvas();

canvas.setBitmap(bitmap2);

canvas.setMatrix(matrix);

//

將bitmap1畫到bitmap2上(這里的偏移參數(shù)根據(jù)實(shí)際情況可能要修改)

canvas.drawBitmap(bitmap1,

0,

0,

paint);

//這里通過向findFaces中傳遞幀圖轉(zhuǎn)化后的bitmap和最大檢測的人臉數(shù)face,返回檢測后的人臉數(shù)

faceNumber

=

detector.findFaces(bitmap2,

faces);

mTV.setText("facnumber"

+

faceNumber);

mTV.setTextColor(Color.RED);

//這里就是我們的人臉識別,繪制識別后的人臉區(qū)域的類

if

(faceNumber

!=

0)

{

mFindFaceView.setVisibility(View.VISIBLE);

mFindFaceView.drawRect(faces,

faceNumber);

}

else

{

mFindFaceView.setVisibility(View.GONE);

}

bitmap2.recycle();

bitmap1.recycle();

}

/**

*

設(shè)置相機(jī)的顯示方向(這里必須這么設(shè)置,不然檢測不到人臉)

*

*

@param

cameraId

相機(jī)ID(0是后置攝像頭,1是前置攝像頭)

*

@param

camera

相機(jī)對象

*/

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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論