iOS CIDetector的使用

作者: NextStep | 来源:发表于2016-02-03 17:37 被阅读1836次

    最近想学习下在iOS中识别人脸的技术,搜素中找到了CIDector,进而找到了各种例子:

    CIContext* context = [CIContextcontextWithOptions:nil];

    UIImage* imageInput = [self.imageViewimage];

    CIImage* image = [CIImageimageWithCGImage:imageInput.CGImage];

    //设置识别参数

    NSDictionary* param = [NSDictionarydictionaryWithObject:CIDetectorAccuracyHigh

    forKey:CIDetectorAccuracy];

    //声明一个CIDetector,并设定识别类型

    CIDetector* faceDetector = [CIDetectordetectorOfType:CIDetectorTypeFace

    context:context

    options:param];

    //取得识别结果

    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之所以在一个数组里,这个图要是有很多脸呢):

    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,这样就有了上图矩形坐标的值,这样看好像是坐标系需要转换(谁有关于这块好的链接或者讲解一下这块给我留言,谢谢!),到此图片脸部识别框正确显示在ps中了。

    那么转换到代码上,写了个方法:

    - (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和真实图片的比例(我已经在其他代码处理了imgView宽高比例和真实图片宽高比例相等:CGRectMake(0,0,kDeviceWidth,kDeviceWidth* (tImg.size.height/ tImg.size.width)),

    所以这里多了个 *2.0

    然后x值 pRect.origin.x* ratio4RealAndShow只需要转换一下比例,

    y值 ((tempImg.size.height*2- pRect.origin.y- pRect.size.height) * ratio4RealAndShow)就是上面ps中图片的逻辑,图片高-检测Y-检测高,乘一下比例,

    宽和高也是只需要乘一下比例。到此一个检测出来的frame转换成了可用的ImgView上的frame,然后在上面引用代码的地方检测到的frame都用这个方法转换一下:

    CGRectfaceRect = [self convert2SuitRect:realityFaceRect];

    完美的解决了问题(眼部和嘴检测的时候有faceWid*0.15或者0.3之类的,是大概估摸眼或者嘴巴占整个脸的比例):

    相关文章

      网友评论

      • matrix_lab:CG, CI坐标系是以左下方为圆点, UIKit是左上方为圆点。这里需要坐标转换

      本文标题:iOS CIDetector的使用

      本文链接:https://www.haomeiwen.com/subject/wedekttx.html