本文主要对OpenCV识别人脸进行简要说明

人脸识别模型文件:https://github.com/opencv/opencv/tree/4.x/data/haarcascades 本文demo:https://github.com/Alienchang/TestiOSCapture

一. 引入OpenCV,这里使用pod(曾经尝试过直接拖源码,文件路径一直报错)
pod 'OpenCV'
二. 头文件引入

在使用的类文件最上方引入

#if __cplusplus && __has_include(<opencv2/imgcodecs/ios.h>)
#import <opencv2/imgproc/types_c.h>
#import <opencv2/core/core.hpp>
#import <opencv2/objdetect/objdetect.hpp>
#import <opencv2/imgcodecs/ios.h>
#import <opencv2/core.hpp>
#import <opencv2/highgui.hpp>
#import <opencv2/imgproc.hpp>
#import <sys/utsname.h>
using namespace cv;
using namespace std;
#endif

如果不是在最上方,有可能编译报错

三. 处理画面

视频采集:https://alienchang.github.io/post/%E5%9B%BE%E5%83%8F%E5%A4%84%E7%90%86/ios%E8%A7%86%E9%A2%91%E9%87%87%E9%9B%86%E4%BB%A5%E5%8F%8A%E9%A2%84%E8%A7%88/ 这里介绍了视频采集。 我们现在需要做的就是捕获采集到的数据,并且使用OpenCV和训练好的模型去识别这个数据。

// 当前画面图像储存格式
CVImageBufferRef imageBuffer =  CMSampleBufferGetImageBuffer(sampleBuffer);
// 锁定当前图像数据,防止其他操作改变数据
CVPixelBufferLockBaseAddress(imageBuffer, 0);
uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);
// 以下操作为耗时操作,如果在主线程或者当前线程操作,会影响视频预览或者其他画面处理速度    
dispatch_async(self.detectQueue, ^{
    // OpenCV人脸识别模型加载
    NSString *path1 = [NSBundle.mainBundle pathForResource:@"haarcascade_frontalface_default" ofType:@"xml"];
        cv::CascadeClassifier cas_alt1 = cv::CascadeClassifier([path1 cStringUsingEncoding:NSUTF8StringEncoding]);
        // 将画面转为OpenCV源数据格式
        Mat original = Mat((int)height,(int)width,CV_8UC4,baseAddress);
        // 简单理解为尺寸的精细程度,取值>1
        double scalingFactor = 1.5;               
        // 识别最少几次成功才认为成功识别为一个人脸
        int minNeighbors = 1;                     
        int flags = 0;
        // 最小可识别区域,如果设置过小,人离摄像头较远时无法识别
        cv::Size miniSize = cv::Size(80, 80);   
        // 区域,cv::Rect等同CGRect
        std::vector<cv::Rect>squares;
        // 开始识别,并将结果输出到squares
        cas_alt2.detectMultiScale(original,
                                  squares,
                                  scalingFactor,
                                  minNeighbors,
                                  flags,
                                  miniSize);

        for (NSInteger i = 0; i < squares.size(); ++i) {
            cv::Rect rect = squares[i];
            CGSize screenSize = UIScreen.mainScreen.bounds.size;
            CGRect oc_Rect = CGRectMake(rect.x, rect.y, rect.width, rect.height);
            
            if (self.detectBlock) {
                self.detectBlock(oc_Rect);
            }
        }
    });