WebRTC音视频通话-实现GPUImage视频美颜滤镜效果iOS

WebRTC音视频通话-实现GPUImage视频美颜滤镜效果

在WebRTC音视频通话的GPUImage美颜效果图如下

在这里插入图片描述

可以看下
之前搭建ossrs服务,可以查看:https://blog.csdn.net/gloryFlow/article/details/132257196
之前实现iOS端调用ossrs音视频通话,可以查看:https://blog.csdn.net/gloryFlow/article/details/132262724
之前WebRTC音视频通话高分辨率不显示画面问题,可以查看:https://blog.csdn.net/gloryFlow/article/details/132262724
修改SDP中的码率Bitrate,可以查看:https://blog.csdn.net/gloryFlow/article/details/132263021

一、GPUImage是什么?

GPUImage是iOS上一个基于OpenGL进行图像处理的开源框架,内置大量滤镜,架构灵活,可以在其基础上很轻松地实现各种图像处理功能。

GPUImage中包含各种滤镜,这里我不会使用那么多,使用的是GPUImageLookupFilter及GPUImagePicture

GPUImage中有一个专门针对lookup table进行处理的滤镜函数GPUImageLookupFilter,使用这个函数就可以直接对图片进行滤镜添加操作了。代码如下

/**GPUImage中有一个专门针对lookup table进行处理的滤镜函数GPUImageLookupFilter,使用这个函数就可以直接对图片进行滤镜添加操作了。originalImg是你希望添加滤镜的原始图片@param image 原图@return 处理后的图片*/
+ (UIImage *)applyLookupFilter:(UIImage *)image lookUpImage:(UIImage *)lookUpImage {if (lookUpImage == nil) {return image;}UIImage *inputImage = image;UIImage *outputImage = nil;GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithImage:inputImage];//添加滤镜GPUImageLookupFilter *lookUpFilter = [[GPUImageLookupFilter alloc] init];//导入之前保存的NewLookupTable.png文件GPUImagePicture *lookupImg = [[GPUImagePicture alloc] initWithImage:lookUpImage];[lookupImg addTarget:lookUpFilter atTextureLocation:1];[stillImageSource addTarget:lookUpFilter atTextureLocation:0];[lookUpFilter useNextFrameForImageCapture];if([lookupImg processImageWithCompletionHandler:nil] && [stillImageSource processImageWithCompletionHandler:nil]) {outputImage= [lookUpFilter imageFromCurrentFramebuffer];}return outputImage;
}

这个需要lookUpImage,图列表如下

在这里插入图片描述

由于暂时没有整理demo的git

这里在使用applyLomofiFilter再试下效果

SDApplyFilter.m中的几个方法

