我正在尝试为iOS应用制作VHS效果,就像在此视频中一样: https://www.youtube.com/watch?v=8ipML-T5yDk
我想实现这种效果,可以减少产生较少的CPU费用。
基本上我需要的是提高色彩水平以创建“色差”,更改锐化参数,并添加一些高斯模糊+添加一些噪音。
我正在使用GPUImage。对于锐化和高斯模糊,易于应用。
我遇到两个问题: 1)对于“色差”,他们这样做的方式通常是复制视频的三倍,并在一个视频上将红色设置为0,在另一个视频上将蓝色设置为0,在最后一个视频上将绿色设置为0,并将其混合为0他们在一起(就像在教程中一样)。但是在iPhone中执行此操作会占用大量CPU资源。
任何想法如何实现相同的效果,而不必复制视频并混合它=
2)我还想添加一些噪音,但不知道要使用哪种GPUImage效果。对此也有任何想法吗?
非常感谢,
塞巴斯蒂安
答案 0 :(得分:3)
(我不是iOS开发人员,但我希望这可以对某人有所帮助。)
我在Windows上编写了VHS过滤器,这就是我所做的:
0 -0.5 0 0 -0.5 2.9 0 -0.5 0 -0.5 0 0
视频:Before After
截图:Before After
CPU和GPU消耗正常。我将此滤镜应用于旧版Windows Phone(使用Snapdragon 808)上的实时摄像头预览,效果很好。
代码(C#,使用Win2D库进行GPU加速,实现Windows.Media.Effects.IBasicVideoEffect接口):
public void ProcessFrame(ProcessVideoFrameContext context) //This method is called each frame
{
int outputWidth = 360; //Output Resolution
int outputHeight = 270;
IDirect3DSurface inputSurface = context.InputFrame.Direct3DSurface;
IDirect3DSurface outputSurface = context.OutputFrame.Direct3DSurface;
using (CanvasBitmap inputFrame = CanvasBitmap.CreateFromDirect3D11Surface(canvasDevice, inputSurface)) //The video frame to be processed
using (CanvasRenderTarget outputFrame = CanvasRenderTarget.CreateFromDirect3D11Surface(canvasDevice, outputSurface)) //The video frame after processing
using (CanvasDrawingSession outputFrameDrawingSession = outputFrame.CreateDrawingSession())
using (CanvasRenderTarget croppedFrame = new CanvasRenderTarget(canvasDevice, outputWidth, outputHeight, outputFrame.Dpi))
using (CanvasDrawingSession croppedFrameDrawingSession = croppedFrame.CreateDrawingSession())
using (CanvasBitmap overlay = Task.Run(async () => { return await CanvasBitmap.LoadAsync(canvasDevice, overlayFrames[new Random().Next(0, overlayFrames.Count - 1)]); }).Result) //"overlayFrames" is a list containing video frames from https://youtu.be/SHhRFU2Jyfs, here we just randomly pick one frame for blend
{
double inputWidth = inputFrame.Size.Width;
double inputHeight = inputFrame.Size.Height;
Rect ractangle;
//Crop the inputFrame to 360*270, save it to "croppedFrame"
if (3 * inputWidth > 4 * inputHeight)
{
double x = (inputWidth - inputHeight / 3 * 4) / 2;
ractangle = new Rect(x, 0, inputWidth - 2 * x, inputHeight);
}
else
{
double y = (inputHeight - inputWidth / 4 * 3) / 2;
ractangle = new Rect(0, y, inputWidth, inputHeight - 2 * y);
}
croppedFrameDrawingSession.DrawImage(inputFrame, new Rect(0, 0, outputWidth, outputHeight), ractangle, 1, CanvasImageInterpolation.HighQualityCubic);
//Apply a bunch of effects (mentioned in step 2,3,4) to "croppedFrame"
BlendEffect vhsEffect = new BlendEffect
{
Background = new ConvolveMatrixEffect
{
Source = new ColorMatrixEffect
{
Source = new SaturationEffect
{
Source = croppedFrame,
Saturation = 0.4f
},
ColorMatrix = new Matrix5x4
{
M11 = 1f,
M22 = 0.93f,
M33 = 1f,
M44 = 1f
}
},
KernelHeight = 3,
KernelWidth = 4,
KernelMatrix = new float[]
{
0, -0.5f, 0, 0,
-0.5f, 2.9f, 0, -0.5f,
0, -0.5f, 0, 0,
}
},
Foreground = overlay,
Mode = BlendEffectMode.Screen
};
//And draw the result to "outputFrame"
outputFrameDrawingSession.DrawImage(vhsEffect, ractangle, new Rect(0, 0, outputWidth, outputHeight));
}
}