今天在找資料的時候無意間發現這個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.Face
s 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.Face s. The array must be sized equal to themaxFaces value set at initialization |
沒有留言:
張貼留言