iOS AVFoundation動(dòng)態(tài)人臉識(shí)別功能

一、AVCaptureSession:設(shè)備輸入數(shù)據(jù)管理對(duì)象

  • 可以根據(jù)AVCaptureSession創(chuàng)建對(duì)應(yīng)的AVCaptureDeviceInputAVCaptureVideoDataOutput對(duì)象
  • 創(chuàng)建出來(lái)的Input、Output對(duì)象會(huì)被添加到AVCaptureSession中管理,代表輸入、輸出數(shù)據(jù)對(duì)象,它配置抽象硬件設(shè)備的ports。
// 1.創(chuàng)建媒體管理會(huì)話(huà)
    AVCaptureSession *captureSession = [[AVCaptureSession alloc] init];
    self.session = captureSession;
    // 判斷分辨率是否支持 640x480,支持就設(shè)置為:640x480
    if ([captureSession canSetSessionPreset:AVCaptureSessionPreset640x480]) {
        captureSession.sessionPreset = AVCaptureSessionPreset640x480;
    }

二、AVCaptureDevice:代表硬件設(shè)備

  • 可以從這個(gè)類(lèi)中獲取手機(jī)硬件的照相機(jī)、聲音傳感器等
  • 當(dāng)我們?cè)趹?yīng)用程序中需要改變一些硬件設(shè)備的屬性(切換攝像頭、閃光模式改變、相機(jī)聚焦改變)的時(shí)候必須要先為設(shè)備加鎖,修改完成后解鎖。
    (補(bǔ)充)
//4. 移除舊輸入,添加新輸入
//4.1 設(shè)備加鎖
session.beginConfiguration()
//4.2. 移除舊設(shè)備
session.removeInput(deviceIn)
//4.3 添加新設(shè)備
session.addInput(newVideoInput)
//4.4 設(shè)備解鎖
session.commitConfiguration()

// 2.獲取前置攝像頭
    AVCaptureDevice *captureDevice = nil;
    NSArray *cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for (AVCaptureDevice *camera in cameras) {
        if (camera.position == AVCaptureDevicePositionFront) {
            captureDevice = camera;
        }
    }
    if (!captureDevice) {
        [DLLoading DLToolTipInWindow:@"無(wú)前置攝像頭!"];
        return;
    }

三、AVCaptureDeviceInput設(shè)備輸入數(shù)據(jù)管理對(duì)象

  • 可以根據(jù)AVCaptureDevice創(chuàng)建對(duì)應(yīng)的AVCaptureDeviceInput對(duì)象
  • 該對(duì)象將會(huì)被添加到AVCaptureSession中管理,代表輸入設(shè)備,它配置抽象硬件設(shè)備的ports,常用的有麥克風(fēng)、相機(jī)等
// 3.創(chuàng)建輸入數(shù)據(jù)對(duì)象
    NSError *error = nil;
    AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
    if (error) {
        [DLLoading DLToolTipInWindow:@"創(chuàng)建輸入數(shù)據(jù)對(duì)象錯(cuò)誤"];
        return;
    }

四、AVCaptureOutput輸出數(shù)據(jù)

  • 輸出的可以是圖片(AVCaptureStillImageOutput)或者視頻(AVCaptureMovieFileOutput)
// 4.創(chuàng)建輸出數(shù)據(jù)對(duì)象
    AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc] init];
    captureOutput.alwaysDiscardsLateVideoFrames = YES;
    [captureOutput setSampleBufferDelegate:self queue:dispatch_queue_create("cameraQueue", NULL)];
    
    NSDictionary *videoSettings = [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA] forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey];
    [captureOutput setVideoSettings:videoSettings];

五、添加輸入、輸出數(shù)據(jù)對(duì)象到session中

// 5.添加【輸入數(shù)據(jù)對(duì)象】和【輸出數(shù)據(jù)對(duì)象】到會(huì)話(huà)中
    if ([captureSession canAddInput:captureInput]) {
        [captureSession addInput:captureInput];
    }
    if ([captureSession canAddOutput:captureOutput]) {
        [captureSession addOutput:captureOutput];
    }

六、AVCaptureVideoPreviewLayer創(chuàng)建實(shí)時(shí)預(yù)覽圖層

  • 我們手機(jī)的照片以及視頻是怎樣顯示在手機(jī)屏幕上的呢,就是通過(guò)把這個(gè)對(duì)象添加到UIViewlayer上的。
// 6.創(chuàng)建實(shí)時(shí)預(yù)覽圖層
    AVCaptureVideoPreviewLayer *previewlayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession];
    [previewlayer connection].videoOrientation = (AVCaptureVideoOrientation)[[UIApplication sharedApplication] statusBarOrientation];
    self.view.layer.masksToBounds = YES;
    previewlayer.frame = CGRectMake((kMainScreenWidth-200)/2, 90, 200, 200);
    previewlayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    [self.scanView insertPreviewLayer:previewlayer];

人臉檢測(cè)器

#pragma mark - 人臉檢測(cè)器
- (CIDetector *)detector{
    if (_detector == nil){
        CIContext *context = [CIContext contextWithOptions:nil];
        NSDictionary *options = [NSDictionary dictionaryWithObject:CIDetectorAccuracyHigh forKey:CIDetectorAccuracy];
        _detector = [CIDetector detectorOfType:CIDetectorTypeFace context:context options:options];
    }
    return _detector;
}

檢測(cè)人臉照片

#pragma mark - 檢測(cè)人臉照片
- (UIImage *)getFaceImageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer{
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    CIImage *ciImage = [CIImage imageWithCVPixelBuffer:imageBuffer];
    CIContext *temporaryContext = [CIContext contextWithOptions:nil];
    CGImageRef videoImage;
    if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortrait) {
        videoImage = [temporaryContext createCGImage:ciImage fromRect:CGRectMake(0, 80, 480, 480)];
    }else{
        videoImage = [temporaryContext createCGImage:ciImage fromRect:CGRectMake(80, 0, 480, 480)];
    }
    UIImage *resultImg = [[UIImage alloc] initWithCGImage:videoImage];
    CGImageRelease(videoImage);
    
    //人臉檢測(cè)
    CIImage *resultCmg = [[CIImage alloc] initWithCGImage:resultImg.CGImage];
    CIFaceFeature * faceFeature = [self.detector featuresInImage:resultCmg].linq_firstOrNil;
    if (faceFeature && faceFeature.hasLeftEyePosition && faceFeature.hasRightEyePosition && faceFeature.hasMouthPosition) {
        return resultImg;
    }
    return nil;
}

代理方法

  • 獲取到outputSampleBuffer 后進(jìn)行人臉識(shí)別操作。
#pragma mark - AVCaptureVideoDataOutputSampleBufferDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
    if (!self.isDetecting) {
        self.isDetecting = YES;
        [connection setVideoOrientation:(AVCaptureVideoOrientation)[[UIApplication sharedApplication] statusBarOrientation]];
        UIImage *img = [self getFaceImageFromSampleBuffer:sampleBuffer];
        if (img && self.timeoutTime > 2) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.session stopRunning];
                self.isDetecting = NO;
                self.timeoutTime = 0;
                [self.scanView startAnimating];
                [self.viewModel faceScanWithImg:img];
            });
        }else{
            self.isDetecting = NO;
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容