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