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 でビットレートを変更します。次を参照してください: https://blog.csdn.net/gloryFlow/article/details/132263021

1. GPUImageとは何ですか?

GPUImage は、iOS 上の OpenGL に基づいた画像処理用のオープンソース フレームワークであり、多数の組み込みフィルターと柔軟なアーキテクチャを備えており、これをベースにしてさまざまな画像処理機能を簡単に実装できます。

GPUImage にはさまざまなフィルターが含まれていますが、ここではあまり使用しません。GPUImageLookupFilter と GPUImagePicture を使用します。

GPUImageにはルックアップテーブル専用に加工されたフィルタ関数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 が必要です。画像のリストは次のとおりです

ここに画像の説明を挿入

デモの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を使用した場合の効果は以下の通りです

ここに画像の説明を挿入

2. WebRTC は音声通話とビデオ通話にビデオ フィルター処理を実装します。

iOS 側での ossrs の音声およびビデオ通話を認識する前に、次のことを確認できます: https://blog.csdn.net/gloryFlow/article/details/132262724
これにはすでに完全なコードがありますが、ここでは一時的な調整を示します。

RTCCameraVideoCapturer のデリゲートのプロキシをポイントします

- (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).pixelBuffer
    
    if (!aFilterVideoFrame) {
    
    
        aFilterVideoFrame = frame;
    }
    
    [self.localVideoSource capturer:capturer didCaptureVideoFrame:frame];
}

次に、SDWebRTCBufferFliter を呼び出してフィルター効果を実現します。
EAGLContext と CIContext が使用されるレンダリング ((RTCCVPixelBuffer *)frame.buffer).pixelBuffer を実現します。

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:rtcPixelBuffer
                                 rotation:frame.rotation
                              timeStampNs:frame.timeStampNs];
    
    return filteredFrame;
}

@end

これまでのところ、WebRTC オーディオおよびビデオ通話における GPUImage ビデオ ビューティー フィルターの具体的な効果を確認できます。

3. まとめ

WebRTC オーディオおよびビデオ通話 - GPUImage ビデオ ビューティー フィルター効果を実現します。主に GPUImage を使用してビデオ画面 CVPixelBufferRef を処理し、処理された CVPixelBufferRef から RTCVideoFrame を生成し、localVideoSource に実装されている DidCaptureVideoFrame メソッドを呼び出します。内容が多く、不正確な記述があるかもしれませんが、ご容赦ください。

この記事のアドレス: https://blog.csdn.net/gloryFlow/article/details/132265842

学習記録、日々改善を続けてください。

おすすめ

転載: blog.csdn.net/gloryFlow/article/details/132265842