+ (UIImage *)applyBeautyFilter:(UIImage *)image {GPUImageBeautifyFilter *filter = [[GPUImageBeautifyFilter alloc] init];[filter forceProcessingAtSize:image.size];GPUImagePicture *pic = [[GPUImagePicture alloc] initWithImage:image];[pic addTarget:filter];[pic processImage];[filter useNextFrameForImageCapture];return [filter imageFromCurrentFramebuffer];
}/**Amatorka滤镜 Rise滤镜,可以使人像皮肤得到很好的调整@param image image@return 处理后的图片*/
+ (UIImage *)applyAmatorkaFilter:(UIImage *)image
{GPUImageAmatorkaFilter *filter = [[GPUImageAmatorkaFilter alloc] init];[filter forceProcessingAtSize:image.size];GPUImagePicture *pic = [[GPUImagePicture alloc] initWithImage:image];[pic addTarget:filter];[pic processImage];[filter useNextFrameForImageCapture];return [filter imageFromCurrentFramebuffer];
}/**复古型滤镜,感觉像旧上海滩@param image image@return 处理后的图片*/
+ (UIImage *)applySoftEleganceFilter:(UIImage *)image
{GPUImageSoftEleganceFilter *filter = [[GPUImageSoftEleganceFilter alloc] init];[filter forceProcessingAtSize:image.size];GPUImagePicture *pic = [[GPUImagePicture alloc] initWithImage:image];[pic addTarget:filter];[pic processImage];[filter useNextFrameForImageCapture];return [filter imageFromCurrentFramebuffer];
}/**图像黑白化,并有大量噪点@param image 原图@return 处理后的图片*/
+ (UIImage *)applyLocalBinaryPatternFilter:(UIImage *)image
{GPUImageLocalBinaryPatternFilter *filter = [[GPUImageLocalBinaryPatternFilter alloc] init];[filter forceProcessingAtSize:image.size];GPUImagePicture *pic = [[GPUImagePicture alloc] initWithImage:image];[pic addTarget:filter];[pic processImage];[filter useNextFrameForImageCapture];return [filter imageFromCurrentFramebuffer];
}/**单色滤镜@param image 原图@return 处理后的图片*/
+ (UIImage *)applyMonochromeFilter:(UIImage *)image
{GPUImageMonochromeFilter *filter = [[GPUImageMonochromeFilter alloc] init];[filter forceProcessingAtSize:image.size];GPUImagePicture *pic = [[GPUImagePicture alloc] initWithImage:image];[pic addTarget:filter];[pic processImage];[filter useNextFrameForImageCapture];return [filter imageFromCurrentFramebuffer];
}

使用GPUImageSoftEleganceFilter复古型滤镜,感觉像旧上海滩效果图如下
在这里插入图片描述

使用GPUImageLocalBinaryPatternFilter图像黑白化效果图如下

在这里插入图片描述

使用GPUImageMonochromeFilter 效果图如下

在这里插入图片描述

二、WebRTC实现音视频通话中视频滤镜处理

之前实现iOS端调用ossrs音视频通话,可以查看:https://blog.csdn.net/gloryFlow/article/details/132262724
这个已经有完整的代码了,这里暂时做一下调整。

为RTCCameraVideoCapturer的delegate指向代理

- (RTCVideoTrack *)createVideoTrack {RTCVideoSource *videoSource = [self.factory videoSource];self.localVideoSource = videoSource;// 如果是模拟器if (TARGET_IPHONE_SIMULATOR) {if (@available(iOS 10, *)) {self.videoCapturer = [[RTCFileVideoCapturer alloc] initWithDelegate:self];} else {// Fallback on earlier versions}} else{self.videoCapturer = [[RTCCameraVideoCapturer alloc] initWithDelegate:self];}RTCVideoTrack *videoTrack = [self.factory videoTrackWithSource:videoSource trackId:@"video0"];return videoTrack;
}

实现RTCVideoCapturerDelegate的方法didCaptureVideoFrame

#pragma mark - RTCVideoCapturerDelegate处理代理
- (void)capturer:(RTCVideoCapturer *)capturer didCaptureVideoFrame:(RTCVideoFrame *)frame {
//    DebugLog(@"capturer:%@ didCaptureVideoFrame:%@", capturer, frame);// 调用SDWebRTCBufferFliter的滤镜处理RTCVideoFrame *aFilterVideoFrame;if (self.delegate && [self.delegate respondsToSelector:@selector(webRTCClient:didCaptureVideoFrame:)]) {aFilterVideoFrame = [self.delegate webRTCClient:self didCaptureVideoFrame:frame];}//  操作C 需要手动释放  否则内存暴涨
//      CVPixelBufferRelease(_buffer)//    拿到pixelBuffer
//        ((RTCCVPixelBuffer*)frame.buffer).pixelBufferif (!aFilterVideoFrame) {aFilterVideoFrame = frame;}[self.localVideoSource capturer:capturer didCaptureVideoFrame:frame];
}

之后调用SDWebRTCBufferFliter,实现滤镜效果。
实现将((RTCCVPixelBuffer *)frame.buffer).pixelBuffer进行渲染,这里用到了EAGLContext、CIContext

