Краткое введение. Я написал приложение дополненной реальности с Oculus Rift на C++ (DirectX). Один из моих фрагментных шейдеров вычисляет неискажение для модели всенаправленной камеры.
Единственная проблема, с которой я столкнулся сейчас, - это прочитать визуализированную неискаженную текстуру 2D и преобразовать ее для 3DPose Tracking/Mapping реального мира с использованием OpenCV. Самое смешное, что я уже сделал наоборот, а это значит, что я уже создал представления ресурсов шейдера с моими искаженными буферами изображения камеры для неискажения. Но почему-то я застрял сейчас в обратном направлении.
Вот код, на котором я застрял:
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);
Сообщение об ошибке:
Необработанное исключение по адресу 0x680EF41C (msvcr120.dll) в ARift.exe: 0xC0000005: место чтения с нарушением прав доступа 0x1FD4EFFC
Нарушение прав доступа происходит именно при попытке создать cv::Mat() с ранее созданным IplFrame. В целях тестирования я изменил одну строку кода, чтобы проверить преобразование OpenCV с моим искаженным буфером камеры, и это сработало:
frame->imageData = (char*)buffer;
to (чтение кадра камеры из искаженного буфера памяти char*):
frame->imageData = (char*)(ariftcontrol->caminput->lsdslamCameraBuffer);
Итак, это, очевидно, означает, что что-то с буфером char* не совсем правильно, но после нескольких часов тестирования я не понимаю, почему. Сначала я подумал, что проблема может заключаться в том, что обе мои камеры имеют формат R8G8B8A8_UNORM, а для RenderTargetTexture установлено значение DXGI_FORMAT_R32G32B32A32_FLOAT (что дало мне сообщение об ошибке отладки DirectX). Но я уже изменил RenderTargetTexture на DXGI_FORMAT_R8G8B8A8_UNORM, чтобы функция CopyResource() работала, и я также сохранил изображение, чтобы посмотреть, как оно выглядит после CopyResource().
Вот оно в формате DDS (видно, что это мое неискаженное 2D-изображение с камеры, но я не уверен, почему оно выглядит так странно, как .dds):
Неискаженное изображение камеры ShaderResource как .dds
А вот это то же самое изображение, только сохраненное как .jpeg (выглядит, как и ожидалось): неискаженное изображение ShaderResource Cameraimage как . jpeg
Это означает, что все копирование из ShaderResource в GPU до строки кода
// SaveDDSTextureToFile(devicecontext_, undistortedShaderTex, L"SCREENSHOT.dds");
Кажется правильным. И, как я упоминал выше, для тестирования я только изменил IplImage->imageData на мои все еще искаженные буферы камеры char *, и преобразование сработало. Так что это должно быть что-то с частью memcpy(), но я скопировал это на самом деле из того места, где я скопировал свои искаженные буферы камеры, в GPU ShaderResource, который работал как шарм!
Примечание. CAMERA_CHANNLES здесь 4.
Может ли кто-нибудь увидеть, что я сделал неправильно здесь? Я ценю каждую помощь, спасибо! :)
ваше здоровье,
- M.
if (language == "c++") use c++ API
- person Berriel   schedule 11.03.2016