今天在找資料的時候無意間發現這個Class : android.media.FaceDetector 覺得相當有趣 , 馬上放下手邊的事情尋找關於FaceDetector的資料 , 找了那麼多資料所以在這邊做個統整 , 首先這邊有關於FaceDetector的Source Code , 想進一步研究的人可以去參考 , 不過關於API Doc的描述 , 進行偵測的圖片必須是RGB565的格式 , 再來是實作程式碼的部分
import android.app.Activity;
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.media.FaceDetector.Face;
import android.os.Bundle;
import android.view.View;
public class FaceDetector_Test extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(new FaceView(this));
}
public static class FaceView extends View
{
int imageWidth, imageHeight;
int numberOfFace = 10;
//自訂能偵測出的臉孔數目
FaceDetector myFaceDetect;
FaceDetector.Face[] myFace;
float myEyesDistance;
int numberOfFaceDetected;
Bitmap myBitmap;
public FaceView(Context context)
{
super(context);
// TODO Auto-generated constructor stub
BitmapFactory.Options BFO = new BitmapFactory.Options();
BFO.inPreferredConfig = Bitmap.Config.RGB_565;
//由於FaceDetector只能處理RGB565格式的圖片 , 所以我們要對
//圖片進行前處理的動作
myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.play, BFO);
//從getResources()中的物件找出在res/drawable裡的圖片
//並以RGB565處理解譯成Bitmap物件
imageWidth = myBitmap.getWidth();
imageHeight = myBitmap.getHeight();
myFaceDetect = new FaceDetector(imageWidth, imageHeight, numberOfFace);
//Note that the width of the image must be even.
//Doc中有描述上面這句 , 不過不是很清楚用意
myFace = new FaceDetector.Face[numberOfFace];
//宣告一個FaceDetector.Face陣列 , 準備儲存所偵測到的臉孔位置資訊
//所以陣列容量必定要和之前自訂的臉孔可偵測數目一樣
numberOfFaceDetected = myFaceDetect.findFaces(myBitmap, myFace);
}
@Override
protected void onDraw(Canvas canvas)
{
// TODO Auto-generated method stub
canvas.drawBitmap(myBitmap, 0, 0, null);
Paint myPaint = new Paint();
myPaint.setColor(Color.GREEN);
myPaint.setStyle(Paint.Style.STROKE);
myPaint.setStrokeWidth(3);
for(int i=0; i < numberOfFaceDetected; i++)
{
//將每個偵測出來的臉孔當畫上框框
Face face = myFace[i];
PointF myMidPoint = new PointF();
face.getMidPoint(myMidPoint);
//兩眼中心點的point
myEyesDistance = face.eyesDistance();
//兩眼之間的距離
canvas.drawRect(
(int)(myMidPoint.x - myEyesDistance),
(int)(myMidPoint.y - myEyesDistance),
(int)(myMidPoint.x + myEyesDistance),
(int)(myMidPoint.y + myEyesDistance),
myPaint);
//如果用兩眼的距離能抓到臉長寬的比例
//畫出的框框大概就可以框住臉了
}
}
}
}
戴眼鏡的照片而且成功的結果
失敗的結果....臉太紅? 眼睛太假?
最後把網路上一些開發者的建議做一個整理:
1. 其實看完程式碼大概可以能知道他是靠偵測眼睛來判斷人臉的位置 , 其他五官的細節就沒辦法偵測到了 , 所以雙眼必須同時出現在照片上才可以進行偵測,並且太陽眼鏡/眼鏡會影響檢測的效果。
2. 對於要偵測圖片的Pixels建議不要小於100x100 pixels否則會偵測不到 , 但是也不要太大 , 否則偵測得過程太久還有可能出現加載圖片例外的狀況 , 大概小於800x800 pixels效果不錯。
3. 可以考慮開一個獨立的Thread來處理。
3. 可以考慮開一個獨立的Thread來處理。
4. 經過我的測試結果 , 如果說放了一張多人團體照的話 , 但是建構子中的 int maxFaces 參數設的很小例如"2" , 我猜測此時API會取他所分析出可能是人臉中 , Rank最高的前兩名作回報 , 所以把 maxFaces 調高一點可以讓團體照偵測的結果準很多 , 對於單人照其實沒太大差別。
下面是關於findFaces function的API Doc , 我特別把一段話標了起來
public int findFaces (Bitmap bitmap, Face[] faces)
Since: API Level 1
Finds all the faces found in a given
Bitmap. The supplied array is populated with FaceDetector.Faces for each face found. The bitmap must be in 565 format (for now).Parameters
| bitmap | the Bitmap graphic to be analyzed |
|---|---|
| faces | an array in which to place all found FaceDetector.Faces. The array must be sized equal to themaxFaces value set at initialization |


沒有留言:
張貼留言