虚幻UE4中如何采集360度全景图片和VR视频

如何使用虚幻4来制作一个VR视频播放器呢,简单来讲,使用虚幻4的视频采集插件来获取图像,并对图像进行处理,就能获取我们需要的图像了,下一步,你可以把图像投影到一个360度球体上,就能形成球形的播放器了。

1.插件测试—采集单帧双眼图像

打开Epic Games Launcher,启动引擎(我使用的版本为4.14.0)。在弹出的对话框中点击New Project标签栏,再选择C++标签页,选择Vehicle Advanced模板,并将项目命名为STEREOSCOPIC。最后点击CreateProject。 

在打开的编辑器菜单栏依次点击Edit→Plugins,然后选择左侧的Movie Capture,在右侧Stereo Panoramic Movie Capture条目中勾选Enabled。然后重启编辑器。 
当编辑器重启后,再次点击Edit→Plugins→Movie Capture,再次检查Stereo Panoramic Movie Capture是否已启用。 
在工具栏,依次点击Blueprints→OpenLevelBlueprint。在Event BeginPlay事件后,新建两个(具体依据需求而定)Execute Console Command节点保存我们需要执行的命令。 
这里先进行采集测试,将下面这两条命令分别放入Execute Console Command节点中:

[代码]:

1 "3">SP.OutputDir D:/StereoCaptureFrames
2 // 采集单帧
3 SP.PanoramicScreenshot


如下图所示: 

然后就可以点击工具栏的Play按钮了。此时系统可能会长时间没有响应(一分钟左右),然后将会有两帧图像存储到先前用SP.OutputDir指定的目录中(实际是在改目录中的一个日期与时间目录下,点击一次Play生成一个),一个是左眼图像,一个是右眼图像。 

2.在项目中集成插件

首先将引擎中的全景采集插件(Stereo Panomic Movie Capture)备份,再将整个插件目录剪切(注意是剪切,而不是复制)出来,一是供我们修改,二是防止和我们自己编译有冲突。Unreal引擎中的插件在路径\Epic Games\4.14\Engine\Plugins下,在这里我们需要将其中的StereoPanorama(\Plugins\Experimental\StereoPanorama)剪切出来。 
然后打开Stereo项目文件夹,在文件夹根目录下新建一个Plugins文件夹,将上一步剪切的StereoPanorama文件夹粘贴到这里。目录结构示例如下(限于篇幅这里只列出了必要的文件): 

打开项目的场景编辑器,依次点击Editor→Plugins→Project→MovieCaputure,启用Stereo Panoramic Movie Caputure,然后重启项目。再次检查Stereo Panoramic Movie Capture是否被启用。 
项目编辑器中,依次点击File→OpenVisualStudio,在VS工程中,依次点击Solution→Games→STEREOSCOPIC→Config,打开DefaultEngine.ini文件,在该文件末尾添加如下文字。

[代码]:

1 "3">[Plugins]
2 +EnabledPlugins=StereoPanorama


如下所示(截图是添加插件后的工程,默认没有Plugins): 


为了强制打包项目的时候插件能够和项目相连,在VS工程中,依次点击Solution→Games→STEREOSCOPIC→Source→STEREOSCOPIC→STEREOSCOPIC.Build.cs文件中添加模块依赖项。

[代码]:

1 "3"> PrivateDependencyModuleNames.AddRange(new string[] { "StereoPanorama" });

如下所示: 

关闭Visual Studio和ue4编辑器,并重启。重启之后可以发现VS工程中已经添加了Plugins文件夹和StereoPanorama插件。

3将左右眼图像自动组合成单一图像

在VS工程中,依次打开Solution→Games→STEREOSCOPIC→Plugins→StereoPahorama→Source→StereoPahorama\Private,打开文件SceneCapture.cpp文件。全部修改工作均在次完成。

为了使我们能够方便地控制合成的开关,我们需要定义一个bool常量在文件的头部,这样,在我们不需要开启合并的时候修改该常量的值即可,不必再修改其余的代码。

[代码]:

1 "3">// Newly inserted code.Defined a const bool
2 const bool CombineAtlasesOnOutput = true;


现在我们需要在代码中有条件地禁用每只眼睛的输出(通过上面定义的CombineAtlasesOnOutput来控制)。然后找到USceneCapturer::SaveAtlas()的底部,找到这样一段代码:


[代码]:

