1.GPUImage
GPUImage是一个很强大的图形图像渲染库,可以通过各种滤镜渲染出很多牛逼的效果,并且不消耗CPU,因为它用的是GPU进行的。最近接触了它的关于相机方面的功能,导入GPUImage库后,可以用很简单的代码写出一个小的相机应用,主要用到 GPUImageVedioCamera 和继承自它的GPUImageStillCamera下面用代码分析:
因为相机应用要能拍照,所以我就直接用GPUImageStillCamera了:
//初始化一个摄像头对象,两个参数分别表示 录制视频的格式 和 使用前置还是后置摄像头
_stillCamera = [[GPUImageStillCamera alloc]initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:AVCaptureDevicePositionFront];
//设置摄像头输出图像的方向
_stillCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
// 设置前置摄像头和后置摄像头是否进行镜像
_stillCamera.horizontallyMirrorRearFacingCamera = NO;
_stillCamera.horizontallyMirrorFrontFacingCamera = YES;
//初始化一个滤镜
_filter = [[GPUImageColorMatrixFilter alloc]init];
//给摄像头加上该滤镜
[_stillCamera addTarget:_filter];
//将当前控制器的view设置为输出口
GPUImageView *filterView = (GPUImageView *)self.ImageView;
//使摄像头经过滤镜后的图像可以显示到当前控制器的view上
[_filter addTarget:filterView];
//开启改摄像头开始捕获图像
[_stillCamera startCameraCapture];
这样,即可以捕捉到当前摄像头的拍摄的图像了,并且我们可以根据需要选取不同的filter进行添加,可以进行实时渲染的。
如果要进行拍照,也就是存储当前时刻图像,直接调用下面的方法:
-(void)capturePhoto
{
//捕捉到当前图像,并存进processedImage
[_stillCamera capturePhotoAsImageProcessedUpToFilter:_filter withCompletionHandler:^(UIImage *processedImage, NSError *error) {
// 保存到相册
[self.library writeImageToSavedPhotosAlbum:processedImage.CGImage metadata:nil completionBlock:^(NSURL *assetURL, NSError *error) {
if (error)
{
NSLog(@"ERROR: the image failed to be written");
}
else
{
NSLog(@"PHOTO SAVED - assetURL: %@", assetURL);
}
}];
}];
}
这里我是存进系统相册里, capturePhoto的方式很多,可以压缩成 jpeg ,png 等等,具体可以查看API。
这样一个简单相机就完成了~
2.人脸检测
无论用GPUImage封装的代码还是直接调用系统API启动摄像头,都会进行init Session,我们可以在init时开启检测人脸,代码如下:
AVCaptureMetadataOutput* metaDataOutput =[[AVCaptureMetadataOutput alloc] init];
if ([_captureSession canAddOutput:metaDataOutput]) {
[_captureSession addOutput:metaDataOutput];
//_faceUICache =[NSMutableDictionary dictionary];
NSArray* supportTypes =metaDataOutput.availableMetadataObjectTypes;
//NSLog(@"supports:%@",supportTypes);
if ([supportTypes containsObject:AVMetadataObjectTypeFace]) {
[metaDataOutput setMetadataObjectTypes:@[AVMetadataObjectTypeFace]];
[metaDataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
}
}
当在摄像头输入的数据中检测到人脸时,会调用代理方法:
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
if (metadataObjects.count != 0)
{
//在这里执行检测到人脸后要执行的代码
/*人脸数据存在metadataObjects这个数组里,数组中每一个元素对应一个metadataObject对象,该对象的各种属性对应人脸各种信息,具体可以查看API*/
}
}
要调节曝光基准点,即要调节相机的一些参数,这里需要AVCaptureDevice对象获取到摄像头,因为前面用了GPUPImage,所以它可以直接通过_stillCamera.inputCamera获取到该对象,下面这个方法即可根据传入的点来进行设置曝光基准点:
-(void)adjustExposureAtPoint:(CGPoint)point
{
NSError *error = nil;
AVCaptureDevice *camera = _stillCamera.inputCamera;
if([camera lockForConfiguration:&error])
{
camera.exposurePointOfInterest = point;
[camera setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
}
[camera unlockForConfiguration];
}
这样就可以调节曝光基准点了。
注意:调好相机的一些参数时每次都必须先锁定:[camera lockForConfiguration:&error]
并在设置完成后解锁: [camera unlockForConfiguration];