Функция OpenCV convertToD3D11Texture2D вызывает нарушение прав доступа - PullRequest
0 голосов
/ 11 июля 2019

Я создаю приложение на C ++ для Windows, используя DirectX для отображения изображений PPM в HDR.Я использую cv::imread для чтения файла в Mat, а затем создаю текстуру ID3D11Texture2D*.Однако, когда я запускаю его, я получаю нарушение прав доступа при запуске cv::directx::convertToD3D11Texture2D(mat, tex), который говорит, что tex - это NULL.

Насколько я понимаю, CreateTexture2D инициализирует текстуру, а convertToD3D11Texture2D копируетизображение к текстуре.

Это соответствующий код:

auto mat = cv::imread("fileL.ppm", cv::IMREAD_ANYCOLOR | cv::IMREAD_ANYDEPTH);

D3D11_TEXTURE2D_DESC desc;
desc.Width = 3840;
desc.Height = 2160;
desc.MipLevels = desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;

ID3D11Texture2D* tex = nullptr;

m_resources->GetDevice()->CreateTexture2D(&desc, nullptr, &tex);


cv::directx::convertToD3D11Texture2D(mat, tex);

В частности, ошибки:

0x00007FFC4750A839 in file.exe: Microsoft C++ exception: _com_error at memory location 0x00000045A28FF340.
Exception thrown at 0x00007FFBCD08A390 (opencv_world410d.dll) in file.exe: 0xC0000005: Access violation reading location 0x0000000000000000.

Редактировать : последобавив desc.SampleDesc.quality = 0, я больше не получаю ошибки для CreateTexture2D, но получаю общее исключение в convertToD3D11Texture2D: Exception at memory location 0x0000002A3836E8D0

Edit 2 : после кэширования исключениясообщение об исключении:

OpenCV(4.1.0) c:\build\master_winpack-build-win64-vc15\opencv\modules\core\src\directx.cpp:1040: error: (-215:Assertion failed) textureType == srcType in function 'cv::directx::__convertToD3D11Texture2DNV'

1 Ответ

0 голосов
/ 12 июля 2019

После того, как я наконец смог правильно отладить ошибку, я обнаружил, что проблема была в том, что моя входная матрица имела 3 канала, а не 4. Чтобы исправить это, я использовал cv::mixChannels, чтобы добавить пустой альфа-канал, и теперь тип моей текстуры и совпадение матрицы.

Рабочий код:

cv::Mat mat = cv::imread("file.ppm", cv::IMREAD_ANYCOLOR | cv::IMREAD_ANYDEPTH);
    cv::Mat as4channelMat(mat.size(), CV_MAKE_TYPE(mat.depth(), 4));

    int conversion[] = { 0, 0, 1, 1, 2, 2, -1, 3 };
    cv::mixChannels(&mat, 1, &as4channelMat, 1, conversion, 4);

    D3D11_TEXTURE2D_DESC desc;
    desc.Width = 3840;
    desc.Height = 2160;
    desc.MipLevels = desc.ArraySize = 1;
    desc.Format = DXGI_FORMAT_R16G16B16A16_UNORM;
    desc.SampleDesc.Count = 1;
    desc.SampleDesc.Quality = 0;
    desc.Usage = D3D11_USAGE_DEFAULT;
    desc.BindFlags = 0;
    desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
    desc.MiscFlags = 0;

    ID3D11Texture2D* tex = nullptr;

    auto hr = m_resources->GetDevice()->CreateTexture2D(&desc, nullptr, &tex);

    if FAILED(hr)
    {
        _com_error err(hr);
        LPCTSTR errMsg = err.ErrorMessage();
    }

    try {
        cv::directx::convertToD3D11Texture2D(as4channelMat, tex);
    } catch (cv::Exception& e)
    {
        std::cerr << "ERROR: " << e.msg << std::endl;
        throw e;
    }
...