您好,登錄后才能下訂單哦!
這篇文章主要介紹“Android中如何實現人臉檢測功能”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Android中如何實現人臉檢測功能”文章能幫助大家解決問題。
1、項目配置
首先,為了將Vision庫添加到你的工程,你需要導入Play Services 8.1或者更高的版本進入你的工程。本教程只導入Play Services Vision庫。打開你工程中的build.gradle文件然后添加以下的編譯依賴節點代碼。
compile 'com.google.android.gms:play-services-vision:8.1.0'
當你已經在工程中包含了Play Services,就可以關閉工程中的build.gradle文件,然后打開 AndroidManifest.xml文件。在你的manifest文件中加入下列數據定義人臉檢測的依賴項。讓Vision庫知道你將會在應用中使用它。
<meta-data android:name="com.google.android.gms.vision.DEPENDENCIES"android:value="face"/>
一旦完成了AndroidManifest.xml的配置,你就可以關閉這個文件。下一步,你需要創建一個新的類文件FaceOverlayView.java。這個類繼承自View類,用來進行人臉檢測邏輯、顯示經過分析的圖像和在圖像上繪制信息來說明觀點等功能。
現在,我們開始增加成員變量并實現構造函數。這個Bitmap(位圖)對象用來存儲將要被分析的位圖數據,SparseArray數組用來存儲在圖像中發現的人臉信息。
public class FaceOverlayView extends View { private Bitmap mBitmap; private SparseArray<Face> mFaces; public FaceOverlayView(Context context) { this(context, null); } public FaceOverlayView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FaceOverlayView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } }
然后,我們在FaceOverlayView類中增加一個setBitmap(Bitmap bitmap)函數,現在我們只通過這個函數存儲位圖對象,一會將用這個方法來分析位圖數據。
public void setBitmap( Bitmap bitmap ) { mBitmap = bitmap; }
接下來,我們需要一張位圖圖片。我已經在GitHub上的示例工程中添加了一張,當然你可以使用任何一張你喜歡的圖片,然后看看它到底可不可行。當你選好圖片后,把它放到res/raw目錄下。本教程假定圖片的名字叫face.jpg。
當你把圖片放到res/raw目錄后,打開res/layout/activity_main.xml文件。在這個布局文件中引用一個FaceOverlayView對象,使它在MainActivity中顯示出來。
<?xml version="1.0" encoding="utf-8"?> <com.tutsplus.facedetection.FaceOverlayView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/face_overlay" android:layout_width="match_parent" android:layout_height="match_parent" />
定義完布局文件后,打開MainActivity然后在onCreate()函數中引用一個FaceOverlayView的實例。通過輸入流從raw文件夾中讀入face.jpg并轉成位圖數據。在擁有了位圖數據之后,你就可以通過調用FaceOverlayView的setBitmap方法在自定義視圖中設置位圖了。
public class MainActivity extends AppCompatActivity { private FaceOverlayView mFaceOverlayView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mFaceOverlayView = (FaceOverlayView) findViewById( R.id.face_overlay ); InputStream stream = getResources().openRawResource( R.raw.face ); Bitmap bitmap = BitmapFactory.decodeStream(stream); mFaceOverlayView.setBitmap(bitmap); } }
2、檢測人臉
現在你的工程已經設置好了,是時候來開始檢測人臉了。在setBitmap( Bitmap bitmap )方法中定義一個FaceDetector對象。我們可以通過用FaceDetector中的構造器來實現,通過FaceDetector.Builder你可以定義多個參數來控制人臉檢測的速度和FaceDetector生成的其他數據。
具體的設置取決于你的應用程序的用途。如果開啟了面部特征搜索,那么人臉檢測的速度回變得很慢。在大多數程序設計中,每一件事都有它的優缺點。如果想要了解關于FaceDetector.Builder的更多信息,你可以通過查找安卓開發者網站的官網文檔獲得。
FaceDetector detector = new FaceDetector.Builder( getContext() ) .setTrackingEnabled(false) .setLandmarkType(FaceDetector.ALL_LANDMARKS) .setMode(FaceDetector.FAST_MODE) .build();
你需要檢查FaceDetector是否是可操作的。每當用戶***次在設備上使用人臉檢測,Play Services服務需要加載一組小型本地庫去處理應用程序的請求。雖然這些工作一般在應用程序啟動之前就完成了,但是做好失敗處理同樣是必要的。
如果FaceDetector是可操作的,那么你需要將位圖數據轉化成Frame對象,并通過detect函數傳入用來做人臉數據分析。當完成數據分析后,你需要釋放探測器,防止內存泄露。***調用invalidate()函數來觸發視圖刷新。
if (!detector.isOperational()) { //Handle contingency } else { Frame frame = new Frame.Builder().setBitmap(bitmap).build(); mFaces = detector.detect(frame); detector.release(); } invalidate();
現在你已經在圖片中發現了人臉信息,并可以使用了。例如,你可以沿著檢測出的每一張臉畫一個框。在invalidate()函數調用之后,我們可以在OnDraw(Canvas canvas)函數中添加所有必要的邏輯。我們需要確保位圖和人臉數據是有效的,在那之后畫布上畫出位圖數據,然后再沿著每張臉的方位畫一個框。
因為不同的設備的分辨率不同,你需要通過控制位圖的縮放尺寸來保證圖片總是能被正確顯示出來。
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if ((mBitmap != null) && (mFaces != null)) { double scale = drawBitmap(canvas); drawFaceBox(canvas, scale); } }
drawBitmap(Canvas canvas)方法會將圖像自適應大小的畫在畫布上,同時返回一個正確的縮放值供你使用。
private double drawBitmap( Canvas canvas ) { double viewWidth = canvas.getWidth(); double viewHeight = canvas.getHeight(); double imageWidth = mBitmap.getWidth(); double imageHeight = mBitmap.getHeight(); double scale = Math.min( viewWidth / imageWidth, viewHeight / imageHeight ); Rect destBounds = new Rect( 0, 0, (int) ( imageWidth * scale ), (int) ( imageHeight * scale ) ); canvas.drawBitmap( mBitmap, null, destBounds, null ); return scale; }
drawFaceBox(Canvas canvas, double scale)方法會更有趣,被檢測到人臉數據以位置信息的方式存儲到mFaces中,這個方法將基于這些位置數據中的寬、高在檢測到的人臉位置畫一個綠色的矩形框。
你需要定義自己的繪畫對象,然后從你的SparseArray數組中循環的找出位置、高度和寬度信息,再利用這些信息在畫布上畫出矩形。
private void drawFaceBox(Canvas canvas, double scale) { //paint should be defined as a member variable rather than //being created on each onDraw request, but left here for //emphasis. Paint paint = new Paint(); paint.setColor(Color.GREEN); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(5); float left = 0; float top = 0; float right = 0; float bottom = 0; for( int i = 0; i < mFaces.size(); i++ ) { Face face = mFaces.valueAt(i); left = (float) ( face.getPosition().x * scale ); top = (float) ( face.getPosition().y * scale ); right = (float) scale * ( face.getPosition().x + face.getWidth() ); bottom = (float) scale * ( face.getPosition().y + face.getHeight() ); canvas.drawRect( left, top, right, bottom, paint ); } }
這時運行你的應用程序,你會發現每張被檢測到的人臉都被矩形包圍著。值得注意的是,現在我們所使用的人臉檢測API版本非常新,所以它不一定能檢測到所有的人臉。你可以通過修改FaceDetector.Builder中的配置,使它獲得到更多的信息,但是我不能保證這一定會起作用。
3、理解面部特征
面部特征指的是臉上的一些特殊點。人臉檢測API不是依靠面部特征來檢測一張人臉,而是在檢測到人臉之后才能檢測面部特征。這就是為什么檢測面部特征是一個可選的設置,我們可以通過FaceDetector.Builder開啟。
你可以把這些面部特征信息做為一個附加的信息來源,例如需找模特的眼睛在哪里,這樣就可以在應用中做相應的處理了。有十二種面部特征是可能被檢測出來的: 左右眼 左右耳朵 左右耳垂 鼻子 左右臉頰 左右嘴角 嘴
面部特征的檢測取決于檢測的角度。例如,有人側對著的話,那么只能檢測到他的一個眼睛,這意味著另一只眼睛不會被檢測到。下表概述了哪些面部特征應該檢測到(Y是基于臉部的歐拉角(左或右))。
歐拉角 Y | 可見的標志 |
---|---|
< -36° | 左眼、左嘴角、左耳朵、鼻子、左臉頰 |
-36° to -12° | 左嘴角、鼻子、下嘴角、右眼、左眼、左臉頰、左耳垂 |
-12° to 12° | 右眼、左眼、鼻子、左臉頰、右臉頰、左嘴角、右嘴角、下嘴角 |
12° to 36° | 右嘴角、鼻子、下嘴角、左眼、右眼、右臉頰、右耳垂 |
> 36° | 右眼、右嘴角、右耳朵、鼻子、右臉頰 |
如果在人臉檢測中,你已經開啟了面部特征檢測,那么你可以很容易地使用面部特征信息。你只需要調用getLandmarks()函數獲得一個面部特征列表就可以了,你可以直接使用它。
在本教程中,你可以利用一個新的函數drawFaceLandmarks(Canvas canvas, double scale)在人臉檢測中檢測出的每一個面部特征上畫一個小圓圈,在onDraw(canvas canvas)函數中,用drawFaceLandmarks替換drawFaceBox。該方法以每個面部特征點的位置為中心,自適應位圖大小,用一個圓圈把面部特征點圈起來。
private void drawFaceLandmarks( Canvas canvas, double scale ) { Paint paint = new Paint(); paint.setColor( Color.GREEN ); paint.setStyle( Paint.Style.STROKE ); paint.setStrokeWidth( 5 ); for( int i = 0; i < mFaces.size(); i++ ) { Face face = mFaces.valueAt(i); for ( Landmark landmark : face.getLandmarks() ) { int cx = (int) ( landmark.getPosition().x * scale ); int cy = (int) ( landmark.getPosition().y * scale ); canvas.drawCircle( cx, cy, 10, paint ); } } }
調用該方法之后,您應該看到如下圖所示的畫面,面部特征點被綠色的小圓圈圈起來。
4、額外的面部數據
人臉的位置和面部特征信息是非常有用的,除此之外,我們在應用中還可以通過Face的內置方法獲得人臉檢測的更多信息。通過getIsSmilingProbability()、getIsLeftEyeOpenProbability()和getIsRightEyeOpenProbability()方法的返回值(范圍從0.0到1.0)我們可以判斷人的左右眼是否睜開,是否微笑。當數值越接近于1.0那么可能性也就越大。
你也可以通過人臉檢測獲得Y和Z軸的歐拉值,Z軸的歐拉值是一定會返回的,如果你想接收到X軸的值,那么你必須在檢測時使用一個準確的模式,下面是一個如何或者這些值的例子。
private void logFaceData() { float smilingProbability; float leftEyeOpenProbability; float rightEyeOpenProbability; float eulerY; float eulerZ; for( int i = 0; i < mFaces.size(); i++ ) { Face face = mFaces.valueAt(i); smilingProbability = face.getIsSmilingProbability(); leftEyeOpenProbability = face.getIsLeftEyeOpenProbability(); rightEyeOpenProbability = face.getIsRightEyeOpenProbability(); eulerY = face.getEulerY(); eulerZ = face.getEulerZ(); Log.e( "Tuts+ Face Detection", "Smiling: " + smilingProbability ); Log.e( "Tuts+ Face Detection", "Left eye open: " + leftEyeOpenProbability ); Log.e( "Tuts+ Face Detection", "Right eye open: " + rightEyeOpenProbability ); Log.e( "Tuts+ Face Detection", "Euler Y: " + eulerY ); Log.e( "Tuts+ Face Detection", "Euler Z: " + eulerZ ); } }
關于“Android中如何實現人臉檢測功能”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。