繁体   English   中英

将Shader的DirectX11 ID3D11Texture2D转换为OpenCV IplImage

[英]Converting DirectX11 ID3D11Texture2D from Shader into OpenCV IplImage

简短介绍 :我已经用C ++(DirectX)的Oculus Rift编写了增强现实应用程序。 我的片段着色器之一为全向相机模型计算了不失真。

我现在唯一的问题是读取渲染的不失真texture2D并将其进一步转换为使用OpenCV进行真实世界的3DPose跟踪/映射。 有趣的是,我已经做了另一种方法,这意味着我已经使用变形的相机imageBuffers创建了着色器资源视图以实现不失真。 但是不知何故,我现在陷入了另一种困境。

这是我停留在的代码:

void GraphicsAPI::UndistortionForLsdSlam()
{
  // ------------------------------------ [ Version 4 ] 
  // Get Pointer to the rendered Shader Resource (Camera Undistortion)
  ID3D11Resource* renderBuffer;
  renderTextureRight_->GetRenderTargetView()->GetResource(&renderBuffer);

  D3D11_TEXTURE2D_DESC texDesc;
  texDesc.ArraySize = 1;
  texDesc.BindFlags = 0;
  texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  texDesc.Width = screenWidth_;
  texDesc.Height = screenHeight_;
  texDesc.MipLevels = 1;
  texDesc.MiscFlags = 0;
  texDesc.SampleDesc.Count = 1;
  texDesc.SampleDesc.Quality = 0;
  texDesc.Usage = D3D11_USAGE_STAGING;

  // Copy Data from GPU only, into CPU Accessable Memory 
  ID3D11Texture2D* undistortedShaderTex;
  device_->CreateTexture2D(&texDesc, 0, &undistortedShaderTex);
  devicecontext_->CopyResource(undistortedShaderTex, renderBuffer);

  // SaveDDSTextureToFile(devicecontext_, undistortedShaderTex, L"SCREENSHOT.dds");

  // Map Resource GPU Resource
  D3D11_MAPPED_SUBRESOURCE mappedResource;
  if (FAILED(devicecontext_->Map(undistortedShaderTex, 0, D3D11_MAP_READ, 0, &mappedResource)))
    std::cout << "Error: [CAM 2] could not Map Rendered Camera ShaderResource for Undistortion" << std::endl;

  // Copy Memory of GPU Memory Layout (swizzled) to CPU
  char* buffer = new char[(screenWidth_ * screenHeight_ * CAMERA_CHANNELS)];
  char* mappedData = static_cast<char*>(mappedResource.pData);
  for (UINT i = 0; i < screenHeight_; i++)
  {
    memcpy(buffer, mappedData, screenWidth_ * 4);
    mappedData += mappedResource.RowPitch;
    buffer += screenWidth_ * 4;
  }
  std::cout << "FINISHED LOOP .. " << std::endl;
  devicecontext_->Unmap(undistortedShaderTex, 0);

  // OpenCV IplImage Convertion
  IplImage* frame = cvCreateImageHeader(cvSize(screenWidth_, screenHeight_), IPL_DEPTH_8U, CAMERA_CHANNELS);
  frame->imageData = (char*)buffer;
  frame->imageDataOrigin = frame->imageData;
  cv::Mat mymat = cv::Mat(frame, true); // Access Violation here(!)
  cv::imshow("Shader Undistortion", mymat);

错误讯息:

ARift.exe中0x680EF41C(msvcr120.dll)的未处理异常:0xC0000005:访问冲突读取位置0x1FD4EFFC

尝试在使用先前创建的IplFrame创建cv :: Mat()时发生访问冲突。 出于测试目的,我更改了一行代码以使用变形的相机缓冲区来测试OpenCV转换,并且可以正常工作:

frame->imageData = (char*)buffer;

到(从变形的相机字符*内存缓冲区读取相机帧):

frame->imageData = (char*)(ariftcontrol->caminput->lsdslamCameraBuffer);

因此,这显然意味着,使用char *缓冲区的某些内容并不十分正确,但是经过数小时的测试,我看不到为什么。 首先,我认为问题可能是因为我的两个摄像机都是R8G8B8A8_UNORM格式,并且RenderTargetTexture设置为DXGI_FORMAT_R32G32B32A32_FLOAT (这给了我DirectX调试错误msg)。 但是我已经将RenderTargetTexture更改为DXGI_FORMAT_R8G8B8A8_UNORM,因此CopyResource()函数可以正常工作,并且我还保存了Image以查看在CopyResource()之后的外观。

这就是DDS(可以清楚地看到它是我未变形的2D摄像机图像,但是我不确定为什么它看起来像.dds一样奇怪):

未失真的ShaderResource Cameraimage为.dds

这是只保存为.jpeg的图像(按预期方式查找 ):未变形的ShaderResource Cameraimage为.jpeg

这意味着从GPU中的ShaderResource复制所有代码,直到代码行

// SaveDDSTextureToFile(devicecontext_, undistortedShaderTex, L"SCREENSHOT.dds");

似乎正确。 正如我上面提到的,为了进行测试,我仅将IplImage-> imageData更改为仍失真的相机char *缓冲区,并且转换有效。 因此,它必须与memcpy()部分有关,但是实际上是从将变形的相机缓冲区复制到GPU ShaderResource的地方复制的,它就像一个魅力一样!

注意: CAMERA_CHANNLES这里是4。

有人可以在这里看到我做错了吗? Í感谢您的帮助,谢谢! :)

干杯,

  • M.

我最终可以实现转换。 当从GPU读取渲染的ShaderResource到我的ID3D11Texture2D * undistortedShaderTex中时,足以映射资源并执行一个

    memcpy(buffer, mappedData, (screenWidth_ * screenHeight_ * 4));

而不是Loop可以从GPU(混乱的内存布局 )转换为CPU内存布局 因此,似乎内存布局已通过某种方式转换。 尽管这对我来说很有趣,因为当我将变形的相机图像作为ShaderResources提供给GPU时,我肯定必须使用上述循环将其转换为GPU内存布局。

我很高兴它现在可以工作了:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM