2016-03-10 6 views
0

Краткое введение: Я написал приложение дополненной реальности с 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.

Может ли кто-нибудь увидеть, что я сделал не так? Н цените каждую помощь, спасибо! :)

веселит,

  • М.
+0

Sidenote: 'если (язык ==«C++») использовать C++ API' – Berriel

ответ

0

я мог бы достичь конверсии, наконец. При чтении обработанной ShaderResource из ГПУ в моем ID3D11Texture2D * undistortedShaderTex, это было достаточно, чтобы отобразить ресурс и сделать один

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

вместо Петля для преобразования из GPU (Layout swizzled памяти) к Формат памяти процессора. Итак, похоже, что макет памяти уже каким-то образом преобразован. Хотя это мне интересно, потому что, когда я подавал свои искаженные изображения камеры как ShaderResources на GPU, мне определенно пришлось преобразовать его в макет памяти графического процессора, используя Loop выше.

Я рад, что он теперь работает :)

+0

Привет, я пытаюсь сделать обратное, преобразовать резюме :: Mat в ID3D11Texture2D , Вы знаете, как это сделать, пожалуйста? – SteveTJS

 Смежные вопросы

  • Нет связанных вопросов^_^