UIImagePickerController
UIImagePickerController 類用于管理可定制的,基于系統(tǒng)支持的用戶界面,用于在支持的設備上拍攝照片和視頻,并且在你的 app 中為用戶保存照片和視頻。 圖像選擇器控制器管理用戶交互并將這些交互的結(jié)果傳遞給委托對象。
UIImagePickerController 繼承于 UINavigationController,歸屬于 UIKit 框架,可以實現(xiàn)圖片選取、拍照、錄制視頻等功能,使用起來十分方便。
使用方式
需要導入框架:import <MobileCoreServices/MobileCoreServices.h>;
拍攝視頻需要導入包:#import <AssetsLibrary/AssetsLibrary.h>
需要遵循的協(xié)議:<UINavigationControllerDelegate,UIImagePickerControllerDelegate>;
注:需要導入 <MobileCoreServices/MobileCoreServices.h> 框架是因為 kUTTypeImage 和 kUTTypeMovie 被定義在其中。
注:實際上我們不會實現(xiàn) UINavigationControllerDelegate 中定義的任何協(xié)議方法,但由于 UIImagePickerController 繼承自 UINavigationController,并且改變了 UINavigationController的行為。因此,我們?nèi)匀恍枰鲃勇暶魑覀兊囊晥D控制器遵守 UINavigationControllerDelegate 協(xié)議。
1. 創(chuàng)建 UIImagePickerController 圖片選擇器對象
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
2. 設置 sourceType 媒體數(shù)據(jù)源類型
UIImagePickerControllerSourceType 是一個枚舉類型,用于設置要跳轉(zhuǎn)到哪個界面(相機拍照、照片圖庫、相冊) :
typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) {
UIImagePickerControllerSourceTypePhotoLibrary API_DEPRECATED("Will be removed in a future release, use PHPicker.", ios(2, API_TO_BE_DEPRECATED)), // 照片庫
UIImagePickerControllerSourceTypeCamera, // 系統(tǒng)內(nèi)置像機
UIImagePickerControllerSourceTypeSavedPhotosAlbum API_DEPRECATED("Will be removed in a future release, use PHPicker.", ios(2, API_TO_BE_DEPRECATED)), // 相冊
} API_UNAVAILABLE(tvos);
?? 查看 Apple 的源碼可以發(fā)現(xiàn),部分類型已經(jīng)被標注為 API_DEPRECATED,意味著該屬性即將被廢棄,推薦使用 PHPicker 代替。
設置示例:
// 驗證設備是否能夠從所需的來源獲取內(nèi)容
BOOL isSourceTypeAvailable = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
if (!isSourceTypeAvailable) {
// 可能是權限未打開,也可能是手機硬件不支持相機功能。
NSLog(@"啟動相機失敗,您的相機功能未開啟,請轉(zhuǎn)到手機設置中開啟相機權限!");
}else{
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
}
3. 設置攝像頭捕捉模式
如果設置了 sourceType 媒體數(shù)據(jù)源類型為 UIImagePickerControllerSourceTypeCamera,那你還需要設置是打開相機的拍照還是錄制視頻功能。
UIImagePickerControllerCameraCaptureMode 是一個枚舉類型:
UIImagePickerControllerCameraCaptureModePhoto, // 拍照模式,默認
UIImagePickerControllerCameraCaptureModeVideo // 視頻錄制模式
拍攝圖片:
// 設定拍攝的媒體類型:圖片
imagePicker.mediaTypes = @[(NSString *)kUTTypeImage];
// 設置攝像頭捕捉模式為捕捉圖片,默認
imagePicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
拍攝視頻:
// 設定拍攝的媒體類型:視頻
imagePicker.mediaTypes = @[(NSString *)kUTTypeMovie];
// 設置攝像頭捕捉模式為捕捉視頻
imagePicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
4. 攝像頭設備
UIImagePickerControllerCameraDevice 是一個枚舉類型,代表前置/后置攝像頭:
UIImagePickerControllerCameraDeviceRear, //后置攝像頭,默認
UIImagePickerControllerCameraDeviceFront //前置攝像頭
設置示例:
// 設置前置攝像頭
if ([UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront]) {
imagePicker.cameraDevice = UIImagePickerControllerCameraDeviceFront;
}
5. 設置錄制視頻質(zhì)量
UIImagePickerControllerQualityType 是一個枚舉類型,設置返回圖片的質(zhì)量:
UIImagePickerControllerQualityTypeHigh // 高清
UIImagePickerControllerQualityTypeMedium // 中等,適合 WiFi 傳輸
UIImagePickerControllerQualityTypeLow // 低質(zhì)量,適合蜂窩網(wǎng)傳輸
UIImagePickerControllerQualityType640x480 // VGA 質(zhì)量,640*480
UIImagePickerControllerQualityTypeIFrame1280x720 // 1280*720
UIImagePickerControllerQualityTypeIFrame960x540 // 960*540
設置示例:
imagePicker.videoQuality = UIImagePickerControllerQualityTypeLow;
6. 設置閃光燈模式
在調(diào)用攝像頭的時候我們可以選擇使用閃光燈,但是默認條件下對視頻有 10 分鐘的限制,需要用 videoMaximumDuration 屬性更改默認時間。
UIImagePickerControllerCameraFlashMode 是一個枚舉類型,用于設置閃光燈關閉、自動、打開。
UIImagePickerControllerCameraFlashModeOff = -1,
UIImagePickerControllerCameraFlashModeAuto = 0,默認
UIImagePickerControllerCameraFlashModeOn = 1
設置示例:
imagePicker.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto
7. 遵循協(xié)議
imagePicker.delegate = self;
8. 是否顯示系統(tǒng)自帶的攝像頭控制面板,默認YES
// 顯示標準相機 UI,
imagePicker.showsCameraControls = NO;
9. 設置自定義覆蓋圖層
UIImageView *overlayImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
overlayImageView.image = [UIImage imageNamed:@"circle3.png"];
UIView *cameraOverlay = overlayImageView;
imagePicker.cameraOverlayView = cameraOverlay
10. 以模態(tài)形式顯示 UIImagePickerController 對象
[self presentViewController:imagePicker animated:YES completion:nil];
11. 遵守并實現(xiàn) UIImagePickerControllerDelegate 協(xié)議中的方法
你需要關注協(xié)議中的這兩個方法:
// 媒體項(圖片或視頻)選擇完成后調(diào)用
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info;
// 取消選擇媒體項調(diào)用
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;
擴展函數(shù),用于保存到相簿:
/* 保存圖片到相簿 */
void UIImageWriteToSavedPhotosAlbum(
UIImage *image,//保存的圖片UIImage
id completionTarget,//回調(diào)的執(zhí)行者
SEL completionSelector, //回調(diào)方法
void *contextInfo//回調(diào)參數(shù)信息
);
//上面一般保存圖片的回調(diào)方法為:
- (void)image:(UIImage *)image
didFinishSavingWithError:(NSError *)error
contextInfo:(void *)contextInfo;
/* 判斷是否能保存視頻到相簿 */
BOOL UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(NSString *videoPath);
/* 保存視頻到相簿 */
void UISaveVideoAtPathToSavedPhotosAlbum(
NSString *videoPath, //保存的視頻文件路徑
id completionTarget, //回調(diào)的執(zhí)行者
SEL completionSelector,//回調(diào)方法
void *contextInfo//回調(diào)參數(shù)信息
);
//上面一般保存視頻的回調(diào)方法為:
- (void)video:(NSString *)videoPath
didFinishSavingWithError:(NSError *)error
contextInfo:(void *)contextInfo;
示例代碼:
#pragma mark - 完成選擇圖片
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
NSLog(@"%s",__func__);
// 從info取出此時攝像頭的媒體類型
NSString *mediaType = info[UIImagePickerControllerMediaType];
if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
// 【拍照模式】
// 通過info字典獲取選擇的照片
UIImage *image = info[UIImagePickerControllerOriginalImage];
// 將照片放入UIImageView對象顯示在UI界面
self.imageView.image = image;
// 保存圖像到相簿
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}else if ([mediaType isEqualToString:(NSString *)kUTTypeMovie]) {
// 【錄像模式】
NSURL *url = info[UIImagePickerControllerMediaURL];
NSString *path = url.path;
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(path)) {
// 保存視頻到相簿
UISaveVideoAtPathToSavedPhotosAlbum(path, self, @selector(video:didFinishSavingWithError:contextInfo:), nil);
}
}
// 關閉UIImagePickerController對象
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark 取消拍照
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
NSLog(@"%s",__func__);
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - 保存圖像或視頻完成的回調(diào)
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
NSLog(@"保存圖片完成");
}
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
NSLog(@"保存視頻完成");
}
封裝使用
VideoCaptureDemo 中將 UIImagePickerController 封裝成了一個Object 類使用,可以參考:
IDImagePickerCoordinator.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
/**
圖片選擇協(xié)調(diào)器
*/
@interface IDImagePickerCoordinator : NSObject
#pragma mark - getter 方法
- (UIImagePickerController *)cameraVC;
@end
IDImagePickerCoordinator.m
#import "IDImagePickerCoordinator.h"
#import <MobileCoreServices/MobileCoreServices.h>
#import <AssetsLibrary/AssetsLibrary.h>
@interface IDImagePickerCoordinator () <UINavigationControllerDelegate, UIImagePickerControllerDelegate>
@property (nonatomic, strong) UIImagePickerController *camera;
@end
@implementation IDImagePickerCoordinator
#pragma mark - Init methods
- (instancetype)init
{
self = [super init];
if(self){
_camera = [self setupImagePicker];
}
return self;
}
- (UIImagePickerController *)cameraVC
{
return _camera;
}
#pragma mark - Private methods
- (UIImagePickerController *)setupImagePicker
{
UIImagePickerController *camera;
if([self isVideoRecordingAvailable]){
camera = [UIImagePickerController new];
camera.sourceType = UIImagePickerControllerSourceTypeCamera;
camera.mediaTypes = @[(NSString *)kUTTypeMovie];
camera.delegate = self;
}
return camera;
}
- (BOOL)isVideoRecordingAvailable
{
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
NSArray *availableMediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
if([availableMediaTypes containsObject:(NSString *)kUTTypeMovie]){
return YES;
}
}
return NO;
}
- (BOOL)setFrontFacingCameraOnImagePicker:(UIImagePickerController *)picker
{
if([UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront]){
[picker setCameraDevice:UIImagePickerControllerCameraDeviceFront];
return YES;
}
return NO;
}
- (void)configureCustomUIOnImagePicker:(UIImagePickerController *)picker
{
UIView *cameraOverlay = [[UIView alloc] init];
picker.showsCameraControls = NO;
picker.cameraOverlayView = cameraOverlay;
}
#pragma mark - UIImagePickerControllerDelegate methods
// 完成選擇圖片
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(nullable NSDictionary<NSString *,id> *)editingInfo NS_DEPRECATED_IOS(2_0, 3_0) {
}
// 完成選擇視頻
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
NSURL *recordedVideoURL= [info objectForKey:UIImagePickerControllerMediaURL];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:recordedVideoURL]) {
[library writeVideoAtPathToSavedPhotosAlbum:recordedVideoURL
completionBlock:^(NSURL *assetURL, NSError *error){}
];
}
[picker dismissViewControllerAnimated:YES completion:nil];
}
// 取消選擇
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[picker dismissViewControllerAnimated:YES completion:nil];
}
@end
使用時先導入頭文件,設置屬性:
@property (nonatomic, strong) IDImagePickerCoordinator *imagePickerCoordinator;
再調(diào)用:
self.imagePickerCoordinator = [IDImagePickerCoordinator new];
[self presentViewController:[_imagePickerCoordinator cameraVC] animated:YES completion:nil];
AVFoundation
HQLAVFoundationViewController.h
#import <UIKit/UIKit.h>
/**
使用AVFoundation類拍照
*/
@interface HQLAVFoundationViewController : UIViewController
@end
HQLAVFoundationViewController.m
#import "HQLAVFoundationViewController.h"
#import <AVFoundation/AVFoundation.h>
#define ThemeColor [UIColor colorWithDisplayP3Red:81/255.0 green:136/255.0 blue:247/255.0 alpha:1.0]
@interface HQLAVFoundationViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (weak, nonatomic) IBOutlet UIButton *openCaptureBtn;
@property (weak, nonatomic) IBOutlet UIButton *canptureBtn;
@property (strong, nonatomic) AVCaptureSession *session; //媒體管理會話
@property (strong, nonatomic) AVCaptureDeviceInput *captureInput; //輸入數(shù)據(jù)對象
@property (strong, nonatomic) AVCaptureStillImageOutput *imageOutput; //輸出數(shù)據(jù)對象
@property (strong, nonatomic) AVCaptureVideoPreviewLayer *captureLayer; //視頻預覽圖層
@end
@implementation HQLAVFoundationViewController
#pragma mark - Lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
[self setNavigationControllerAppearance];
// 初始化攝像頭
[self initCaptureSession];
self.openCaptureBtn.hidden = NO;
self.canptureBtn.hidden = YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Custom Accessors
- (void)setNavigationControllerAppearance {
// 設置導航欄標題&字體&顏色
self.navigationItem.title = @"AVFoundation拍照";
[self.navigationController.navigationBar setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:17],NSForegroundColorAttributeName:ThemeColor}];
}
#pragma mark 初始化攝像頭
- (void)initCaptureSession {
/*
1?? AVCaptureSession
媒體捕捉會話,管理輸入與輸出之間的數(shù)據(jù)流,以及在出現(xiàn)問題時生成運行時錯誤。
負責把捕獲到的音頻視頻數(shù)據(jù)輸出到輸出設備上,一個會話可以有多個輸入輸入。
*/
// 1.創(chuàng)建媒體管理會話
AVCaptureSession *captureSession = [[AVCaptureSession alloc] init];
self.session = captureSession;
// 判斷分辨率是否支持 1280*720,支持就設置為:1280*720
if ([captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720]) {
captureSession.sessionPreset = AVCaptureSessionPreset1280x720;
}
/*
2?? AVCaptureDevice
關于相機硬件的接口。它被用于控制硬件特性,諸如鏡頭的位置、曝光、閃光燈等。
*/
// 2.獲取后置攝像頭
AVCaptureDevice *captureDevice = nil;
NSArray *cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *camera in cameras) {
if (camera.position == AVCaptureDevicePositionBack) {
// 獲得后置攝像頭
captureDevice = camera;
}
}
if (!captureDevice) {
NSLog(@"2.取得后置攝像頭錯誤!");
return;
}
// 取得前置攝像頭
// AVCaptureDevice *frontCaptureDevice = [AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInWideAngleCamera mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionFront];
/*
3?? AVCaptureDeviceInput
設備輸入數(shù)據(jù)管理對象,管理輸入數(shù)據(jù)
*/
// 3.創(chuàng)建輸入數(shù)據(jù)對象
NSError *error = nil;
AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
if (error) {
NSLog(@"3.創(chuàng)建輸入數(shù)據(jù)對象錯誤");
return;
}
self.captureInput = captureInput;
/*
4?? AVCaptureOutput
設備輸出數(shù)據(jù)管理對象,管理輸出數(shù)據(jù),通常使用它的子類:
AVCaptureAudioDataOutput //輸出音頻管理對象,輸出數(shù)據(jù)為NSData
AVCaptureStillImageDataOutput //輸出圖片管理對象,輸出數(shù)據(jù)為NSData
AVCaptureVideoDataOutput //輸出視頻管理對象,輸出數(shù)據(jù)為NSData
AVCaptureFileOutput
輸出文件管理對象,輸出數(shù)據(jù)以文件形式輸出
{//子類
AVCaptureAudioFileOutput //輸出是音頻文件
AVCaptureMovieFileOutput //輸出是視頻文件
}
*/
// 4.創(chuàng)建輸出數(shù)據(jù)對象
AVCaptureStillImageOutput *imageOutpot = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *setting = @{
AVVideoCodecKey:AVVideoCodecJPEG
};
[imageOutpot setOutputSettings:setting];
self.imageOutput = imageOutpot;
// 5?? 5.添加【輸入數(shù)據(jù)對象】和【輸出對象】到會話中
if ([captureSession canAddInput:captureInput]) {
[captureSession addInput:captureInput];
}
if ([captureSession canAddOutput:imageOutpot]) {
[captureSession addOutput:imageOutpot];
}
/*
6?? AVCaptureVideoPreviewLayer
實時預覽圖層
AVCaptureVideoPreviewLayer 是 CALayer 的子類,可被用于自動顯示相機產(chǎn)生的實時圖像。它還有幾個工具性質(zhì)的方法,可將 layer 上的坐標轉(zhuǎn)化到設備上。它看起來像輸出,但其實不是。另外,它擁有 session (outputs 被 session 所擁有)。
*/
// 6.創(chuàng)建實時預覽圖層
AVCaptureVideoPreviewLayer *previewlayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession];
self.view.layer.masksToBounds = YES;
previewlayer.frame = self.view.bounds;
previewlayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
// 【預覽圖層】插入在【拍照按鈕】的下方
[self.view.layer insertSublayer:previewlayer below:self.canptureBtn.layer];
self.captureLayer = previewlayer;
}
#pragma mark - IBAction
#pragma mark 打開攝像頭
- (IBAction)takePhoto:(UIButton *)sender {
self.captureLayer.hidden = NO;
self.canptureBtn.hidden = NO;
self.openCaptureBtn.hidden = YES;
[self.session startRunning]; //開始捕捉
}
#pragma mark 拍照
- (IBAction)takeMedia:(id)sender {
// 根據(jù)設備輸出獲得連接
AVCaptureConnection *connection = [self.imageOutput connectionWithMediaType:AVMediaTypeVideo];
// 通過連接獲得設備的輸出數(shù)據(jù)
[self.imageOutput captureStillImageAsynchronouslyFromConnection:connection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
// 獲取輸出的JPG圖片
NSData *imgData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *image = [UIImage imageWithData:imgData];
self.imageView.image = image;
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil); //保存到相冊
self.captureLayer.hidden = YES;
self.canptureBtn.hidden = YES;
self.openCaptureBtn.hidden = NO;
[self.session stopRunning];
}];
}
@end
關于 AVFoundation 視頻錄制的使用推薦閱讀:ctolib:在 iOS 上捕獲 視頻
以及源碼:VideoCaptureDemo
配合使用 CoreImage 實現(xiàn)人臉識別
人臉識別過程分3個步驟:
- 首先建立人臉的【面紋數(shù)據(jù)庫】;
- 獲取當前人臉面像圖片;
- 用當前的面紋編碼與數(shù)據(jù)庫中的面紋編碼進行比對。
CIDetector 是 CoreImage 中的一個特征識別濾鏡。它可以找到圖片中的人臉,但是是誰無法判斷,需要數(shù)據(jù)庫。要想識別可以看 OpenCV 和 Face.com。
#pragma mark - 識別人臉
/**
識別人臉算法
@param image 輸入的圖片
*/
- (void)faceDetectWithImage:(UIImage *)image {
NSDictionary *imageOptions = [NSDictionary dictionaryWithObject:@(5) forKey:CIDetectorImageOrientation];
// 將圖像轉(zhuǎn)換為CIImage
CIImage *personciImage = [CIImage imageWithCGImage:image.CGImage];
// 設置識別參數(shù)
NSDictionary *opts = [NSDictionary dictionaryWithObject:
CIDetectorAccuracyHigh forKey:CIDetectorAccuracy];
CIContext *context = [CIContext contextWithOptions:nil];
//聲明一個CIDetector,并設定識別器類型為人臉識別
CIDetector *faceDetector=[CIDetector detectorOfType:CIDetectorTypeFace context:context options:opts];
// 識別出人臉數(shù)組
// featuresInImage:方法 識別器會找到所給圖像中的人臉,最后返回一個人臉數(shù)組
NSArray *features = [faceDetector featuresInImage:personciImage options:imageOptions];
// 得到圖片的尺寸
CGSize inputImageSize = [personciImage extent].size;
// 利用仿射變換將image沿Y軸對稱
CGAffineTransform transform = CGAffineTransformScale(CGAffineTransformIdentity, 1, -1);
// 將圖片上移
transform = CGAffineTransformTranslate(transform, 0, -inputImageSize.height);
// 遍歷識別到的人臉
for (CIFaceFeature *faceFeature in features) {
// 獲取人臉的frame
CGRect faceViewBounds = CGRectApplyAffineTransform(faceFeature.bounds, transform);
CGSize viewSize = _imageView.bounds.size;
CGFloat scale = MIN(viewSize.width / inputImageSize.width,
viewSize.height / inputImageSize.height);
CGFloat offsetX = (viewSize.width - inputImageSize.width * scale) / 2;
CGFloat offsetY = (viewSize.height - inputImageSize.height * scale) / 2;
// 縮放
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(scale, scale);
// 修正
faceViewBounds = CGRectApplyAffineTransform(faceViewBounds, scaleTransform);
faceViewBounds.origin.x += offsetX;
faceViewBounds.origin.y += offsetY;
// 描繪人臉區(qū)域
UIView *faceView = [[UIView alloc] initWithFrame:faceViewBounds];
faceView.layer.borderWidth = 2;
faceView.layer.borderColor = [UIColor redColor].CGColor;
[_imageView addSubview:faceView];
// 判斷是否有左眼位置
if(faceFeature.hasLeftEyePosition){}
// 判斷是否有右眼位置
if(faceFeature.hasRightEyePosition){}
// 判斷是否有嘴位置
if(faceFeature.hasMouthPosition){}
// 判斷是否微笑
if (faceFeature.hasSmile){}
}
// 裁剪識別到的人臉
if ([features count]>0) {
CIImage *image = [personciImage imageByCroppingToRect:[[features objectAtIndex:0] bounds]];
UIImage *face = [UIImage imageWithCGImage:[context createCGImage:image fromRect:image.extent]];
// 顯示裁剪后的人臉
_imageView.image = face;
NSLog(@"識別人臉數(shù)::%lu",(unsigned long)[features count]);
}
}
關于拍照完成后使用人臉識別并裁剪,顯示的人臉圖片方向自動逆時針旋轉(zhuǎn)90°顯示的問題:
原因:iPhone 默認的方向是HOME 鍵位于左邊的方向,故豎屏情況原始圖像被拍攝后的EXIF方向值是6,被裁剪后方向信息會被刪除,置為1。
解決方法:在人像識別之前先修改圖像的EXIF信息為1,再進行人像識別,CIDetectorImageOrientation 值也需要改為1。

參考
libfacedetection – ?? 9.8 k,C++ 人臉識別 包含正面和多視角人臉檢測兩個算法.優(yōu)點:速度快(OpenCV haar+adaboost的2-3倍), 準確度高 (FDDB非公開類評測排名第二),能估計人臉角度
-
GitHub: PBJVision ?? 1.9 k
iOS Media Capture - 具有觸摸錄制視頻、慢動作和攝影的功能。
PBJVision 是一個適用于 iOS 的相機庫,它可以輕松地在你的 iOS 應用中集成特殊的捕捉功能,定制相機界面。
GitHub: TGCameraViewController:?? 1.4 k-(已不再維護)基于 AVFoundation 的自定義相機。樣式漂亮,輕量并且可以很容易地集成到 iOS 項目中。
GitHub: RSKImageCropper ?? 2.3 k-適用于iOS的圖片裁剪器,類似Contacts app,可上下左右移動圖片選取最合適的區(qū)域