当前位置:主页 > 资料 >

iOS 相机流人脸识别(二)-关键点检测(face landmark
栏目分类:资料   发布日期:2018-08-03   浏览次数:

导读:本文为去找网小编(www.7zhao.net)为您推荐的iOS 相机流人脸识别(二)-关键点检测(face landmark --Dlib),希望对您有所帮助,谢谢! 上篇文章人脸框检测已经介绍了我们如何从视频流中检测出人

本文为去找网小编(www.7zhao.net)为您推荐的iOS 相机流人脸识别(二)-关键点检测(face landmark --Dlib),希望对您有所帮助,谢谢!

内容来自www.7zhao.net



www.7zhao.net

上篇文章人脸框检测已经介绍了我们如何从视频流中检测出人脸位置的信息,基于这些内容,我们继续向下扩展,获取人脸68个关键点的信息,之所以要获得人脸位置的信息正是为了获取关键点做的准备,因为获取关键点的时候会用到人脸的位置 www.7zhao.net

继续看那张图

www.7zhao.net

这就是我们需要拿到的东西,今天我们要做的就是通过Dlib 检测出68个 人脸关键点,然后将这68个关键点绘制到视频流中

copyright www.7zhao.net

废话不多说 还是首先看下效果如何 copyright www.7zhao.net

欢迎访问www.7zhao.net

蜗壳还是很帅的哦!

copyright www.7zhao.net

Dlib 介绍

Dlib是一个包含机器学习算法的C++开源工具包。Dlib可以帮助您创建很多复杂的机器学习方面的软件来帮助解决实际问题。目前Dlib已经被广泛的用在行业和学术领域,包括机器人,嵌入式设备,移动电话和大型高性能计算环境 (这个是copy 的) 去找(www.7zhao.net欢迎您

Dlib 的集成

Dlib包含一个.a 和一个头文件的文件夹,我们可以在google 里搜索下载一个,或者通过cmake 来自己交叉编译一个,再或者用我的Dlib及模型 ( 密码: q6z4) 本文来自去找www.7zhao.net

(一)将Dlib放入你的工程

将我整理好的库及模型下载后你会看到是这样的 copyright www.7zhao.net

内容来自www.7zhao.net

那么你直接拖到你工程中

欢迎访问www.7zhao.net

需要注意的

欢迎访问www.7zhao.net

去找(www.7zhao.net欢迎您

我们拖进来以后那个dlib 的文件夹不能在工程里,一定要remove 掉,否则build 不起来,这里坑了很久,但记住不是 move to trash 本文来自去找www.7zhao.net

去找(www.7zhao.net欢迎您

就是这样 欢迎访问www.7zhao.net

(二)配置工程

(1).build setting 本文来自去找www.7zhao.net

搜索 preprocessor macros 内容来自www.7zhao.net

添加宏

欢迎访问www.7zhao.net

DLIB_JPEG_SUPPORT 内容来自www.7zhao.net

DLIB_NO_GUI_SUPPORT

内容来自www.7zhao.net

NDEBUG

内容来自www.7zhao.net

DDLIB_USE_BLAS 去找(www.7zhao.net欢迎您

DLIB_USE_LAPACK

copyright www.7zhao.net

内容来自www.7zhao.net

(2). header search path 内容来自www.7zhao.net

拖一下你的目录进去就行了 本文来自去找www.7zhao.net

内容来自www.7zhao.net

(3).依赖库

www.7zhao.net

Acceletrate.framework 去找(www.7zhao.net欢迎您

AssetsLibrary.framework

copyright www.7zhao.net

copyright www.7zhao.net

其他几个是opencv 用到的,不知道的同学看下上篇 人脸框检测

去找(www.7zhao.net欢迎您

(三)写代码了

这里需要注意的是,不要同时导入dlib 的头文件 和 opencv 的头文件,因为里面又一些宏定义 还是方法来着 会冲突,这里我们用单独的类来检测人脸的关键点

copyright www.7zhao.net

(1).新建一个FaceDlibWrapper类 将.m改成.mm 重写init 方法

内容来自www.7zhao.net

#import 
<dlib image_processing="" h="">
 
#import 
 <dlib image_io="" h="">
  
- (instancetype)init
{
    self = [super init];
    if (self) {
        //初始化 检测器
        NSString *modelFileName = [[NSBundle mainBundle] pathForResource:@"shape_predictor_68_face_landmarks" ofType:@"dat"];
        std::string modelFileNameCString = [modelFileName UTF8String];
        dlib::deserialize(modelFileNameCString) >> sp;
    }
    return self;
}
 </dlib>
</dlib> 
内容来自www.7zhao.net

(2).检测方法 去找(www.7zhao.net欢迎您

//之所以 return 的数组 看起来比较啰嗦 但是是为了让你们看清,也可以不这么写
- (NSArray 
<nsarray nbsp="">
 <nsvalue nbsp="">
   *>*)detecitonOnSampleBuffer:(CMSampleBufferRef)sampleBuffer inRects:(NSArray
  <nsvalue nbsp="">
    *)rects {
    
    dlib::array2d
   <dlib::bgr_pixel>
     img;
    dlib::array2d
    <dlib::bgr_pixel>
      img_gray;
    // MARK: magic
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    CVPixelBufferLockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
    
    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CVPixelBufferGetHeight(imageBuffer);
    char *baseBuffer = (char *)CVPixelBufferGetBaseAddress(imageBuffer);
    
    // set_size expects rows, cols format
    img.set_size(height, width);
    
    // copy samplebuffer image data into dlib image format
    img.reset();
    long position = 0;
    while (img.move_next()) {
        dlib::bgr_pixel& pixel = img.element();
        
        // assuming bgra format here
        long bufferLocation = position * 4; //(row * width + column) * 4;
        char b = baseBuffer[bufferLocation];
        char g = baseBuffer[bufferLocation + 1];
        char r = baseBuffer[bufferLocation + 2];
        //        we do not need this
        //        char a = baseBuffer[bufferLocation + 3];
        
        dlib::bgr_pixel newpixel(b, g, r);
        pixel = newpixel;
        
        position++;
    }
    
    // unlock buffer again until we need it again
    CVPixelBufferUnlockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
    
    // convert the face bounds list to dlib format
    std::vector
     <dlib::rectangle>
       convertedRectangles = [self convertCGRectValueArray:rects];
    dlib::assign_image(img_gray, img);
  
    
    NSMutableArray *facesLandmarks = [NSMutableArray arrayWithCapacity:0];
    for (unsigned long j = 0; j < convertedRectangles.size(); ++j)
    {
        dlib::rectangle oneFaceRect = convertedRectangles[j];
        
        // detect all landmarks
        dlib::full_object_detection shape = sp(img, oneFaceRect);
        
        //shape 里面就是我们所需要的68 个点 因为dilb 跟 opencv 冲突 所以我们转换成Foundation 的 Array
        NSMutableArray *landmarks = [NSMutableArray arrayWithCapacity:0];
        for (int i = 0; i < shape.num_parts(); i++) {
            dlib::point p = shape.part(i);
            [landmarks addObject:[NSValue valueWithCGPoint:CGPointMake(p.x(), p.y())]];
        }
        [facesLandmarks addObject:landmarks];
    }
    
    return facesLandmarks;
}
- (std::vector
      <dlib::rectangle>
       )convertCGRectValueArray:(NSArray
       <nsvalue nbsp="">
         *)rects {
    std::vector
        <dlib::rectangle>
          myConvertedRects;
    for (NSValue *rectValue in rects) {
        CGRect rect = [rectValue CGRectValue];
        long left = rect.origin.x;
        long top = rect.origin.y;
        long right = left + rect.size.width;
        long bottom = top + rect.size.height;
        dlib::rectangle dlibRect(left, top, right, bottom);
        
        myConvertedRects.push_back(dlibRect);
    }
    return myConvertedRects;
}
        </dlib::rectangle>
       </nsvalue>
      </dlib::rectangle>
     </dlib::rectangle>
    </dlib::bgr_pixel>
   </dlib::bgr_pixel>
  </nsvalue>
 </nsvalue>
</nsarray> copyright www.7zhao.net 

(3).获取关键点,并绘制在流中

本文来自去找www.7zhao.net

继续上篇文章,在绘制人脸框的位置,我们一起将68个关键点绘制出来

内容来自www.7zhao.net

#pragma mark - AVCaptureSession Delegate -
- (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
    
    NSMutableArray *bounds = [NSMutableArray arrayWithCapacity:0];
    for (AVMetadataFaceObject *faceobject in self.currentMetadata) {
        AVMetadataObject *face = [output transformedMetadataObjectForMetadataObject:faceobject connection:connection];
        [bounds addObject:[NSValue valueWithCGRect:face.bounds]];
    }
   
    UIImage *image = [self imageFromPixelBuffer:sampleBuffer];
    cv::Mat mat;
    UIImageToMat(image, mat);
    
    //获取关键点,将脸部信息的数组 和 相机流 传进去
    NSArray *facesLandmarks = [_dr detecitonOnSampleBuffer:sampleBuffer inRects:bounds];
    
    // 绘制68 个关键点
    for (NSArray *landmarks in facesLandmarks) {
        for (NSValue *point in landmarks) {
            CGPoint p = [point CGPointValue];
            cv::rectangle(mat, cv::Rect(p.x,p.y,4,4), cv::Scalar(255,0,0,255),-1);
        }
    }
    for (NSValue *rect in bounds) {
        CGRect r = [rect CGRectValue];
        //画框
        cv::rectangle(mat, cv::Rect(r.origin.x,r.origin.y,r.size.width,r.size.height), cv::Scalar(255,0,0,255));
    }
    
    //这里不考虑性能 直接怼Image
    dispatch_async(dispatch_get_main_queue(), ^{
       self.cameraView.image = MatToUIImage(mat);
    });
} 本文来自去找www.7zhao.net 

内容来自www.7zhao.net


本文原文地址:http://www.cocoachina.com/ios/20180803/24450.html

以上为iOS 相机流人脸识别(二)-关键点检测(face landmark --Dlib)文章的全部内容,若您也有好的文章,欢迎与我们分享!

内容来自www.7zhao.net

   皖ICP备12002049号-2 皖公网安备 34088102000435号   关于我们|联系我们| 免责声明|友情链接|网站地图|手机版