Краткое введение: Я написал приложение дополненной реальности с Oculus Rift в C++ (DirectX). Один из моих шейдеров фрагментов вычисляет неискаженное значение для всенаправленной модели камеры.Преобразование DirectX11 ID3D11Texture2D от Shader в OpenCV IplImage
Единственная проблема, с которой я столкнулся сейчас, - это прочитать рендеринговую нестационарную текстуру2D и преобразовать ее для 3DPose Tracking/Mapping реального мира с использованием OpenCV. Смешная вещь, я уже делал наоборот, а это значит, что я уже создал шейдерные представления ресурсов с искаженной камерой 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);
Error Msg:
Необработанное исключение в 0x680EF41C (msvcr120.dll) в ARift.exe: 0xC0000005: Access место обнаружения ошибок 0x1FD4EFFC
Нарушение доступа происходит точно в момент, когда пытаясь создать cv :: Mat() с ранее созданным IplFrame. Для целей тестирования, я изменил одну строку кода для тестирования преобразования OpenCV с моей искаженной буфер камеры, и она работала:
frame->imageData = (char*)buffer;
с (чтение кадр камеры с искаженной полукокса камеры * буфера памяти):
frame->imageData = (char*)(ariftcontrol->caminput->lsdslamCameraBuffer);
Значит, это означает, что что-то с буфером char * не совсем корректно, но после нескольких часов тестирования я не понимаю, почему. Сначала я думал, что проблема может быть связана с тем, что обе мои камеры - это R8G8B8A8_UNORM Формат и RenderTargetTexture были установлены в DXGI_FORMAT_R32G32B32A32_FLOAT (что дало мне сообщение об ошибке Debug DirectX). Но я уже изменил RenderTargetTexture на DXGI_FORMAT_R8G8B8A8_UNORM, поэтому функция CopyResource() работает, и я также сохранил изображение, чтобы увидеть, как это выглядит после CopyResource().
Здесь, как СОД (можно увидеть, что это ясно моя неискаженное 2D камеры изображения, но я не знаю, почему он выглядит так странно, как .dds):
Undistorted ShaderResource Cameraimage as .dds
И здесь то же самое изображение сохраняется только в формате .jpeg (Смотрит, как и ожидалось): UNdistored ShaderResource Cameraimage as .jpeg
Это означает, что все копирование с ShaderResource в ГПУ, пока строка кода
// SaveDDSTextureToFile(devicecontext_, undistortedShaderTex, L"SCREENSHOT.dds");
Правильно. И, как я уже упоминал выше, для тестирования я только изменил IplImage-> imageData на мои все еще искаженные камеры char * Buffers, и преобразование сработало. Так что это должно быть что-то с частью memcpy(), но я скопировал это на самом деле с того места, где я скопировал свои искаженные буферы камеры в GPU ShaderResource, который работал как шарм!
Примечание: CAMERA_CHANNLES здесь 4.
Может ли кто-нибудь увидеть, что я сделал не так? Н цените каждую помощь, спасибо! :)
веселит,
- М.
Sidenote: 'если (язык ==«C++») использовать C++ API' – Berriel