BDFaceBaseViewController.m 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. //
  2. // BDFaceBaseViewController.m
  3. // FaceSDKSample_IOS
  4. //
  5. // Created by 阿凡树 on 2017/5/23.
  6. // Copyright © 2017年 Baidu. All rights reserved.
  7. //
  8. #import "BDFaceBaseViewController.h"
  9. #import "BDFaceImageUtils.h"
  10. #import "BDFaceRemindView.h"
  11. #import "BDFaceLogoView.h"
  12. // 判断是否是ipad
  13. #define isPad ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
  14. // 判断iPhoneX
  15. #define IS_IPHONE_X ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) && !isPad : NO)
  16. // 判断iPHoneXr
  17. #define IS_IPHONE_Xr ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(828, 1792), [[UIScreen mainScreen] currentMode].size) && !isPad : NO)
  18. // 判断iPhoneXs
  19. #define IS_IPHONE_Xs ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) && !isPad : NO)
  20. // 判断iPhoneXs Max
  21. #define IS_IPHONE_Xs_Max ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1242, 2688), [[UIScreen mainScreen] currentMode].size) && !isPad : NO)
  22. #define scaleValue 0.70
  23. #define scaleValueX 0.80
  24. #define ScreenRect [UIScreen mainScreen].bounds
  25. #define ScreenWidth [UIScreen mainScreen].bounds.size.width
  26. #define ScreenHeight [UIScreen mainScreen].bounds.size.height
  27. /**iPhone6s为标准,乘以宽的比例*/
  28. #define KScaleX(value) ((value)/375.0f * ScreenWidth)
  29. /**iPhone6s为标准,乘以高的比例*/
  30. #define KScaleY(value) ((value)/667.0f * ScreenHeight)
  31. @interface BDFaceBaseViewController () <CaptureDataOutputProtocol>
  32. //{
  33. // UIImageView * newImage;
  34. // BOOL isPaint;
  35. //}
  36. @property (nonatomic, readwrite, retain) UILabel *remindLabel;
  37. @property (nonatomic, readwrite, retain) UIImageView *voiceImageView;
  38. @property (nonatomic, readwrite, retain) BDFaceRemindView * remindView;
  39. @property (nonatomic, readwrite, retain) UILabel * remindDetailLabel;
  40. // 超时相关控件
  41. @property (nonatomic, readwrite, retain) UIView *timeOutMainView;
  42. @property (nonatomic, readwrite, retain) UIImageView *timeOutImageView;
  43. @property (nonatomic, readwrite, retain) UILabel *timeOutLabel;
  44. @property (nonatomic, readwrite, retain) UIView *timeOutLine;
  45. @property (nonatomic, readwrite, retain) UIButton *timeOutRestartButton;
  46. @property (nonatomic, readwrite, retain) UILabel *timeOutRestartLabel;
  47. @property (nonatomic, readwrite, retain) UIView *timeOutLine2;
  48. @property (nonatomic, readwrite, retain) UIButton *timeOutRestartButton2;
  49. @property (nonatomic, readwrite, retain) UILabel *timeOutBackToMainLabel2;
  50. @end
  51. @implementation BDFaceBaseViewController
  52. - (void)dealloc
  53. {
  54. [[NSNotificationCenter defaultCenter] removeObserver:self];
  55. }
  56. - (void) setHasFinished:(BOOL)hasFinished {
  57. _hasFinished = hasFinished;
  58. if (hasFinished) {
  59. [self.videoCapture stopSession];
  60. self.videoCapture.delegate = nil;
  61. }
  62. }
  63. - (void)warningStatus:(WarningStatus)status warning:(NSString *)warning
  64. {
  65. __weak typeof(self) weakSelf = self;
  66. dispatch_async(dispatch_get_main_queue(), ^{
  67. if (status == PoseStatus) {
  68. [weakSelf.remindLabel setHidden:false];
  69. [weakSelf.remindView setHidden:false];
  70. [weakSelf.remindDetailLabel setHidden:false];
  71. weakSelf.remindDetailLabel.text = warning;
  72. weakSelf.remindLabel.text = @"请保持正脸";
  73. }else if (status == occlusionStatus) {
  74. [weakSelf.remindLabel setHidden:false];
  75. [weakSelf.remindView setHidden:true];
  76. [weakSelf.remindDetailLabel setHidden:false];
  77. weakSelf.remindDetailLabel.text = warning;
  78. weakSelf.remindLabel.text = @"脸部有遮挡";
  79. }else {
  80. [weakSelf.remindLabel setHidden:false];
  81. [weakSelf.remindView setHidden:true];
  82. [weakSelf.remindDetailLabel setHidden:true];
  83. weakSelf.remindLabel.text = warning;
  84. }
  85. });
  86. }
  87. - (void)singleActionSuccess:(BOOL)success
  88. {
  89. __weak typeof(self) weakSelf = self;
  90. dispatch_async(dispatch_get_main_queue(), ^{
  91. if (success) {
  92. }else {
  93. }
  94. });
  95. }
  96. - (void)viewDidLoad {
  97. [super viewDidLoad];
  98. // 用于播放视频流
  99. if (IS_IPHONE_X || IS_IPHONE_Xr || IS_IPHONE_Xs || IS_IPHONE_Xs_Max) {
  100. self.previewRect = CGRectMake(ScreenWidth*(1-scaleValueX)/2.0, ScreenHeight*(1-scaleValueX)/2.0, ScreenWidth*scaleValueX, ScreenHeight*scaleValueX);
  101. } else {
  102. self.previewRect = CGRectMake(ScreenWidth*(1-scaleValue)/2.0, ScreenHeight*(1-scaleValue)/2.0, ScreenWidth*scaleValue, ScreenHeight*scaleValue);
  103. }
  104. // 超时的view初始化,但是不添加到当前view内
  105. // 超时的最底层view,大小和屏幕大小一致,为了突出弹窗的view的效果,背景为灰色,0.7的透视度
  106. _timeOutMainView = [[UIView alloc] init];
  107. _timeOutMainView.frame = ScreenRect;
  108. _timeOutMainView.alpha = 0.7;
  109. _timeOutMainView.backgroundColor = [UIColor grayColor];
  110. // 弹出的主体view
  111. self.timeOutView = [[UIView alloc] init];
  112. self.timeOutView.frame = CGRectMake(KScaleX(20), KScaleY(179.3), ScreenWidth-KScaleX(40), KScaleY(281.3));
  113. self.timeOutView.backgroundColor = [UIColor colorWithRed:255 / 255.0 green:255 / 255.0 blue:255 / 255.0 alpha:1 / 1.0];
  114. self.timeOutView.layer.cornerRadius = 7.5;
  115. // 超时的image
  116. _timeOutImageView = [[UIImageView alloc] init];
  117. _timeOutImageView.frame = CGRectMake((ScreenWidth-76) / 2, KScaleY(217.3), 76, 76);
  118. _timeOutImageView.image = [UIImage imageNamed:@"icon_overtime"];
  119. // 超时的label
  120. _timeOutLabel = [[UILabel alloc] init];
  121. _timeOutLabel.frame = CGRectMake(KScaleX(40), KScaleY(309.3), ScreenWidth-KScaleX(80), 22);
  122. _timeOutLabel.text = @"人脸采集超时";
  123. _timeOutLabel.textAlignment = NSTextAlignmentCenter;
  124. _timeOutLabel.font = [UIFont fontWithName:@"PingFangSC-Medium" size:18];
  125. _timeOutLabel.textColor = [UIColor colorWithRed:0 / 255.0 green:0 / 255.0 blue:0 / 255.0 alpha:1 / 1.0];
  126. // 区分线
  127. _timeOutLine = [[UIView alloc] init];
  128. _timeOutLine.frame = CGRectMake((ScreenWidth-320) / 2, 361.2, 320, 0.3);
  129. _timeOutLine.backgroundColor = [UIColor colorWithRed:255 / 255.0 green:255 / 255.0 blue:255 / 255.0 alpha:1 / 1.0];
  130. // 重新开始采集button
  131. _timeOutRestartButton = [[UIButton alloc] initWithFrame:CGRectMake((ScreenWidth-320)/2, KScaleY(376), 320, 18)];
  132. [_timeOutRestartButton addTarget:self action:@selector(reStart:) forControlEvents:UIControlEventTouchUpInside];
  133. // 重新采集的文字label
  134. _timeOutRestartLabel = [[UILabel alloc] init];
  135. _timeOutRestartLabel.frame = CGRectMake((ScreenWidth-72) / 2, KScaleY(376.3), 72, 18);
  136. _timeOutRestartLabel.text = @"重新采集";
  137. _timeOutRestartLabel.font = [UIFont fontWithName:@"PingFangSC-Medium" size:18];
  138. _timeOutRestartLabel.textColor = [UIColor colorWithRed:0 / 255.0 green:186 / 255.0 blue:242 / 255.0 alpha:1 / 1.0];
  139. // 区分线
  140. _timeOutLine2 = [[UIView alloc] init];
  141. _timeOutLine2.frame = CGRectMake((ScreenWidth-320) / 2, 409.2, 320, 0.3);
  142. _timeOutLine2.backgroundColor = [UIColor colorWithRed:255 / 255.0 green:255 / 255.0 blue:255 / 255.0 alpha:1 / 1.0];
  143. // 回到首页的button
  144. _timeOutRestartButton2 = [[UIButton alloc] initWithFrame:CGRectMake((ScreenWidth-320)/2, KScaleY(424), 320, 18)];
  145. [_timeOutRestartButton2 addTarget:self action:@selector(backToPreView:) forControlEvents:UIControlEventTouchUpInside];
  146. // 回到首页的label
  147. _timeOutBackToMainLabel2 = [[UILabel alloc] init];
  148. _timeOutBackToMainLabel2.frame = CGRectMake((ScreenWidth-72) / 2, KScaleY(424.3), 72, 18);
  149. _timeOutBackToMainLabel2.text = @"回到首页";
  150. _timeOutBackToMainLabel2.font = [UIFont fontWithName:@"PingFangSC-Medium" size:18];
  151. _timeOutBackToMainLabel2.textColor = [UIColor colorWithRed:102 / 255.0 green:102 / 255.0 blue:102 / 255.0 alpha:1 / 1.0];
  152. // 初始化相机处理类
  153. self.videoCapture = [[BDFaceVideoCaptureDevice alloc] init];
  154. self.videoCapture.delegate = self;
  155. // 用于展示视频流的imageview
  156. self.displayImageView = [[UIImageView alloc] initWithFrame:self.previewRect];
  157. self.displayImageView.contentMode = UIViewContentModeScaleAspectFill;
  158. [self.view addSubview:self.displayImageView];
  159. CGRect circleRect =CGRectMake(ScreenWidth*(1-scaleValue)/2.0 , 175*ScreenHeight/667, ScreenWidth*scaleValue, ScreenWidth*scaleValue);
  160. // 画圈和圆形遮罩
  161. self.detectRect = CGRectMake(circleRect.origin.x , circleRect.origin.y, circleRect.size.width, circleRect.size.height*5/4);
  162. CGPoint centerPoint = CGPointMake(CGRectGetMidX(circleRect), CGRectGetMidY(circleRect));
  163. //创建一个View
  164. UIView *maskView = [[UIView alloc] initWithFrame:ScreenRect];
  165. maskView.backgroundColor = [UIColor whiteColor];
  166. maskView.alpha = 1;
  167. [self.view addSubview:maskView];
  168. //贝塞尔曲线 画一个带有圆角的矩形
  169. UIBezierPath *bpath = [UIBezierPath bezierPathWithRoundedRect:ScreenRect cornerRadius:0];
  170. //贝塞尔曲线 画一个圆形
  171. [bpath appendPath:[UIBezierPath bezierPathWithArcCenter:centerPoint radius:ScreenWidth*scaleValue / 2 startAngle:0 endAngle:2 * M_PI clockwise:NO]];
  172. //创建一个CAShapeLayer 图层
  173. CAShapeLayer *shapeLayer = [CAShapeLayer layer];
  174. shapeLayer.path = bpath.CGPath;
  175. // 添加图层蒙板
  176. maskView.layer.mask = shapeLayer;
  177. // 进度条view,活体检测页面
  178. CGRect circleProgressRect = CGRectMake(CGRectGetMinX(circleRect) - 13.7, CGRectGetMinY(circleRect) - 13.7, CGRectGetWidth(circleRect) + (13.7 * 2), CGRectGetHeight(circleRect) + (13.7 * 2));
  179. self.circleProgressView = [[BDFaceCycleProgressView alloc] initWithFrame:circleProgressRect];
  180. // 动作活体动画
  181. self.remindAnimationView = [[BDFaceRemindAnimationView alloc] initWithFrame:circleRect];
  182. // 提示框(动作)
  183. self.remindLabel = [[UILabel alloc] init];
  184. self.remindLabel.frame = CGRectMake(0, 103.3, ScreenWidth, 22);
  185. self.remindLabel.textAlignment = NSTextAlignmentCenter;
  186. self.remindLabel.textColor = [UIColor colorWithRed:0 / 255.0 green:0 / 255.0 blue:0 / 255.0 alpha:1 / 1.0];
  187. self.remindLabel.font = [UIFont boldSystemFontOfSize:22];
  188. [self.view addSubview:self.remindLabel];
  189. // 提示label(遮挡等问题)
  190. self.remindDetailLabel = [[UILabel alloc] init];
  191. self.remindDetailLabel.frame = CGRectMake(0, 139.3, ScreenWidth, 16);
  192. self.remindDetailLabel.font = [UIFont systemFontOfSize:16];
  193. self.remindDetailLabel.textColor = [UIColor colorWithRed:102 / 255.0 green:102 / 255.0 blue:102 / 255.0 alpha:1 / 1.0];
  194. self.remindDetailLabel.textAlignment = NSTextAlignmentCenter;
  195. [self.view addSubview:self.remindDetailLabel];
  196. [self.remindDetailLabel setHidden:true];
  197. UIButton *backButton = [[UIButton alloc] init];
  198. backButton.frame = CGRectMake(23.3, 43.3, 20, 20);
  199. [backButton setImage:[UIImage imageNamed:@"icon_titlebar_close"] forState:UIControlStateNormal];
  200. [backButton addTarget:self action:@selector(closeAction) forControlEvents:UIControlEventTouchUpInside];
  201. [self.view addSubview:backButton];
  202. // 音量imageView,可动态播放图片
  203. _voiceImageView = [[UIImageView alloc] init];
  204. _voiceImageView.frame = CGRectMake((ScreenWidth-22-20), 42.7, 22, 22);
  205. _voiceImageView.animationImages = [NSArray arrayWithObjects:
  206. [UIImage imageNamed:@"icon_titlebar_voice1"],
  207. [UIImage imageNamed:@"icon_titlebar_voice2"], nil];
  208. _voiceImageView.animationDuration = 2;
  209. _voiceImageView.animationRepeatCount = 0;
  210. NSNumber *soundMode = [[NSUserDefaults standardUserDefaults] objectForKey:@"SoundMode"];
  211. if (soundMode.boolValue){
  212. [_voiceImageView startAnimating];
  213. } else {
  214. _voiceImageView.image = [UIImage imageNamed:@"icon_titlebar_voice_close"];
  215. }
  216. _voiceImageView.userInteractionEnabled = YES;
  217. UITapGestureRecognizer *changeVoidceSet = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(changeVoidceSet:)];
  218. [_voiceImageView addGestureRecognizer:changeVoidceSet];
  219. [self.view addSubview:_voiceImageView];
  220. // 底部logo部分
  221. UIImageView *logoImageView = [[UIImageView alloc] init];
  222. logoImageView.frame = CGRectMake(0, CGRectGetMaxY(self.view.frame) - 221, ScreenWidth, 221);
  223. logoImageView.image = [UIImage imageNamed:@"bg_bottom_pattern"];
  224. [self.view addSubview:logoImageView];
  225. // 设置logo,底部的位置和大小,实例化显示
  226. BDFaceLogoView* logoView = [[BDFaceLogoView alloc] initWithFrame:CGRectMake(0, (ScreenHeight-15-12), ScreenWidth, 12)];
  227. [self.view addSubview:logoView];
  228. // 监听重新返回APP
  229. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignAction) name:UIApplicationWillResignActiveNotification object:nil];
  230. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
  231. /*
  232. 调试需要时可以打开以下注释
  233. 蓝色框:检测框(视频流返回的位置)
  234. 黄色框:采集框(人脸在采集框中都可以被识别,为了容错设置的宽松了一点)
  235. 圆框:采集显示框(人脸应该放置的检测位置)
  236. 绿色框:人脸最小框(通过最小框判定人脸是否过远,按照黄色框百分比:0.4宽)
  237. // UIImageView* circleImage= [[UIImageView alloc]init];
  238. // circleImage = [self creatRectangle:circleImage withRect:circleRect withcolor:[UIColor redColor]];
  239. // [self.view addSubview:circleImage];
  240. //
  241. // UIImageView* previewImage= [[UIImageView alloc]init];
  242. // previewImage = [self creatRectangle:previewImage withRect:self.previewRect withcolor:[UIColor yellowColor]];
  243. // [self.view addSubview:previewImage];
  244. //
  245. // UIImageView* detectImage= [[UIImageView alloc]init];
  246. // detectImage = [self creatRectangle:detectImage withRect:self.detectRect withcolor:[UIColor blueColor]];
  247. // [self.view addSubview:detectImage];
  248. //
  249. // CGRect _minRect = CGRectMake(CGRectGetMinX(self.detectRect)+CGRectGetWidth(self.detectRect)*(1-[[FaceSDKManager sharedInstance] minRectScale])/2, CGRectGetMinY(self.detectRect)+CGRectGetWidth(self.detectRect)*(1-[[FaceSDKManager sharedInstance] minRectScale])/2, CGRectGetWidth(self.detectRect)*[[FaceSDKManager sharedInstance] minRectScale], CGRectGetWidth(self.detectRect)*[[FaceSDKManager sharedInstance] minRectScale]);
  250. // UIImageView* minImage= [[UIImageView alloc]init];
  251. // minImage = [self creatRectangle:minImage withRect:_minRect withcolor:[UIColor greenColor]];
  252. // [self.view addSubview:minImage];
  253. */
  254. }
  255. #pragma mark-绘框方法
  256. - (UIImageView *)creatRectangle:(UIImageView *)imageView withRect:(CGRect) rect withcolor:(UIColor *)color{
  257. CAShapeLayer *lineLayer = [CAShapeLayer layer];
  258. //创建需要画线的视图
  259. UIBezierPath *linePath = [UIBezierPath bezierPath];
  260. //起点
  261. float x = rect.origin.x;
  262. float y = rect.origin.y;
  263. float W = rect.size.width;
  264. float H = rect.size.height;
  265. [linePath moveToPoint:CGPointMake(x, y)];
  266. //其他点
  267. [linePath addLineToPoint:CGPointMake(x + W, y)];
  268. [linePath addLineToPoint:CGPointMake(x + W, y + H)];
  269. [linePath addLineToPoint:CGPointMake(x, y + H)];
  270. [linePath addLineToPoint:CGPointMake(x, y)];
  271. lineLayer.lineWidth = 2;
  272. lineLayer.strokeColor = color.CGColor;
  273. lineLayer.path = linePath.CGPath;
  274. lineLayer.fillColor = nil; // 默认为blackColor
  275. imageView.layer.sublayers = nil;
  276. [imageView.layer addSublayer:lineLayer];
  277. return imageView;
  278. }
  279. - (void)isTimeOut:(BOOL)isOrNot {
  280. if (isOrNot){
  281. // 加载超时的view
  282. [self outTimeViewLoad];
  283. }
  284. }
  285. - (void)outTimeViewLoad{
  286. // 显示超时view,并停止视频流工作
  287. self.remindLabel.text = @"";
  288. self.remindDetailLabel.text = @"";
  289. self.videoCapture.runningStatus = NO;
  290. [self.videoCapture stopSession];
  291. [self.view addSubview:_timeOutMainView];
  292. [self.view addSubview:_timeOutView];
  293. [self.view addSubview:_timeOutImageView];
  294. [self.view addSubview:_timeOutLabel];
  295. [self.view addSubview:_timeOutRestartButton];
  296. [self.view addSubview:_timeOutLine];
  297. [self.view addSubview:_timeOutRestartLabel];
  298. [self.view addSubview:_timeOutLine2];
  299. [self.view addSubview:_timeOutRestartButton2];
  300. [self.view addSubview:_timeOutBackToMainLabel2];
  301. }
  302. - (void)outTimeViewUnload{
  303. // 关闭超时的view,恢复视频流工作
  304. self.videoCapture.runningStatus = YES;
  305. [self.videoCapture startSession];
  306. [_timeOutMainView removeFromSuperview];
  307. [_timeOutView removeFromSuperview];
  308. [_timeOutImageView removeFromSuperview];
  309. [_timeOutLabel removeFromSuperview];
  310. [_timeOutRestartButton removeFromSuperview];
  311. [_timeOutLine removeFromSuperview];
  312. [_timeOutRestartLabel removeFromSuperview];
  313. [_timeOutLine2 removeFromSuperview];
  314. [_timeOutBackToMainLabel2 removeFromSuperview];
  315. [_timeOutRestartButton2 removeFromSuperview];
  316. }
  317. - (void)viewDidDisappear:(BOOL)animated {
  318. [super viewDidDisappear:animated];
  319. self.hasFinished = YES;
  320. self.videoCapture.runningStatus = NO;
  321. }
  322. - (void)viewWillAppear:(BOOL)animated {
  323. [super viewWillAppear:animated];
  324. _hasFinished = NO;
  325. self.videoCapture.runningStatus = YES;
  326. [self.videoCapture startSession];
  327. }
  328. - (void)didReceiveMemoryWarning {
  329. [super didReceiveMemoryWarning];
  330. // Dispose of any resources that can be recreated.
  331. }
  332. - (void)faceProcesss:(UIImage *)image {
  333. }
  334. - (void)closeAction {
  335. _hasFinished = YES;
  336. self.videoCapture.runningStatus = NO;
  337. [self dismissViewControllerAnimated:YES completion:nil];
  338. if (self.faceCheckBodyCompletedBlock) {
  339. self.faceCheckBodyCompletedBlock(NO);
  340. }
  341. }
  342. #pragma mark - ButtonFunction
  343. - (IBAction)reStart:(UIButton *)sender{
  344. // 对应页面去补充
  345. dispatch_async(dispatch_get_main_queue(), ^{
  346. [self outTimeViewUnload];
  347. });
  348. // 调用相应的部分设置
  349. [self selfReplayFunction];
  350. }
  351. - (void)selfReplayFunction{
  352. // 相应的功能在采集/检测时候写
  353. }
  354. - (IBAction)backToPreView:(UIButton *)sender{
  355. [self dismissViewControllerAnimated:YES completion:nil];
  356. }
  357. #pragma mark - Notification
  358. - (void)onAppWillResignAction {
  359. _hasFinished = YES;
  360. }
  361. - (void)onAppBecomeActive {
  362. _hasFinished = NO;
  363. }
  364. #pragma mark - voiceImageView tap
  365. - (void)changeVoidceSet:(UITapGestureRecognizer *)sender {
  366. NSNumber *soundMode = [[NSUserDefaults standardUserDefaults] objectForKey:@"SoundMode"];
  367. NSLog(@"点击");
  368. if (soundMode.boolValue && _voiceImageView.animating) {
  369. [_voiceImageView stopAnimating];
  370. _voiceImageView.image = [UIImage imageNamed:@"icon_titlebar_voice_close"];
  371. // 之前是开启的,点击后关闭
  372. [[NSUserDefaults standardUserDefaults] setObject:@(NO) forKey:@"SoundMode"];
  373. // 活体声音
  374. [IDLFaceLivenessManager sharedInstance].enableSound = NO;
  375. // 图像采集声音
  376. [IDLFaceDetectionManager sharedInstance].enableSound = NO;
  377. } else {
  378. [_voiceImageView startAnimating];
  379. [[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:@"SoundMode"];
  380. // 活体声音
  381. [IDLFaceLivenessManager sharedInstance].enableSound = YES;
  382. // 图像采集声音
  383. [IDLFaceDetectionManager sharedInstance].enableSound = YES;
  384. }
  385. }
  386. #pragma mark - CaptureDataOutputProtocol
  387. - (void)captureOutputSampleBuffer:(UIImage *)image {
  388. if (_hasFinished) {
  389. return;
  390. }
  391. __weak typeof(self) weakSelf = self;
  392. dispatch_async(dispatch_get_main_queue(), ^{
  393. weakSelf.displayImageView.image = image;
  394. });
  395. [self faceProcesss:image];
  396. }
  397. - (void)captureError {
  398. NSString *errorStr = @"出现未知错误,请检查相机设置";
  399. AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
  400. if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied){
  401. errorStr = @"相机权限受限,请在设置中启用";
  402. }
  403. __weak typeof(self) weakSelf = self;
  404. dispatch_async(dispatch_get_main_queue(), ^{
  405. UIAlertController* alert = [UIAlertController alertControllerWithTitle:nil message:errorStr preferredStyle:UIAlertControllerStyleAlert];
  406. UIAlertAction* action = [UIAlertAction actionWithTitle:@"知道啦" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
  407. NSLog(@"知道啦");
  408. }];
  409. [alert addAction:action];
  410. UIViewController* fatherViewController = weakSelf.presentingViewController;
  411. [weakSelf dismissViewControllerAnimated:YES completion:^{
  412. [fatherViewController presentViewController:alert animated:YES completion:nil];
  413. }];
  414. });
  415. }
  416. @end