March 24, 2012

Face Detection บน iOS 5

Apple เปิด API ที่ช่วยในการตรวจจับใบหน้าให้มาตั้งแต่ iOS 5.0 ช่วยให้นักพัฒนาสามารถตรวจจับใบหน้าคนในภาพได้ง่ายๆ

คลาสพระเอกของ entry นี้ก็คือ CIDetector ซึ่งเป็นคลาสที่อยู่ใน CoreImage.framework โดยที่คลาสนี้มี method หลักอยู่ตัวเดียวก็คือ (NSArray *)featuresInImage:(CIImage *)image ที่จะคอยรับ CIImage เข้าไปและ return Array ของ CIFaceFeature กลับออกมา ซึ่งขนาดของ Array ก็จะขึ้นอยู่กับจำนวนของใบหน้าคนที่มีการตรวจพบนั่นเอง ซึ่ง CIFaceFeature ก็จะบรรจุตำแหน่งของ ตาซ้าย ตาขวา และปากไว้

เริ่มจากสมมติว่ามี UIImageView อยู่ 1 รูป


__weak IBOutlet UIImageView *_personImageView;


จากนั้นสร้าง object ของ CIDetector ขึ้นมา พร้อมกำหนด option ให้มัน ซึ่ง option จะเป็นการกำหนดความแม่นยำในการหาว่าจะมากหรือน้อย โดยถ้ากำหนดเป็นความแม่นยำมากก็จะใช้เวลาในการตรวจจับใบหน้าคนนานมากขึ้น


NSDictionary *options = [NSDictionary dictionaryWithObject: CIDetectorAccuracyHigh
                                                    forKey: CIDetectorAccuracy];

CIDetector *detector = [CIDetector detectorOfType: CIDetectorTypeFace
                                          context: nil
                                          options: options];


จากโค้ดด้านบนจะสังเกตเห็นตอนสร้าง detector นั้นมีการกำหนด type ให้ด้วย ซึ่งตอนนี้ใน API สามารถกำหนดค่านี้ได้เพียงค่าเดียว (อนาคตอาจกำหนดให้หาส่วนอื่นๆ ได้เพิ่ม?)

เมื่อเราได้ตัว detector มาแล้ว ก็ต้องเตรียม CIImage สำหรับจะส่งเข้าไปให้มันช่วยหาหน้าคนให้หน่อย เนื่องจากในโลกของ CoreImage นั้นมันไม่รู้จัก UIImage ที่เรามักใช้กันนั่นเอง ดังนี้


CIImage *image = [[CIImage allocinitWithImage_personImageView.image];
NSArray *features = [detector featuresInImage: image];


หลังจากได้ features มาแล้ว ก็ลองนำ CIFaceFeature แต่ละตัวใน array มาใช้งาน หรือลองแปะลงบนรูปเพื่อเช็คความถูกต้อง


for(CIFaceFeature *feature in features){
    if(feature.hasLeftEyePosition){
        [self markAtPoint: feature.leftEyePosition];
    }
    
    if(feature.hasRightEyePosition){
        [self markAtPoint: feature.rightEyePosition];
    }

    if(feature.hasMouthPosition){
        [self markAtPoint: feature.mouthPosition];
    }
}


ตอนที่จะ mark ตำแหน่งลงบนรูป ต้องอย่าลืมว่าระบบ coordinate ในโลกของ CoreImage ไม่เหมือนกันกับในโลกของ UIKit ที่คุ้นเคยกันนะ ;)



เท่าที่ทดสอบมาถือว่าใช้งานได้ดีพอสมควร ส่วนความฉลาดในการหาก็น่าจะเป็นแบบเดียวกับที่ใช้ใน iPhone 4S และโปรแกรม iPhoto บน Mac

ที่มาของภาพ: Lenna