UTexture2D* PrivateLeapImage::validImagePointer(UTexture2D* Pointer, int32 PWidth, int32 PHeight, EPixelFormat Format, bool GammaCorrectionUsed) { //Make sure we're valid if (!Self->IsValid) { UE_LOG(LeapPluginLog, Error, TEXT("Warning! Invalid Image.")); return nullptr; } //Instantiate the texture if needed if (Pointer == nullptr) { if (PWidth == 0 || PHeight == 0) { //Spit out only valid errors, two size 0 textures will be attempted per pointer, //unable to filter the messages out without this (or a pointer to Leap Controller, but this uses less resources). if (IgnoreTwoInvalidSizesDone) { UE_LOG(LeapPluginLog, Error, TEXT("Warning! Leap Image SDK access is denied, please enable image support from the Leap Controller before events emit (e.g. at BeginPlay).")); } else { InvalidSizesReported++; if (InvalidSizesReported == 2) { IgnoreTwoInvalidSizesDone = true; } } return nullptr; } UE_LOG(LeapPluginLog, Log, TEXT("Created Leap Image Texture Sized: %d, %d, format %d"), PWidth, PHeight, (int)Format); Pointer = UTexture2D::CreateTransient(PWidth, PHeight, Format); //PF_B8G8R8A8 Pointer->UpdateResource(); UpdateTextureRegion = FUpdateTextureRegion2D(0, 0, 0, 0, PWidth, PHeight); //change texture settings if (!GammaCorrectionUsed) { Pointer->SRGB = 0; } //keep it around? } //If the size changed, recreate the image (NB: GC may release the platform data in which case we need to recreate it (since 4.7) if (!UtilityPointerIsValid(Pointer->PlatformData) || Pointer->PlatformData->SizeX != PWidth || Pointer->PlatformData->SizeY != PHeight) { UE_LOG(LeapPluginLog, Log, TEXT("ReCreated Leap Image Texture Sized: %d, %d. Old Size: %d, %d"), PWidth, PHeight, Pointer->PlatformData->SizeX, Pointer->PlatformData->SizeY); Pointer = UTexture2D::CreateTransient(PWidth, PHeight, Format); Pointer->UpdateResource(); UpdateTextureRegion = FUpdateTextureRegion2D(0, 0, 0, 0, PWidth, PHeight); } return Pointer; }
// Called when the game starts void UOpenCVComponent::BeginPlay() { Super::BeginPlay(); // ... if (nullptr != Texture2D) { if (cv::ocl::haveOpenCL()) { cv::ocl::Context Context; if (Context.create(cv::ocl::Device::TYPE_GPU)) { cv::ocl::Device(Context.device(0)); //!< Simple OpenCL Code const cv::String Code = "__kernel void main(__global uchar* dst, const int pitch, const int offset, const int rows, const int cols) {" "const int2 uv = { get_global_id(0), get_global_id(1) };" "const int2 dim = { rows, cols };" "const int2 grid = { 16, 16 };" "const int2 repeate = dim / grid;" "const int index = mad24(uv.y, pitch, uv.x + offset);" "dst[index] = ((uv.x % grid.x) * repeate.x >> 1) + ((uv.y % grid.y) * repeate.y >> 1);" "}"; const cv::ocl::ProgramSource ProgramSource(Code); //!< Build OpenCL const cv::String Buildopt = ""; cv::String Errmsg; const auto Program = Context.getProg(ProgramSource, Buildopt, Errmsg); const auto Width = Texture2D->GetSizeX(); const auto Height = Texture2D->GetSizeY(); //!< Result destination const auto Mat = cv::UMat(Height, Width, CV_8U, cv::ACCESS_WRITE, cv::USAGE_ALLOCATE_DEVICE_MEMORY); //!< OpenCL function name and arguments cv::ocl::Kernel Kernel("main", Program); Kernel.args(cv::ocl::KernelArg::ReadWrite(Mat)); //!< Execute OpenCL size_t Threads[] = { Width, Height, 1 }; if (!Kernel.run(ARRAY_COUNT(Threads), Threads, nullptr, true)) { GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("OpenCL run failed")); } const auto Result = Mat.getMat(cv::ACCESS_READ); //!< Add some OpenCV operations cv::putText(Mat, cv::String("Hello OpenCV"), cv::Point(0, 255), CV_FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(0, 127, 127)); cv::rectangle(Mat, cv::Point(64 + 5, 64 + 5), cv::Point(96 + 5, 96 + 5), cv::Scalar(0, 255, 0)); cv::circle(Mat, cv::Point(128, 128), 32, cv::Scalar(0, 0, 255)); //cv::imshow("Result", Result); //!< cv::Mat -> TArray<FColor> Colors.Empty(); Colors.Reserve(Width * Height); for (auto i = 0; i < Height; ++i) { for (auto j = 0; j < Width; ++j) { const auto Value = Result.data[i * Width + j]; Colors.Add(FColor(Value, Value, Value)); } } //!< Update UTexture2D ENQUEUE_RENDER_COMMAND(UpdateTexture2D)( [Tex = Texture2D, this](FRHICommandListImmediate& RHICmdList) { const auto TexWidth = Tex->GetSizeX(); const auto TexHeight = Tex->GetSizeY(); const auto Pitch = GPixelFormats[Tex->GetPixelFormat()].BlockBytes * TexWidth; RHIUpdateTexture2D(Tex->Resource->TextureRHI->GetTexture2D(), 0, FUpdateTextureRegion2D(0, 0, 0, 0, TexWidth, TexHeight), Pitch, reinterpret_cast<const uint8*>(&Colors[0])); }); } } } }