EAGLContext是OpenGL绘制句柄或者上下文,在绘制试图之前,需要指定使用创建的上下文绘制。
CIContext是用来渲染CIImage,将作用在CIImage上的滤镜链应用到原始的图片数据中。我这里需要将UIImage转换成CIImage。

具体代码实现如下

SDWebRTCBufferFliter.h

#import <Foundation/Foundation.h>
#import "WebRTCClient.h"@interface SDWebRTCBufferFliter : NSObject- (RTCVideoFrame *)webRTCClient:(WebRTCClient *)client didCaptureVideoFrame:(RTCVideoFrame *)frame;@end

SDWebRTCBufferFliter.m

#import "SDWebRTCBufferFliter.h"
#import <VideoToolbox/VideoToolbox.h>
#import "SDApplyFilter.h"@interface SDWebRTCBufferFliter ()
// 滤镜
@property (nonatomic, strong) EAGLContext *eaglContext;@property (nonatomic, strong) CIContext *coreImageContext;@property (nonatomic, strong) UIImage *lookUpImage;@end@implementation SDWebRTCBufferFliter- (instancetype)init
{self = [super init];if (self) {self.eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];self.coreImageContext = [CIContext contextWithEAGLContext:self.eaglContext options:nil];self.lookUpImage = [UIImage imageNamed:@"lookup_jiari"];}return self;
}- (RTCVideoFrame *)webRTCClient:(WebRTCClient *)client didCaptureVideoFrame:(RTCVideoFrame *)frame {CVPixelBufferRef pixelBufferRef = ((RTCCVPixelBuffer *)frame.buffer).pixelBuffer;//    CFRetain(pixelBufferRef);if (pixelBufferRef) {CIImage *inputImage = [CIImage imageWithCVPixelBuffer:pixelBufferRef];CGImageRef imgRef = [_coreImageContext createCGImage:inputImage fromRect:[inputImage extent]];UIImage *fromImage = nil;if (!fromImage) {fromImage = [UIImage imageWithCGImage:imgRef];}UIImage *toImage;toImage = [SDApplyFilter applyMonochromeFilter:fromImage];
//
//        if (toImage == nil) {
//            toImage = [SDApplyFilter applyLookupFilter:fromImage lookUpImage:self.lookUpImage];
//        } else {
//            toImage = [SDApplyFilter applyLookupFilter:fromImage lookUpImage:self.lookUpImage];
//        }if (toImage == nil) {toImage = fromImage;}CGImageRef toImgRef = toImage.CGImage;CIImage *ciimage = [CIImage imageWithCGImage:toImgRef];[_coreImageContext render:ciimage toCVPixelBuffer:pixelBufferRef];CGImageRelease(imgRef);//必须释放fromImage = nil;toImage = nil;ciimage = nil;inputImage = nil;}RTCCVPixelBuffer *rtcPixelBuffer =[[RTCCVPixelBuffer alloc] initWithPixelBuffer:pixelBufferRef];RTCVideoFrame *filteredFrame =[[RTCVideoFrame alloc] initWithBuffer:rtcPixelBufferrotation:frame.rotationtimeStampNs:frame.timeStampNs];return filteredFrame;
}@end

至此可以看到在WebRTC音视频通话中GPUImage视频美颜滤镜的具体效果了。

三、小结

WebRTC音视频通话-实现GPUImage视频美颜滤镜效果。主要用到GPUImage处理视频画面CVPixelBufferRef,将处理后的CVPixelBufferRef生成RTCVideoFrame,通过调用localVideoSource中实现的didCaptureVideoFrame方法。内容较多,描述可能不准确,请见谅。

本文地址:https://blog.csdn.net/gloryFlow/article/details/132265842

学习记录,每天不停进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/88505.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SCAU操作系统知识点之(一)计算机系统概述

