![](/img/trans.png)
[英]How to get the DirectX::Image (from DirectXTex) structure based on ID3D11Texture2D?
[英]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。
有人可以在这里看到我做错了吗? Í感谢您的帮助,谢谢! :)
干杯,
我最终可以实现转换。 当从GPU读取渲染的ShaderResource到我的ID3D11Texture2D * undistortedShaderTex中时,足以映射资源并执行一个
memcpy(buffer, mappedData, (screenWidth_ * screenHeight_ * 4));
而不是Loop可以从GPU(混乱的内存布局 )转换为CPU内存布局 。 因此,似乎内存布局已通过某种方式转换。 尽管这对我来说很有趣,因为当我将变形的相机图像作为ShaderResources提供给GPU时,我肯定必须使用上述循环将其转换为GPU内存布局。
我很高兴它现在可以工作了:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.