最近想學習下在iOS中識別人臉的技術(shù)豌拙,搜素中找到了CIDector毁渗,進而找到了各種例子:
CIContext* context = [CIContextcontextWithOptions:nil];
UIImage* imageInput = [self.imageViewimage];
CIImage* image = [CIImageimageWithCGImage:imageInput.CGImage];
//設置識別參數(shù)
NSDictionary* param = [NSDictionarydictionaryWithObject:CIDetectorAccuracyHigh
forKey:CIDetectorAccuracy];
//聲明一個CIDetector,并設定識別類型
CIDetector* faceDetector = [CIDetectordetectorOfType:CIDetectorTypeFace
context:context
options:param];
//取得識別結(jié)果
NSArray* detectResult = [faceDetector featuresInImage:image];
UIView* resultView = [[UIView alloc]initWithFrame:self.imageView.frame];
[self.viewaddSubview:resultView];
for(CIFaceFeature* faceFeature in detectResult) {
//臉部
UIView* faceView = [[UIView alloc]initWithFrame:faceFeature.bounds];
faceView.layer.borderWidth=1;
faceView.layer.borderColor= [UIColororangeColor].CGColor;
[resultView addSubview:faceView];
//左眼
if(faceFeature.hasLeftEyePosition) {
}
//右眼
if(faceFeature.hasRightEyePosition) {
}
//嘴巴
if(faceFeature.hasMouthPosition) {
}
}
[resultViewsetTransform:CGAffineTransformMakeScale(1, -1)];
如上代碼芳来,大部分都是這種樣子的含末,這是使用CIDetector基礎的代碼,但是運行之(這里用到了偶像gaga的圖片268*381即舌,(*@ο@*) 哇~)答渔,
這是what?橙色的框識別臉到哪去了?=暮?宋雏!可能有很多大神會很快補點代碼解決這個問題:[resultViewsetTransform:CGAffineTransformMakeScale(1, -1)] , balabala......
但是我這個愚公啊芜飘,花了好多時間來驗證正確的坐標:
首先我把faceFeature的bounds和UIImage.size打印出來(faceFeature之所以在一個數(shù)組里,這個圖要是有很多臉呢):
faceFrame===={{98, 182}, {138, 138}},imageSize===={134, 190.5}
faceFrame就是上面桔框顯示的位置磨总,imageSize是圖片大小,what?我的圖片是268*381啊嗦明,怎么會是一半:ios - Why the property Size of UIImage is half of the real picture size? - Stack Overflow
好吧UIImage這里size是真實的一半,因為@2x什么的蚪燕。
但是娶牌,為什么faceFrame的位置是這樣奔浅?
于是我打開ps,用faceFrame的位置東拼西湊:
得出gaga臉部框的frame是(98诗良,61汹桦,138,138)鉴裹,這不是除了Y值其他都和打印出來的都一樣么舞骆,可上面模擬器上的圖片連x值都不一樣啊,這是因為圖片在UIImageView有縮放的問題(imgView的寬度又不是138,這個一會再說)
Y值是怎么算出來的呢径荔,首先我用圖片的高減去當前的Y得到的是上圖矩形底邊的Y值199督禽,然后再減去矩形的高度138得出61,這樣就有了上圖矩形坐標的值总处,這樣看好像是坐標系需要轉(zhuǎn)換(誰有關(guān)于這塊好的鏈接或者講解一下這塊給我留言狈惫,謝謝!)鹦马,到此圖片臉部識別框正確顯示在ps中了胧谈。
那么轉(zhuǎn)換到代碼上,寫了個方法:
- (CGRect)convert2SuitRect:(CGRect)pRect
{
UIImage* tempImg =self.imageView.image;
float ratio4RealAndShow =
self.imageView.frame.size.width(tempImg.size.width*2.0);
CGRect resultRect =
CGRectMake(pRect.origin.x* ratio4RealAndShow, (tempImg.size.height*2- pRect.origin.y- pRect.size.height) * ratio4RealAndShow, ?pRect.size.width* ratio4RealAndShow, pRect.size.height* ratio4RealAndShow);
return resultRect;
}
說明一下:
pRect=faceFeature.bounds;
ratio4RealAndShow是imgView和真實圖片的比例(我已經(jīng)在其他代碼處理了imgView寬高比例和真實圖片寬高比例相等:CGRectMake(0,0,kDeviceWidth,kDeviceWidth* (tImg.size.height/ tImg.size.width))菠红,
所以這里多了個 *2.0
然后x值 pRect.origin.x* ratio4RealAndShow只需要轉(zhuǎn)換一下比例第岖,
y值 ((tempImg.size.height*2- pRect.origin.y- pRect.size.height) * ratio4RealAndShow)就是上面ps中圖片的邏輯,圖片高-檢測Y-檢測高试溯,乘一下比例蔑滓,
寬和高也是只需要乘一下比例。到此一個檢測出來的frame轉(zhuǎn)換成了可用的ImgView上的frame遇绞,然后在上面引用代碼的地方檢測到的frame都用這個方法轉(zhuǎn)換一下:
CGRectfaceRect = [self convert2SuitRect:realityFaceRect];
完美的解決了問題(眼部和嘴檢測的時候有faceWid*0.15或者0.3之類的键袱,是大概估摸眼或者嘴巴占整個臉的比例):