缩写词&#xff1a; OS: Operating System 操作系统 PSW: Program Status Word 程序状态字 FCFS: First Come First Serve 先来先服务 PCB: Process Control Block 进程控制块 DMA: Direct Memory Access 直接存储器存取 MMU: Memory Management Unit 内存管理单元 SSTF: Short…

从零构建深度学习推理框架-6 构建计算图

PNNX PNNX项目 PyTorch Neural Network eXchange&#xff08;PNNX&#xff09;是PyTorch模型互操作性的开放标准。PNNX为PyTorch提供了一种开源的模型格式&#xff0c;它定义了与Pytorch相匹配的数据流图和运算图&#xff0c;我们的框架在PNNX之上封装了一层更加易用和简单的计…

本地跑Mapreduce程序的相关配置

本地跑MapReduce程序需要配置的代码 为了在本地运行MapReduce程序&#xff0c;需要加如下的东西 在项目中创建一个如图所示的包&#xff1a;org.apache.hadoop.io.nativeio&#xff0c;并在该包下面创建一个名为&#xff1a;NativeIO的类&#xff08;注意&#xff1a;名字不能…

五、约束编程求解优化问题

文章目录 1、瑶草问题-离散优化问题2、重试优化3、分支限界法-改进重试优化法4、重启式搜索4.1 重启方针/策略4.2 自动化搜索策略 THE END 1、瑶草问题-离散优化问题 \qquad 要求在一个建木上构建一个完整的分枝树&#xff0c;每一个完整的分枝有100段&#xff0c;完整分枝上的…

uniapp 扩展组件 uni-forms 的表单验证之 validateFunction 只响应一次

uniapp 扩展组件 uni-forms 的表单验证之 validateFunction 只响应一次 问题代码官方说明参考资料 问题代码 直接从官方示例中复制过来改的。为了演示 <template><view><uni-forms ref"form" :modelValue"formData" :rules"rules&qu…

深度学习(36)—— 图神经网络GNN(1)

深度学习&#xff08;36&#xff09;—— 图神经网络GNN&#xff08;1&#xff09; 这个系列的所有代码我都会放在git上&#xff0c;欢迎造访 文章目录 深度学习&#xff08;36&#xff09;—— 图神经网络GNN&#xff08;1&#xff09;1. 基础知识2.使用场景3. 图卷积神经网…

UnityWebGL移动端兼容性说明

测试时间2023.8.10 官方文档说明 依据Unity官方最新版本文档&#xff08;2021.3LTS&#xff09;&#xff0c;关于WebGL的兼容性说明为"Unity WebGL不支持移动设备。它可能适用于高端设备&#xff0c;但当前的设备通常不够强大&#xff0c;并且没有足够的内存来支持Unity …

【c语言】字符函数与字符串函数(上)

大家好呀&#xff0c;今天给大家分享一下字符函数和字符串函数&#xff0c;说起字符函数和字符串函数大家会想到哪些呢&#xff1f;&#xff1f;我想到的只有求字符串长度的strlen,拷贝字符串的strcpy,字符串比较相同的strcmp,今天&#xff0c;我要分享给大家的是我们一些其他的…

SQL-每日一题【1517. 查找拥有有效邮箱的用户】

题目 表: Users 编写一个解决方案&#xff0c;以查找具有有效电子邮件的用户。 一个有效的电子邮件具有前缀名称和域&#xff0c;其中&#xff1a; 前缀 名称是一个字符串&#xff0c;可以包含字母&#xff08;大写或小写&#xff09;&#xff0c;数字&#xff0c;下划线 _ &…

详细讲解如何在github上编辑个人主页?

在 GitHub 上编辑个人主页可以让您展示您的项目、技能和个人信息&#xff0c;以及与其他开发者互动。以下是详细的步骤来在 GitHub 上编辑个人主页&#xff1a; 创建 GitHub 账户 如果您还没有 GitHub 账户&#xff0c;首先需要注册一个。 登录到 GitHub 使用您的用户名和密…

