DFCaptureController介绍
1. DFCaptureControllerDelegate协议
/// 检测句柄初始化回调
/// @param errorCode 错误码
- (void)initCompletedWithErrorCode:(int)errorCode;
/// 检测成功回调
/// @param image 检测到的卡证图片
/// @param cardSideType 卡证类型
/// @param isCopy 是否是复印件
- (void)detectFinished:(UIImage *)image cardSideType:(DFCardDetectedSide)cardSideType isCopy:(BOOL)isCopy;
/// 开启自动上传识别,识别成功回调
/// @param image 检测到的卡证图片
/// @param cardSideType 卡证类型
/// @param isCopy 是否是复印件
/// @param result 识别结果
- (void)recognizeSucessfully:(UIImage *)image cardSideType:(DFCardDetectedSide)cardSideType isCopy:(BOOL)isCopy result:(NSDictionary *)result;
/// 开启自动上传识别,识别失败回调
/// @param image 检测到的卡证图片
/// @param cardSideType 卡证类型
/// @param isCopy 是否是复印件
/// @param errorMessage 错误信息
- (void)recognizeFailed:(UIImage *)image cardSideType:(DFCardDetectedSide)cardSideType isCopy:(BOOL)isCopy errorMessage:(NSString *)errorMessage;
2.初始化
/// 检测页面初始化
/// @param cardType 卡证类型
/// @param filterCopy 是否过滤复印件
/// @param delegate 代理
/// @param autoRecognize 是否自动上传识别
/// @param navigationController 导航控制器
+ (instancetype)pushCaptureControllerWithCardType:(DFCardDetectedType)cardType
filterCopy:(BOOL)filterCopy
delegate:(id<DFCaptureControllerDelegate>)delegate
autoRecognize:(BOOL)autoRecognize
navigationController:(UINavigationController *)navigationController;
3.自定义相机
- (AVCaptureVideoPreviewLayer *)previewLayer
{
if (_previewLayer == nil) {
_previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
_previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
}
return _previewLayer;
}
- (AVCaptureDevice *)device
{
if (_device == nil) {
_device = [self cameraWithPosition:AVCaptureDevicePositionBack];
if ([_device lockForConfiguration:nil]) {
//自动闪光灯
if ([_device isFlashModeSupported:AVCaptureFlashModeAuto]) {
[_device setFlashMode:AVCaptureFlashModeAuto];
}
//自动白平衡
if ([_device isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance]) {
[_device setWhiteBalanceMode:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance];
}
//自动对焦
if ([_device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {
[_device setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
}
//自动曝光
if ([_device isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) {
[_device setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
}
int frameRate = 30;
CMTime frameDuration = kCMTimeInvalid;
frameDuration = CMTimeMake(1, frameRate);
_device.activeVideoMaxFrameDuration = frameDuration;
_device.activeVideoMinFrameDuration = frameDuration;
[_device unlockForConfiguration];
}
}
return _device;
}
- (AVCaptureDeviceInput *)input
{
if (_input == nil) {
_input = [[AVCaptureDeviceInput alloc] initWithDevice:self.device error:nil];
}
return _input;
}
- (AVCaptureVideoDataOutput *)videoDataOutput
{
if (_videoDataOutput == nil) {
_videoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
[_videoDataOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]];
}
return _videoDataOutput;
}
- (AVCaptureSession *)session
{
if (_session == nil) {
_session = [[AVCaptureSession alloc] init];
if ([_session canAddInput:self.input]) {
[_session addInput:self.input];
}
if ([_session canAddOutput:self.videoDataOutput]) {
[_session addOutput:self.videoDataOutput];
}
if ([_session canSetSessionPreset:AVCaptureSessionPreset1280x720]) {
_session.sessionPreset = AVCaptureSessionPreset1280x720;
}
}
return _session;
}
- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position
{
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in devices)
if (device.position == position) {
return device;
}
return nil;
}
4.UI布局添加检测区域遮罩
- (void)setupSubViews
{
self.view.backgroundColor = [UIColor whiteColor];
UIView *preview = [[UIView alloc] initWithFrame:self.view.bounds];
preview.backgroundColor = [UIColor whiteColor];
[self.view addSubview:preview];
self.preview = preview;
CGRect bounds = self.preview.bounds;
self.previewLayer.frame = bounds;
self.previewLayer.position = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
self.previewLayer.backgroundColor = [UIColor whiteColor].CGColor;
[self.preview.layer addSublayer:self.previewLayer];
if ([self.previewLayer.connection isVideoOrientationSupported]) {
[self.previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
}
CGFloat width = [UIScreen mainScreen].bounds.size.width * 0.9;
CGFloat x = ([UIScreen mainScreen].bounds.size.width - width) / 2.0;
CGFloat ratio = DFDETECTREGIONSCALE;
self.windowFrame = CGRectMake(x, 232 / 2.0, width, width / ratio);
DFCardCaptureView *captureView = [[DFCardCaptureView alloc] initWithFrame:self.preview.bounds andWindowFrame:self.windowFrame superLayer:self.previewLayer];
self.captureView = captureView;
}
5.初始化卡证检测
- (void)setupCardsDetector
{
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"df_cards_detector" ofType:@"bundle"];
NSString *licensePath = [NSString stringWithFormat:@"%@/DFLicense", bundlePath];
DFCardsDetector *detector = [[DFCardsDetector alloc] initWithResourceBundlePath:bundlePath licensePath:licensePath delegate:self];
[detector setCardDetectedType:self.cardType filterCopy:self.filterCopy];
self.detector = detector;
}
4.实现卡证检测代理方法
初始化回调
- (void)initCompletedWithErrorCode:(int)errorCode
{
if (errorCode != 0) {
[self.navigationController popViewControllerAnimated:YES];
if (self.delegate && [self.delegate respondsToSelector:@selector(initCompletedWithErrorCode:)]) {
[self.delegate initCompletedWithErrorCode:errorCode];
}
}
}
检测状态回调
- (void)detectCard:(BOOL)isDetectedCard
{
if (isDetectedCard) {
[self.captureView setLineColor:[UIColor greenColor]];
} else {
[self.captureView setLineColor:[UIColor redColor]];
}
}
检测完成回调
- (void)detectFinished:(UIImage *)image cardSideType:(DFCardDetectedSide)cardSideType isCopy:(BOOL)isCopy
{
[self stopScanning];
if (self.autoRecognize) {
__weak __typeof(self) weakSelf = self;
DFRecognizeController *recognizeController = [[DFRecognizeController alloc] initWithImage:image cardSide:cardSideType cardType:self.cardType isCopy:isCopy successBlock:^(UIImage * _Nonnull image, DFCardDetectedSide cardSide, BOOL isCopy, NSDictionary * _Nonnull result) {
if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(recognizeSucessfully:cardSideType:isCopy:result:)]) {
[weakSelf.delegate recognizeSucessfully:image cardSideType:cardSideType isCopy:isCopy result:result];
}
} failedBlock:^(NSString * _Nonnull errorMessage) {
if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(recognizeFailed:cardSideType:isCopy:errorMessage:)]) {
[weakSelf.delegate recognizeFailed:image cardSideType:cardSideType isCopy:isCopy errorMessage:errorMessage];
}
}];
[self addChildViewController:recognizeController];
[self.view addSubview:recognizeController.view];
} else {
if (self.delegate && [self.delegate respondsToSelector:@selector(detectFinished:cardSideType:isCopy:)]) {
[self.delegate detectFinished:image cardSideType:cardSideType isCopy:isCopy];
}
}
}
5.开始卡证检测
在相机回调中调用卡证检测对象的检测方法。
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
if ([connection isVideoOrientationSupported]) {
[connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
}
// detect
CGRect detectRect = self.windowFrame;
detectRect.origin.y -= self.statusBarHeight > 0 ? 20 : 0;
[self.detector detectWithCMSampleBuffer:sampleBuffer detectRect:detectRect previewSize:CGSizeMake(1280, 720) degree:0];
}