-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Save image from target render every frame. #37
Comments
Hey, What do you mean by freeze? Properly freeze and crash, or just very slow but you still get logs and images? I only skimmed the code... The thing that looked most suspicious to me is this (below): Depending on the behavior of RenderFence.Wait() it looks like either an infinite loop or perhaps interferes with the game-thread because your game thread waits long times for the render to finish.
|
Hey thanks for your quick response. I got your point. i did it to check what is causing the issue. Its working now but it drops my fps to 8 from 80. These are my code. Even the sensor warmup as you can see in the code where i am not doing anything brings my fps to 14. I would really appreciate if you can tell me whats the problem here.
|
Previously, PR #20 pointed out that Anyhow.. that could be the issue. Even when not writing to disk you already fetch the data into RAM. Depending on your resolution that can be quite a bit of data. |
Hi Timm, |
@shekharsuman3 The alignment is perhaps due to the fact that the bytes are packed in a certain way? I am not sure about the details, but in UE5.3 the function returns an additional parameter called OutRowPitchInPixels, which are essentially the amount of pixels per row stored in the databuffer: |
Hello Everyone,
I am trying to capture and save image to disc every frame from a camera sensor in unreal engine 5.2. At every tick i try to capture and save image to disc. i tried to use code from this repo. But when i try to save every frame, scene freezes and same image is rendered at every frame. but if i capture image at alternate frame it works. Here are my code. I would really appreciate any help.
// PinHoleCineCamera.cpp
#include "PinHoleCineCamera.h"
#include "Engine.h"
#include "Engine/SceneCapture2D.h"
#include "Runtime/Engine/Classes/Components/SceneCaptureComponent2D.h"
#include "CineCameraComponent.h"
#include "Kismet/GameplayStatics.h"
#include "ShowFlags.h"
#include "RHICommandList.h"
#include "ImageWrapper/Public/IImageWrapper.h"
#include "ImageWrapper/Public/IImageWrapperModule.h"
#include "ImageUtils.h"
#include "Modules/ModuleManager.h"
#include "Misc/FileHelper.h"
#include "Engine/TextureRenderTarget2D.h"
#include "Engine/Texture2D.h"
#include "Misc/FileHelper.h"
#include "IImageWrapper.h"
#include "HAL/PlatformProcess.h"
#include "RenderingThread.h"
#include "ImageUtils.h"
#include "Engine/World.h"
#include "Engine/GameViewportClient.h"
#include "IImageWrapperModule.h"
APinHoleCineCamera::APinHoleCineCamera(const FObjectInitializer& ObjectInitializer) : ACineCameraActor(ObjectInitializer)
{
//RootComponent = CreateDefaultSubobject(TEXT("RootComponent"));
UCineCameraComponent* CineCameraComponent1 = GetCineCameraComponent();
SceneCaptureComponent = CreateDefaultSubobject(TEXT("SceneCaptureComponent"));
SceneCaptureComponent->AttachToComponent(CineCameraComponent1, FAttachmentTransformRules::KeepRelativeTransform);
// Set the SceneCaptureComponent properties
SceneCaptureComponent->ProjectionType = ECameraProjectionMode::Perspective;
//SceneCaptureComponent->OrthoWidth = 0.0f; // Set OrthoWidth to 0 for perspective projection
SceneCaptureComponent->FOVAngle = 93.665;
// Set Camera Properties
SceneCaptureComponent->CaptureSource = ESceneCaptureSource::SCS_FinalColorHDR;
SceneCaptureComponent->ShowFlags.SetTemporalAA(true);
}
void APinHoleCineCamera::AttachPinHoleCameraToVehicle(AActor* Vehicle, PINHOLECINECAMERACfg SensorCfg_, float FixedDeltaTime_) {
}
void APinHoleCineCamera::GetPinHoleCineCameraData() {
const uint32_t Timestamp = std::round(FixedDeltaTime * Frame * 1000);
Frame = Frame + 1U;
// Read pixels once RenderFence is completed
if (!RenderRequestQueue.IsEmpty()) {
// Peek the next RenderRequest from queue
FRenderRequestStruct* nextRenderRequest = nullptr;
RenderRequestQueue.Peek(nextRenderRequest);
if (nextRenderRequest) { //nullptr check
if (nextRenderRequest->RenderFence.IsFenceComplete()) { // Check if rendering is done, indicated by RenderFence
// Load the image wrapper module
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked(FName("ImageWrapper"));
FString FrameNumberString = FString::Printf(TEXT("%06d.png"), Timestamp);
FString FilePath = FPaths::Combine(SensorCfg.PathSave, FrameNumberString);
static TSharedPtr imageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG); //EImageFormat::PNG //EImageFormat::JPEG
imageWrapper->SetRaw(nextRenderRequest->Image.GetData(), nextRenderRequest->Image.GetAllocatedSize(), FrameWidth, FrameHeight, ERGBFormat::BGRA, 8);
const TArray64& ImgData = imageWrapper->GetCompressed(5);
//const TArray& ImgData = static_cast<TArray<uint8, FDefaultAllocator>> (imageWrapper->GetCompressed(5));
RunAsyncImageSaveTask(ImgData, FilePath);
}
}
}
}
void APinHoleCineCamera::CaptureNonBlocking() {
if (!IsValid(SceneCaptureComponent)) {
UE_LOG(LogTemp, Error, TEXT("CaptureColorNonBlocking: CaptureComponent was not valid!"));
return;
}
SceneCaptureComponent->TextureTarget->TargetGamma = GEngine->GetDisplayGamma();
FTextureRenderTargetResource* renderTargetResource = SceneCaptureComponent->TextureTarget->GameThread_GetRenderTargetResource();
}
void APinHoleCineCamera::RunAsyncImageSaveTask(TArray64 Image, FString ImageName) {
(new FAutoDeleteAsyncTask(Image, ImageName))->StartBackgroundTask();
}
AsyncSaveImageToDiskTask::AsyncSaveImageToDiskTask(TArray64 Image, FString ImageName) {
ImageCopy = Image;
FileName = ImageName;
}
AsyncSaveImageToDiskTask::~AsyncSaveImageToDiskTask() {
UE_LOG(LogTemp, Warning, TEXT("AsyncTaskDone"));
}
void AsyncSaveImageToDiskTask::DoWork() {
FFileHelper::SaveArrayToFile(ImageCopy, *FileName);
//UE_LOG(LogTemp, Error, TEXT("Stored Image: %s"), *FileName);
}
// PinHoleCineCamera.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "CineCameraActor.h"
#include "Containers/Queue.h"
#include "Engine/SceneCapture2D.h"
#include "Components/SceneCaptureComponent2D.h"
#include "PinHoleCineCamera.generated.h"
struct PINHOLECINECAMERACfg {
// Rotation from sensor coordinate system to vehicle coordinate system.
FRotator RotationSensorToVehicle;
// Translation from sensor coordinate system to vehicle coordinate system.
FVector TranslationSensorToVehicle;
// Path where to save the csv logger file.
FString PathSave;
// Sensor frequency
float Frequency;
};
USTRUCT()
struct FRenderRequestStruct {
GENERATED_BODY()
TArray Image;
FRenderCommandFence RenderFence;
FRenderRequestStruct() {}
};
UCLASS()
class AVL_UE5_API APinHoleCineCamera : public ACineCameraActor{
GENERATED_BODY()
public:
APinHoleCineCamera(const FObjectInitializer& ObjectInitializer);
protected:
//virtual void BeginPlay() override;
virtual void BeginPlay() override {
Super::BeginPlay();
};
public:
//virtual void Tick(float DeltaTime) override;
void AttachPinHoleCameraToVehicle(AActor* Vehicle, PINHOLECINECAMERACfg SensorCfg, float FixedDeltaTime);
void GetPinHoleCineCameraData();
UFUNCTION(BlueprintCallable, Category = "ImageCapture")
void CaptureNonBlocking();
//bool IsPreviousFenceComplete() const;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture")
int FrameWidth = 4112;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture")
int FrameHeight = 2176;
protected:
int ImgCounter = 0;
void RunAsyncImageSaveTask(TArray64 Image, FString ImageName);
// RenderRequest Queue
TQueue<FRenderRequestStruct*> RenderRequestQueue;
private:
UPROPERTY(EditAnywhere, Category = "Capture")
USceneCaptureComponent2D* SceneCaptureComponent;
PINHOLECINECAMERACfg SensorCfg;
FString TestSequenceNumber;
float FixedDeltaTime;
int32_t Frame = 0;
};
class AsyncSaveImageToDiskTask : public FNonAbandonableTask {
public:
AsyncSaveImageToDiskTask(TArray64 Image, FString ImageName);
~AsyncSaveImageToDiskTask();
FORCEINLINE TStatId GetStatId() const {
RETURN_QUICK_DECLARE_CYCLE_STAT(AsyncSaveImageToDiskTask, STATGROUP_ThreadPoolAsyncTasks);
}
protected:
TArray64 ImageCopy;
FString FileName = "";
public:
void DoWork();
};
The text was updated successfully, but these errors were encountered: