iOS AR之视频特效挂件(GPUImage)
在苹果开发者大会之后,苹果要在iOS 11 、Xcode9中添加ARKit框架,似乎AR没有那么神秘,我们早就用过了,比如QQ的视频挂件、花椒的礼物动画、还有支付宝的扫福都应该属于AR技术。今天我就浅谈视频特效挂件。
思路
- 1.通过摄像头捕获数据
- 2.回调数据CMSampleBufferRef
- 3.进行物体识别(人脸识别)这里用的是CoreImage的人脸识别CIDetector、也可用OpenCV等。
- 4.显示特效(视频、GIF、图片、文字等等)
- 5.视频本地写入
涉及到的技术
- 1.GPUImageVideoCamera的使用
- 2.GPUImageUIElement的使用
- 3.FLAnimatedImageView的使用
- 4.GPUImageMovie的使用
- 5.GPUImageFilter的使用
- 6.CIDetector的使用
我做的是显示GIF特效。效果图: 请忽略我的模样\( ̄︶ ̄)/
Demo没有做美颜,可查看我GPUImage其他博客、应该会有收获
完整Demo地址:
https://coding.net/u/Xoxo_x/p/VideoAndAudio/git/blob/master/GPUImage%E7%9B%B8%E6%9C%BA%E7%89%B9%E6%95%88.zip
主要步骤:
[self initGPUImageView];//初始化GPUImageView//初始化滤镜GPUImageAlphaBlendFilter,主要用来做半透明的混合的[self initFilter];[self initCamera];//初始化相机
GPUImageUIElement 是GPUImage提供的可以将我们的普通UI转化为纹理输出到视频中
- (UIView *)elementView {if (!_elementView) {gifImageView = [[FLAnimatedImageView alloc] init];gifImageView.frame = CGRectMake(0, 0, 160, 160);[self.view addSubview:gifImageView];NSData *gifImageData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle]pathForResource:[NSString stringWithFormat:@"hudie"] ofType:@"gif" inDirectory:nil]];[self animatedImageView:gifImageView data:gifImageData];[_elementView addSubview:gifImageView];}return _elementView;
}
FLAnimatedImageView 用于播放gif动画
GPUImageFilter* progressFilter = [[GPUImageFilter alloc] init];[videoCamera addTarget:progressFilter];
将两个纹理输出到GPUImageView
[progressFilter addTarget:filter];[pictureView addTarget:filter];[filter addTarget:filterView];
设置处理回调
__strong typeof(self) strongSelf = self;[progressFilter setFrameProcessingCompletionBlock:^(GPUImageOutput *output, CMTime time) {// update capImageView's frameCGRect rect = strongSelf.faceBounds;CGSize size = gifImageView.frame.size;[UIView animateWithDuration:0.2 animations:^{gifImageView.frame = CGRectMake(rect.origin.x + (rect.size.width - size.width)/2, rect.origin.y - size.height, size.width, size.height);}];[pictureView updateWithTimestamp:time];[strongSelf->pictureView updateWithTimestamp:time];}];
使用屏幕刷新频率
CADisplayLink * displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(onDisplayLink:)];[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
视频回调代理、获取原始数据
- (void)willOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer {if (!_faceThinking) {CFAllocatorRef allocator = CFAllocatorGetDefault();CMSampleBufferRef sbufCopyOut;CMSampleBufferCreateCopy(allocator,sampleBuffer,&sbufCopyOut);[self performSelectorInBackground:@selector(grepFacesForSampleBuffer:) withObject:CFBridgingRelease(sbufCopyOut)];}
}
将CMSampleBufferRef进行图像转化识别、提取特征
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);CFDictionaryRef attachments = CMCopyDictionaryOfAttachments(kCFAllocatorDefault, sampleBuffer, kCMAttachmentMode_ShouldPropagate);CIImage *convertedImage = [[CIImage alloc] initWithCVPixelBuffer:pixelBuffer options:(__bridge NSDictionary *)attachments];
imageOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:exifOrientation] forKey:CIDetectorImageOrientation];NSArray *features = [self.faceDetector featuresInImage:convertedImage options:imageOptions];// get the clean aperture// the clean aperture is a rectangle that defines the portion of the encoded pixel dimensions// that represents image data valid for display.CMFormatDescriptionRef fdesc = CMSampleBufferGetFormatDescription(sampleBuffer);CGRect clap = CMVideoFormatDescriptionGetCleanAperture(fdesc, false /*originIsTopLeft == false*/);
进行识别
dispatch_async(dispatch_get_main_queue(), ^{CGRect previewBox = self.view.frame;if (featureArray.count) {gifImageView.hidden = NO;}else {
// gifImageView.hidden = YES;return ;}for ( CIFaceFeature *faceFeature in featureArray) {// find the correct position for the square layer within the previewLayer// the feature box originates in the bottom left of the video frame.// (Bottom right if mirroring is turned on)//Update face bounds for iOS Coordinate SystemCGRect faceRect = [faceFeature bounds];// flip preview width and heightCGFloat temp = faceRect.size.width;faceRect.size.width = faceRect.size.height;faceRect.size.height = temp;temp = faceRect.origin.x;faceRect.origin.x = faceRect.origin.y;faceRect.origin.y = temp;// scale coordinates so they fit in the preview box, which may be scaledCGFloat widthScaleBy = previewBox.size.width / clap.size.height;CGFloat heightScaleBy = previewBox.size.height / clap.size.width;faceRect.size.width *= widthScaleBy;faceRect.size.height *= heightScaleBy;faceRect.origin.x *= widthScaleBy;faceRect.origin.y *= heightScaleBy;faceRect = CGRectOffset(faceRect, previewBox.origin.x, previewBox.origin.y);//mirrorCGRect rect = CGRectMake(previewBox.size.width - faceRect.origin.x - faceRect.size.width, faceRect.origin.y, faceRect.size.width, faceRect.size.height);if (fabs(rect.origin.x - self.faceBounds.origin.x) > 5.0) {self.faceBounds = rect;// if (self.faceView) {// [self.faceView removeFromSuperview];// self.faceView = nil;// }//// // create a UIView using the bounds of the face// self.faceView = [[UIView alloc] initWithFrame:self.faceBounds];//// // add a border around the newly created UIView// self.faceView.layer.borderWidth = 1;// self.faceView.layer.borderColor = [[UIColor redColor] CGColor];//// // add the new view to create a box around the face// [self.view addSubview:self.faceView];}}});
然后再回到中更改蝴蝶的位置为头顶的位置
完整Demo地址:
https://coding.net/u/Xoxo_x/p/VideoAndAudio/git/blob/master/GPUImage%E7%9B%B8%E6%9C%BA%E7%89%B9%E6%95%88.zip
iOS AR之视频特效挂件(GPUImage)相关推荐
- iphone ios 视频特效,视频合成
如果对av foundation 不熟悉得话,建议先看看wwdc 2010 关于av foundation得讲座.http://blog.csdn.net/linzhiji/article/detai ...
- 手把手实现火爆全网的视频特效 “蚂蚁呀嘿”,太魔性了
点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 导读 Hi,大家好,今天是周末,今天给各位读者分享最近很火的视频特效. 将会依据现有的demo,一步步 ...
- 那么多短视频特效,凭什么抖音出的这么火
萧箫 发自 凹非寺 量子位 报道 | 公众号 QbitAI 说到短视频特效,你或许第一时间会想到"抖音特效". 没错,抖音的特效似乎总是火到出圈,像用一段视频让你"重返三 ...
- 美摄iOS端短视频SDK视频编辑的流程及方法
美摄短视频SDK提供视频编辑功能,支持视频图片素材混合导入.滤镜.配音.时间特效.画中画等丰富的编辑效果.本文介绍iOS端短视频SDK视频编辑的流程及方法. 短视频SDK主要包含"视频录制& ...
- Android IOS WebRTC 音视频开发总结(三八)-- tx help
Android IOS WebRTC 音视频开发总结(三八)-- tx help 本文主要介绍帮一个程序员解决webrtc疑问的过程,文章来自博客园RTC.Blacker,支持原创,转载请说明出处(w ...
- Android IOS WebRTC 音视频开发总结(二三)-- hurtc使用说明
Android IOS WebRTC 音视频开发总结(二三)-- hurtc使用说明 本文主要介绍如何测试基于浏览器和手机的视频通话程序,转载请说明出处,文章来自博客园RTC.Blacker,更多详见 ...
- Android IOS WebRTC 音视频开发总结(四二)-- webrtc开发者大会
Android IOS WebRTC 音视频开发总结(四二)-- webrtc开发者大会 本文主要介绍11月要在北京举办的webrtc开发者全球大会,文章来自博客园RTC.Blacker,支持原创,转 ...
- 短视频APP开发:短视频特效SDK功能火爆来袭!
为什么短视频这么火呢?因为它符合了用户碎片化时间的需求,既娱乐了大众,又不会浪费用户太多时间. 短视频APP开发以互联网技术为核心,在原有的基础上不断进行创新,进而拥有多种强大的拍摄功能,让用户可以快 ...
- Android IOS WebRTC 音视频开发总结(八十七)-- WebRTC中丢包重传NACK实现分析
Android IOS WebRTC 音视频开发总结(八十七)-- WebRTC中丢包重传NACK实现分析 本文主要介绍WebRTC中丢包重传NACK的实现,作者:weizhenwei ,文章最早发表 ...
最新文章
- JNI与NDK学习第二篇-----应用篇
- utf8乱码解决方案[适合tomcat部署的jsp应用]
- 201771010126.王燕《面向对象程序设计(Java)》第六周学习总结
- FPGA的设计艺术(4)STA实战之不同时序路径的建立保持时间计算
- Android 开源库获取途径整理
- Python 数据结构视频教程一
- MATLAB应用实战系列(四十四)-基于matlab的支持向量机分类、回归问题(附源码解析)
- iOS开发者React Native学习路线
- 百度api语音识别一直“无内容”_PHP开发语音识别功能
- OPENCV图像变换-1
- mysql 5.6 设置long_query_time的值无效的原因
- 第十八届绵竹年画节开幕 大巡游展示清末年画《迎春图》场景
- 让Windows Server 2008+IIS 7+ASP.NET支持10万个同时请求
- 如何彻底卸载3dmax2020_3DMAX 2020安装失败,怎么把3DMAX 2020彻底卸载删除干净重新安装?...
- InnoDB下SQL执行底层原理和redolog、binlog
- 图片不能置于底层怎么办_ps怎么把图片置于底层
- 帝国cms7.2 linux伪静态,帝国CMS7.0IIS伪静态设置教程
- 【推荐】推荐一款云盘 不限速 【下载免登录】【下载不限速】【2T大存储】
- 从硬盘中安装ubuntu 18,04
- 深度之眼Paper带读笔记NLP.2:word2vec.baseline.1
热门文章
- ios h5页面回弹
- 公有IP地址和私有IP地址
- 全国行政区划代码PHP版数据
- VM安装Mac os x10.11的诸多坑人问题
- 一块网卡,两个网口,设置两个内网IP
- RuntimeError: CUDA error: out of memory
- 通过张三与如花悲惨爱情故事,理解“用户“、“shell“、“操作系统“之间的关系
- python 修改excel文档
- F2833x烧录到FLASH芯片锁住如何解除
- postgresql 除法运算