简介:我用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;
to(从失真的相机字符*内存缓冲区读取相机帧):
frame->imageData = (char*)(ariftcontrol->caminput->lsdslamCameraBuffer);
所以这显然意味着,使用char *缓冲区的东西并不完全正确,但经过数小时的测试后,我看不出原因。首先我认为问题可能是因为我的两个相机都是 R8G8B8A8_UNORM 格式,并且RenderTargetTexture设置为 DXGI_FORMAT_R32G32B32A32_FLOAT (这给了我一个DirectX调试错误消息)。但是我已经将RenderTargetTexture更改为DXGI_FORMAT_R8G8B8A8_UNORM,因此CopyResource()函数可以工作,我还保存了Image,看看它在CopyResource()之后的样子。
这就像DDS(人们可以看到它显然是我未失真的2D相机Image,但我不确定为什么它看起来像.dds那么奇怪):
Undistorted ShaderResource Cameraimage as .dds
在这里它是相同的图像只保存为.jpeg(看起来像预期): UNdistored ShaderResource Cameraimage as .jpeg
这意味着,所有从GPU中的ShaderResource复制到代码行
// SaveDDSTextureToFile(devicecontext_, undistortedShaderTex, L"SCREENSHOT.dds");
似乎正确。正如我上面提到的,为了进行测试,我只将IplImage-&gt; imageData更改为仍然失真的相机char * Buffers,并且转换工作正常。所以它必须与memcpy()部分有关,但我实际上是从我将失真的相机缓冲区复制到GPU ShaderResource的地方复制了它,它就像一个魅力!
注意: CAMERA_CHANNLES是4。
有人能看到我在这里做错了吗? Í感谢每一位帮助,谢谢! :)
欢呼声,
答案 0 :(得分:0)
我终于可以实现转换了。当从GPU读取渲染的ShaderResource到我的ID3D11Texture2D * undistortedShaderTex时,映射资源并执行单个
就足够了 memcpy(buffer, mappedData, (screenWidth_ * screenHeight_ * 4));
而不是Loop从 GPU(swizzled Memory Layout )转换为 CPU内存布局。因此,似乎内存布局已经以某种方式进行了转换。虽然这对我很有意思,因为当我将扭曲的相机图像作为ShaderResources提供给GPU时,我绝对不得不使用上面的循环将其转换为GPU内存布局。
我很高兴它现在有效:)