您的位置:首页 > 产品设计 > UI/UE

UE4中采集360°全景图片和视频

2016-11-22 14:43 274 查看

UE4中导出全景图片和视频

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节点中:

SP.OutputDir D:/StereoCaptureFrames
// 采集单帧
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文件,在该文件末尾添加如下文字。

[Plugins]
+EnabledPlugins=StereoPanorama


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



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

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


如下所示:



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

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

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

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

// Newly inserted code.Defined a const bool
const bool CombineAtlasesOnOutput = true;


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

IImageWrapperPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper( EImageFormat::PNG );
ImageWrapper->SetRaw(SphericalAtlas.GetData(), SphericalAtlas.GetAllocatedSize(), SphericalAtlasWidth, SphericalAtlasHeight, ERGBFormat::BGRA, 8);
const TArray<uint8>& PNGData = ImageWrapper->GetCompressed(100);
FFileHelper::SaveArrayToFile( PNGData, *AtlasName );


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

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

IImageWrapperPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper( EImageFormat::PNG );
if (!CombineAtlasesOnOutput)
{
ImageWrapper->SetRaw(SphericalAtlas.GetData(), SphericalAtlas.GetAllocatedSize(), SphericalAtlasWidth, SphericalAtlasHeight, ERGBFormat::BGRA, 8);
const TArray<uint8>& PNGData = ImageWrapper->GetCompressed(100);
FFileHelper::SaveArrayToFile(PNGData, *AtlasName);
}


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

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

if (FStereoPanoramaManager::GenerateDebugImages->GetInt() != 0)
{
FString FrameStringUnprojected = FString::Printf(TEXT("%s_%05d_Unprojected.png"), *Folder, CurrentFrameCount);
FString AtlasNameUnprojected = OutputDir / Timestamp / FrameStringUnprojected;

ImageWrapper->SetRaw(SurfaceData.GetData(), SurfaceData.GetAllocatedSize(), UnprojectedAtlasWidth, UnprojectedAtlasHeight, ERGBFormat::BGRA, 8);
const TArray<uint8>& PNGDataUnprojected = ImageWrapper->GetCompressed(100);
// 原来的代码为 FFileHelper::SaveArrayToFile(PNGData, *AtlasNameUnprojected);
FFileHelper::SaveArrayToFile(PNGDataUnprojected, *AtlasNameUnprojected);
}


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

查找代码:

TArray<FColor> SphericalLeftEyeAtlas  = SaveAtlas( TEXT( "Left" ), UnprojectedLeftEyeAtlas );
TArray<FColor> SphericalRightEyeAtlas = SaveAtlas(TEXT("Right"), UnprojectedRightEyeAtlas);


在其后添加:

//*NEW* - Begin
if (CombineAtlasesOnOutput)
{
TArray<FColor> CombinedAtlas;
CombinedAtlas.Append(SphericalLeftEyeAtlas);
CombinedAtlas.Append(SphericalRightEyeAtlas);
IImageWrapperPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::JPEG);
ImageWrapper->SetRaw(CombinedAtlas.GetData(), CombinedAtlas.GetAllocatedSize(), SphericalAtlasWidth, SphericalAtlasHeight * 2, ERGBFormat::BGRA, 8);
const TArray<uint8>& PNGData = ImageWrapper->GetCompressed(100);
// Generate name
FString FrameString = FString::Printf(TEXT("Frame_%05d.jpg"), CurrentFrameCount);
FString AtlasName = OutputDir / Timestamp / FrameString;
FFileHelper::SaveArrayToFile(PNGData, *AtlasName);
ImageWrapper.Reset();

}
//*NEW* - END


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



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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  360