【TypeScript】进阶之路语法细节,类型和函数

进阶之路 类型别名(type)的使用接口(interface)的声明的使用二者区别&#xff1a; 联合类型和交叉类型联合类型交叉类型 类型断言获取DOM元素 非空类型断言字面量类型的使用类型缩小&#xff08;类型收窄&#xff09;TypeScript 函数类型函数类型表达式内部规则检测函数的调用签…

置信域策略优化Trust Region Policy Optimization (TRPO)

1. 置信域方法(Trust Region Methods) [1]将置信域方法用到强化学习中&#xff0c;并取到了非常好的结果. 1.1 优化问题 1.2 置信域 1.3 置信域方法的过程 References [1] Schulman J, Levine S, Abbeel P, et al. Trust region policy optimization[C]//International conf…

【K8S系列】深入解析k8s网络插件—Weave Net

序言 做一件事并不难&#xff0c;难的是在于坚持。坚持一下也不难&#xff0c;难的是坚持到底。 文章标记颜色说明&#xff1a; 黄色&#xff1a;重要标题红色&#xff1a;用来标记结论绿色&#xff1a;用来标记论点蓝色&#xff1a;用来标记论点 Kubernetes (k8s) 是一个容器编…

构建Docker容器监控系统(cadvisor+influxDB+grafana)

目录 一、部署 1、安装docker-cd 2、阿里云镜像加速 3、下载组件镜像 4、创建自定义网络 5、创建influxdb容器 6、创建Cadvisor 容器 7、创建granafa容器 一、部署 1、安装docker-cd [rootlocalhost ~]# iptables -F [rootlocalhost ~]# setenforce 0 setenforce: SELi…

BGP的工作过程及报文

IGP核心:路由的计算。OSPF,ISIS等 BGP核心:路由的传递,不产生路由,只是路由的搬运工,一般用于规模特别大的网络中,只要TCP可达就可以建立邻居。 大型企业分支间采用BGP进行路由传递,不同的分支属于不同的BGP的AS,它们通过BGP进行路由交互。企业与运营商之间可使用BGP进行…

解决nvm安装后,node生效但npm无效

问题描述 nvm安装后&#xff0c;node生效但npm无效 清除缓存 C:\Users\cc\AppData\Roaming cc是我的用户名改成你自己的就行删除 npm和npm-cache

Rx.NET in Action 中文介绍 前言及序言

Rx 处理器目录 (Catalog of Rx operators) 目标可选方式Rx 处理器(Operator)创建 Observable Creating Observables直接创建 By explicit logicCreate Defer根据范围创建 By specificationRangeRepeatGenerateTimerInterval Return使用预设 Predefined primitivesThrow …

软件测试(功能、接口、性能、自动化)详解

一、软件测试功能测试 测试用例编写是软件测试的基本技能&#xff1b;也有很多人认为测试用例是软件测试的核心&#xff1b;软件测试中最重要的是设计和生成有效的测试用例&#xff1b;测试用例是测试工作的指导&#xff0c;是软件测试的必须遵守的准则。 黑盒测试常见测试用…

Gartner发布2023年的存储技术成熟曲线

技术路线说明 Gartner自1995年起开始采用技术成熟度曲线&#xff0c;它描述创新的典型发展过程&#xff0c;即从过热期发展到幻灭低谷期&#xff0c;再到人们最终理解创新在市场或领域内的意义和角色。 一项技术 (或相关创新)在发展到最终成熟期的过程中经历多个阶段&#xff1…

二十二、策略模式

目录 1、项目需求2、传统方案解决鸭子问题的分析和代码实现3、传统方式实现存在的问题分析和解决方案4、策略模式基本介绍5、使用策略模式解决鸭子问题6、策略模式的注意事项和细节7、策略模式的使用场景 以具体项目来演示为什么需要策略模式&#xff0c;策略模式的优点&#x…