BDFaceLivenessViewController.m 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. //
  2. // LivenessViewController.m
  3. // FaceSDKSample_IOS
  4. //
  5. // Created by 阿凡树 on 2017/5/23.
  6. // Copyright © 2017年 Baidu. All rights reserved.
  7. //
  8. #import "BDFaceLivenessViewController.h"
  9. #import "BDFaceSuccessViewController.h"
  10. #import "BDFaceLivingConfigModel.h"
  11. #import "BDFaceImageShow.h"
  12. #import <IDLFaceSDK/IDLFaceSDK.h>
  13. #import "BDFaceLog.h"
  14. @interface BDFaceLivenessViewController ()
  15. {
  16. UIImageView * newImage;
  17. BOOL isPaint;
  18. }
  19. @property (nonatomic, strong) NSArray *livenessArray;
  20. @property (nonatomic, assign) BOOL order;
  21. @property (nonatomic, assign) NSInteger numberOfLiveness;
  22. @property (nonatomic, assign) BOOL isAnimating;
  23. @end
  24. @implementation BDFaceLivenessViewController
  25. - (void)viewDidLoad {
  26. [super viewDidLoad];
  27. // 刻度线背颜色
  28. self.circleProgressView.lineBgColor = [UIColor colorWithRed:102 / 255.0 green:102 / 255.0 blue:102 / 255.0 alpha:1 / 1.0];
  29. // 刻度线进度颜色
  30. self.circleProgressView.scaleColor = [UIColor colorWithRed:0 / 255.0 green:186 / 255.0 blue:242 / 255.0 alpha:1 / 1.0];
  31. [self.view addSubview:self.circleProgressView];
  32. // 提示动画设置
  33. [self.view addSubview:self.remindAnimationView];
  34. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  35. [self.remindAnimationView setActionImages];
  36. });
  37. }
  38. - (void)viewWillAppear:(BOOL)animated {
  39. [super viewWillAppear:animated];
  40. [[IDLFaceLivenessManager sharedInstance] startInitial];
  41. }
  42. - (void)viewDidDisappear:(BOOL)animated {
  43. [super viewDidDisappear:animated];
  44. [IDLFaceLivenessManager.sharedInstance reset];
  45. }
  46. - (void)onAppBecomeActive {
  47. [super onAppBecomeActive];
  48. [[IDLFaceLivenessManager sharedInstance] livenesswithList:_livenessArray order:_order numberOfLiveness:_numberOfLiveness];
  49. }
  50. - (void)onAppWillResignAction {
  51. [super onAppWillResignAction];
  52. [IDLFaceLivenessManager.sharedInstance reset];
  53. }
  54. - (void)didReceiveMemoryWarning {
  55. [super didReceiveMemoryWarning];
  56. // Dispose of any resources that can be recreated.
  57. }
  58. - (void)livenesswithList:(NSArray *)livenessArray order:(BOOL)order numberOfLiveness:(NSInteger)numberOfLiveness {
  59. _livenessArray = [NSArray arrayWithArray:livenessArray];
  60. _order = order;
  61. _numberOfLiveness = numberOfLiveness;
  62. [[IDLFaceLivenessManager sharedInstance] livenesswithList:livenessArray order:order numberOfLiveness:numberOfLiveness];
  63. }
  64. - (void)faceProcesss:(UIImage *)image {
  65. if (self.hasFinished) {
  66. return;
  67. }
  68. dispatch_async(dispatch_get_main_queue(), ^{
  69. self.isAnimating = [self.remindAnimationView isActionAnimating];
  70. });
  71. /*
  72. 显示提示动画的过程中还可以做动作
  73. */
  74. // if (self.isAnimating){
  75. // return;
  76. // }
  77. __weak typeof(self) weakSelf = self;
  78. [[IDLFaceLivenessManager sharedInstance] livenessNormalWithImage:image previewRect:self.previewRect detectRect:self.detectRect completionHandler:^(NSDictionary *images, FaceInfo *faceInfo, LivenessRemindCode remindCode) {
  79. // NSLog(@"remindCode = %lu", (unsigned long)remindCode);
  80. /*
  81. 此注释里的代码用于显示人脸框,调试过程中需要显示人脸款可打开注释
  82. // 绘制人脸框功能,开发者可以通过观察人脸框_faceRectFit 在 previewRect 包含关系判断是框内还是框外
  83. dispatch_async(dispatch_get_main_queue(), ^{
  84. CGRect faceRect = [BDFaceQualityUtil getFaceRect:faceInfo.landMarks withCount:faceInfo.landMarks.count];
  85. CGRect faceRectFit = [BDFaceUtil convertRectFrom:faceRect image:image previewRect:previewRect];
  86. if (!isPaint) {
  87. newImage= [[UIImageView alloc]init];
  88. [self.view addSubview:newImage];
  89. isPaint = !isPaint;
  90. }
  91. newImage = [self creatRectangle:newImage withRect:faceRectFit withcolor:[UIColor blackColor]];
  92. });
  93. */
  94. switch (remindCode) {
  95. case LivenessRemindCodeOK: {
  96. weakSelf.hasFinished = YES;
  97. [self warningStatus:CommonStatus warning:@"非常好"];
  98. if (images[@"image"] != nil && [(NSArray *)images[@"image"] count] != 0) {
  99. NSArray *imageArr = images[@"image"];
  100. for (FaceCropImageInfo * image in imageArr) {
  101. NSLog(@"cropImageWithBlack %f %f", image.cropImageWithBlack.size.height, image.cropImageWithBlack.size.width);
  102. NSLog(@"originalImage %f %f", image.originalImage.size.height, image.originalImage.size.width);
  103. }
  104. NSMutableArray *imagesAllKeysArr = [NSMutableArray arrayWithArray:images.allKeys];
  105. if ([imagesAllKeysArr containsObject:@"image"]) {
  106. [imagesAllKeysArr removeObject:@"image"];
  107. }
  108. NSString * key = @"";
  109. NSInteger num = imagesAllKeysArr.count;
  110. switch (num) {
  111. case 0:
  112. key = @"";
  113. break;
  114. case 1:
  115. key = [NSString stringWithFormat:@"%@",imagesAllKeysArr.firstObject];
  116. break;
  117. default:
  118. key = [NSString stringWithFormat:@"%@",imagesAllKeysArr[((imagesAllKeysArr.count - 1) >=0 )? (imagesAllKeysArr.count - 1) : 0]];
  119. break;
  120. }
  121. NSString * base64Str = images[key];
  122. // NSData * showData = [[NSData alloc]initWithBase64EncodedString:base64Str options:NSDataBase64DecodingIgnoreUnknownCharacters];
  123. // UIImage *myImage = [UIImage imageWithData:showData];
  124. [RQ_CHECKBODY_MANAGER setActionImageString:base64Str];
  125. FaceCropImageInfo * bestImage = imageArr[0];
  126. [[BDFaceImageShow sharedInstance] setSuccessImage:bestImage.originalImage];
  127. [[BDFaceImageShow sharedInstance] setSilentliveScore:bestImage.silentliveScore];
  128. dispatch_async(dispatch_get_main_queue(), ^{
  129. // UIViewController* fatherViewController = weakSelf.presentingViewController;
  130. // [weakSelf dismissViewControllerAnimated:YES completion:^{
  131. // BDFaceSuccessViewController *avc = [[BDFaceSuccessViewController alloc] init];
  132. // avc.modalPresentationStyle = UIModalPresentationFullScreen;
  133. // [fatherViewController presentViewController:avc animated:YES completion:nil];
  134. // [self closeAction];
  135. // }];
  136. [self closeActionWithIsSuccess:YES];
  137. });
  138. }
  139. dispatch_async(dispatch_get_main_queue(), ^{
  140. [self.remindAnimationView stopActionAnimating];
  141. });
  142. [self singleActionSuccess:true];
  143. [BDFaceLog makeLogAfterFinishRecognizeAction:YES];
  144. break;
  145. }
  146. case LivenessRemindCodePitchOutofDownRange:
  147. [self warningStatus:PoseStatus warning:@"请略微抬头" conditionMeet:false];
  148. [self singleActionSuccess:false];
  149. break;
  150. case LivenessRemindCodePitchOutofUpRange:
  151. [self warningStatus:PoseStatus warning:@"请略微低头" conditionMeet:false];
  152. [self singleActionSuccess:false];
  153. break;
  154. case LivenessRemindCodeYawOutofRightRange:
  155. [self warningStatus:PoseStatus warning:@"请略微向右转头" conditionMeet:false];
  156. [self singleActionSuccess:false];
  157. break;
  158. case LivenessRemindCodeYawOutofLeftRange:
  159. [self warningStatus:PoseStatus warning:@"请略微向左转头" conditionMeet:false];
  160. [self singleActionSuccess:false];
  161. break;
  162. case LivenessRemindCodePoorIllumination:
  163. [self warningStatus:CommonStatus warning:@"请使环境光线再亮些" conditionMeet:false];
  164. [self singleActionSuccess:false];
  165. break;
  166. case LivenessRemindCodeNoFaceDetected:
  167. [self warningStatus:CommonStatus warning:@"把脸移入框内" conditionMeet:false];
  168. [self singleActionSuccess:false];
  169. break;
  170. case LivenessRemindCodeImageBlured:
  171. [self warningStatus:PoseStatus warning:@"请握稳手机" conditionMeet:false];
  172. [self singleActionSuccess:false];
  173. break;
  174. case LivenessRemindCodeOcclusionLeftEye:
  175. [self warningStatus:occlusionStatus warning:@"左眼有遮挡" conditionMeet:false];
  176. [self singleActionSuccess:false];
  177. break;
  178. case LivenessRemindCodeOcclusionRightEye:
  179. [self warningStatus:occlusionStatus warning:@"右眼有遮挡" conditionMeet:false];
  180. [self singleActionSuccess:false];
  181. break;
  182. case LivenessRemindCodeOcclusionNose:
  183. [self warningStatus:occlusionStatus warning:@"鼻子有遮挡" conditionMeet:false];
  184. [self singleActionSuccess:false];
  185. break;
  186. case LivenessRemindCodeOcclusionMouth:
  187. [self warningStatus:occlusionStatus warning:@"嘴巴有遮挡" conditionMeet:false];
  188. [self singleActionSuccess:false];
  189. break;
  190. case LivenessRemindCodeOcclusionLeftContour:
  191. [self warningStatus:occlusionStatus warning:@"左脸颊有遮挡" conditionMeet:false];
  192. [self singleActionSuccess:false];
  193. break;
  194. case LivenessRemindCodeOcclusionRightContour:
  195. [self warningStatus:occlusionStatus warning:@"右脸颊有遮挡" conditionMeet:false];
  196. [self singleActionSuccess:false];
  197. break;
  198. case LivenessRemindCodeOcclusionChinCoutour:
  199. [self warningStatus:occlusionStatus warning:@"下颚有遮挡" conditionMeet:false];
  200. [self singleActionSuccess:false];
  201. break;
  202. case LivenessRemindCodeLeftEyeClosed:
  203. [self warningStatus:occlusionStatus warning:@"左眼未睁开" conditionMeet:false];
  204. [self singleActionSuccess:false];
  205. break;
  206. case LivenessRemindCodeRightEyeClosed:
  207. [self warningStatus:occlusionStatus warning:@"右眼未睁开" conditionMeet:false];
  208. [self singleActionSuccess:false];
  209. break;
  210. case LivenessRemindCodeTooClose:
  211. [self warningStatus:CommonStatus warning:@"请将脸部离远一点" conditionMeet:false];
  212. [self singleActionSuccess:false];
  213. break;
  214. case LivenessRemindCodeTooFar:
  215. [self warningStatus:CommonStatus warning:@"请将脸部靠近一点" conditionMeet:false];
  216. [self singleActionSuccess:false];
  217. break;
  218. case LivenessRemindCodeBeyondPreviewFrame:
  219. [self warningStatus:CommonStatus warning:@"把脸移入框内" conditionMeet:false];
  220. [self singleActionSuccess:false];
  221. break;
  222. case LivenessRemindCodeLiveEye:
  223. [self warningStatus:CommonStatus warning:@"眨眨眼" conditionMeet:true];
  224. [self singleActionSuccess:false];
  225. break;
  226. case LivenessRemindCodeLiveMouth:
  227. [self warningStatus:CommonStatus warning:@"张张嘴" conditionMeet:true];
  228. [self singleActionSuccess:false];
  229. break;
  230. case LivenessRemindCodeLiveYawRight:
  231. [self warningStatus:CommonStatus warning:@"向右缓慢转头" conditionMeet:true];
  232. [self singleActionSuccess:false];
  233. break;
  234. case LivenessRemindCodeLiveYawLeft:
  235. [self warningStatus:CommonStatus warning:@"向左缓慢转头" conditionMeet:true];
  236. [self singleActionSuccess:false];
  237. break;
  238. case LivenessRemindCodeLivePitchUp:
  239. [self warningStatus:CommonStatus warning:@"缓慢抬头" conditionMeet:true];
  240. [self singleActionSuccess:false];
  241. break;
  242. case LivenessRemindCodeLivePitchDown:
  243. [self warningStatus:CommonStatus warning:@"缓慢低头" conditionMeet:true];
  244. [self singleActionSuccess:false];
  245. break;
  246. // case LivenessRemindCodeLiveYaw:
  247. // [self warningStatus:CommonStatus warning:@"左右摇头" conditionMeet:true];
  248. // [self singleActionSuccess:false];
  249. // break;
  250. case LivenessRemindCodeSingleLivenessFinished:
  251. {
  252. [[IDLFaceLivenessManager sharedInstance] livenessProcessHandler:^(float numberOfLiveness, float numberOfSuccess, LivenessActionType currenActionType) {
  253. NSLog(@"Finished 非常好 %d %d %d", (int)numberOfLiveness, (int)numberOfSuccess, (int)currenActionType);
  254. dispatch_async(dispatch_get_main_queue(), ^{
  255. [self.circleProgressView setPercent:(CGFloat)(numberOfSuccess / numberOfLiveness)];
  256. });
  257. }];
  258. [self warningStatus:CommonStatus warning:@"非常好" conditionMeet:true];
  259. [self singleActionSuccess:true];
  260. dispatch_async(dispatch_get_main_queue(), ^{
  261. [self.remindAnimationView stopActionAnimating];
  262. });
  263. }
  264. break;
  265. case LivenessRemindCodeFaceIdChanged:
  266. {
  267. [[IDLFaceLivenessManager sharedInstance] livenessProcessHandler:^(float numberOfLiveness, float numberOfSuccess, LivenessActionType currenActionType) {
  268. NSLog(@"face id changed %d %d %d", (int)numberOfLiveness, (int)numberOfSuccess, (int)currenActionType);
  269. dispatch_async(dispatch_get_main_queue(), ^{
  270. [self.circleProgressView setPercent:0];
  271. });
  272. }];
  273. [self warningStatus:CommonStatus warning:@"把脸移入框内" conditionMeet:true];
  274. }
  275. break;
  276. case LivenessRemindCodeVerifyInitError: {
  277. if (self.faceCheckBodyCompletedBlock) {
  278. self.faceCheckBodyCompletedBlock(NO);
  279. }
  280. [self warningStatus:CommonStatus warning:@"验证失败"];
  281. }
  282. break;
  283. // case LivenessRemindCodeVerifyDecryptError:
  284. // [self warningStatus:CommonStatus warning:@"验证失败"];
  285. // break;
  286. // case LivenessRemindCodeVerifyInfoFormatError:
  287. // [self warningStatus:CommonStatus warning:@"验证失败"];
  288. // break;
  289. // case LivenessRemindCodeVerifyExpired:
  290. // [self warningStatus:CommonStatus warning:@"验证失败"];
  291. // break;
  292. // case LivenessRemindCodeVerifyMissRequiredInfo:
  293. // [self warningStatus:CommonStatus warning:@"验证失败"];
  294. // break;
  295. // case LivenessRemindCodeVerifyInfoCheckError:
  296. // [self warningStatus:CommonStatus warning:@"验证失败"];
  297. // break;
  298. // case LivenessRemindCodeVerifyLocalFileError:
  299. // [self warningStatus:CommonStatus warning:@"验证失败"];
  300. // break;
  301. // case LivenessRemindCodeVerifyRemoteDataError:
  302. // [self warningStatus:CommonStatus warning:@"验证失败"];
  303. // break;
  304. case LivenessRemindCodeTimeout: {
  305. // 时间超时,重置之前采集数据
  306. [[IDLFaceLivenessManager sharedInstance] reset];
  307. dispatch_async(dispatch_get_main_queue(), ^{
  308. // 时间超时,ui进度重置0
  309. [self.circleProgressView setPercent:0];
  310. [self isTimeOut:YES];
  311. });
  312. [BDFaceLog makeLogAfterFinishRecognizeAction:NO];
  313. break;
  314. }
  315. case LivenessRemindActionCodeTimeout:{
  316. [[IDLFaceLivenessManager sharedInstance] livenessProcessHandler:^(float numberOfLiveness, float numberOfSuccess, LivenessActionType currenActionType) {
  317. NSLog(@"动作超时 %d %d %d", (int)numberOfLiveness, (int)numberOfSuccess, (int)currenActionType);
  318. dispatch_async(dispatch_get_main_queue(), ^{
  319. [self.remindAnimationView startActionAnimating:(int)currenActionType];
  320. });
  321. }];
  322. [BDFaceLog makeLogAfterFinishRecognizeAction:NO];
  323. break;
  324. }
  325. case LivenessRemindCodeConditionMeet: {
  326. }
  327. break;
  328. default:
  329. break;
  330. }
  331. }];
  332. }
  333. - (void)selfReplayFunction{
  334. [[IDLFaceLivenessManager sharedInstance] reset];
  335. BDFaceLivingConfigModel* model = [BDFaceLivingConfigModel sharedInstance];
  336. [[IDLFaceLivenessManager sharedInstance] livenesswithList:model.liveActionArray order:model.isByOrder numberOfLiveness:model.numOfLiveness];
  337. }
  338. - (void)warningStatus:(WarningStatus)status warning:(NSString *)warning conditionMeet:(BOOL)meet{
  339. [self warningStatus:status warning:warning];
  340. }
  341. @end