UE4中採集360°全景圖片和視頻

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/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章