1 "3">IImageWrapperPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper( EImageFormat::PNG );
2 ImageWrapper->SetRaw(SphericalAtlas.GetData(), SphericalAtlas.GetAllocatedSize(), SphericalAtlasWidth, SphericalAtlasHeight, ERGBFormat::BGRA, 8);
3 const T"http://www.52vr.com/armr/" style="font-weight: bold;color: ;" target="_blank">ARray& PNGData = ImageWrapper->GetCompressed(100);
4 FFileHelper::SaveArrayToFile( PNGData, *AtlasName );


这几行代码就是控制左右眼输出的,如果我们定义的CombineAtlasesOnOutput为true,就意味这我们需要合并两张眼睛的图像,那么我们就需要禁掉它(左右单独输出),如果为false则我们需要输出左右眼的单独序列帧,所以就需要执行它。 

综上,可以写一个if语句来判断CombineAtlasesOnOutput的值:

[代码]:

1 "3">IImageWrapperPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper( EImageFormat::PNG );
2 if (!CombineAtlasesOnOutput)
3 {
4     ImageWrapper->SetRaw(SphericalAtlas.GetData(), SphericalAtlas.GetAllocatedSize(), SphericalAtlasWidth, SphericalAtlasHeight, ERGBFormat::BGRA, 8);
5     const TArray& PNGData = ImageWrapper->GetCompressed(100);
6     FFileHelper::SaveArrayToFile(PNGData, *AtlasName);
7 }


这样会导致一个错误,因为PNGData是在if的作用域内定义的,如果执行到了if后(被释放掉)或者根本没有执行到(if判断为false(!true))就会导致后面对PNGData的使用造成错误。 

在上面if语句之后的代码块中对PNGData的使用处为:

[代码]:

01 "3">if (FStereoPanoramaManager::GenerateDebugImages->GetInt() != 0)
02 {
03     FString FrameStringUnprojected = FString::Printf(TEXT("%s_%05d_Unprojected.png"), *Folder, CurrentFrameCount);
04     FString AtlasNameUnprojected = OutputDir / Timestamp / FrameStringUnprojected;
05  
06     ImageWrapper->SetRaw(SurfaceData.GetData(), SurfaceData.GetAllocatedSize(), UnprojectedAtlasWidth, UnprojectedAtlasHeight, ERGBFormat::BGRA, 8);
07     const TArray& PNGDataUnprojected = ImageWrapper->GetCompressed(100);
08     // 原来的代码为 FFileHelper::SaveArrayToFile(PNGData, *AtlasNameUnprojected);
09     FFileHelper::SaveArrayToFile(PNGDataUnprojected, *AtlasNameUnprojected);
10 }


对禁用左右眼单帧输出部分,如果只写这部分代码,现在再执行采集是不会有任何有意义图像输出的(因为现在已经把左右眼输出禁用了)。下面继续搞将两张合并到一块的方法。 

查找代码:

[代码]:

1 "3">TArray SphericalLeftEyeAtlas  = SaveAtlas( TEXT( "Left" ), UnprojectedLeftEyeAtlas );
2         TArray SphericalRightEyeAtlas = SaveAtlas(TEXT("Right"), UnprojectedRightEyeAtlas);


在其后添加:

[代码]:

01 "3">//*NEW* - Begin
02 if (CombineAtlasesOnOutput)
03 {
04     TArray CombinedAtlas;
05     CombinedAtlas.Append(SphericalLeftEyeAtlas);
06     CombinedAtlas.Append(SphericalRightEyeAtlas);
07     IImageWrapperPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::JPEG);
08     ImageWrapper->SetRaw(CombinedAtlas.GetData(), CombinedAtlas.GetAllocatedSize(), SphericalAtlasWidth, SphericalAtlasHeight * 2, ERGBFormat::BGRA, 8);
09     const TArray& PNGData = ImageWrapper->GetCompressed(100);
10     // Generate name
11     FString FrameString = FString::Printf(TEXT("Frame_%05d.jpg"), CurrentFrameCount);
12     FString AtlasName = OutputDir / Timestamp / FrameString;
13     FFileHelper::SaveArrayToFile(PNGData, *AtlasName);
14     ImageWrapper.Reset();
15  
16 }
17 //*NEW* - END


此时在VS工程中编译项工程STEREOSCOPIC,并重启UE4编辑器和VS,就会采集并将左右眼合并成一张图片了。 

参考连接:https://imzlp.me/2016/09/05/capturing-stereoscopic-360-screenshots-videos-movies-unreal-engine-4/

翻译整理:zhuxiaoyang2000

本文转自: 52VR.com    Hololens http://www.52vr.com/article-766-1.html

你可能感兴趣的:(开发引擎相关,虚幻4,UE4,360视频,VR)