BDFaceLivenessViewController.m 16 KB

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