Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
865 views
in Technique[技术] by (71.8m points)

opencv - Get cv::Mat from ID3D11Texture2D c++

I try to create video AVI format from ID3D11Texture2D by using OpenCV.

Step 1 I transform texture into QByteArray and get QImage

Step 2 Then JPG format I save in QBuffer and create new QByteArray

Step 3 By using the QByteArray I get cv::Mat that serves as a frame for VideoWriter

Here is the solid script that creates video:

        D3D11_MAPPED_SUBRESOURCE* resource = new D3D11_MAPPED_SUBRESOURCE;
        UINT subresource = D3D11CalcSubresource(0, 0, 0);

        lImmediateContext->Map(texture, subresource, D3D11_MAP_READ_WRITE, 0, resource);

        EImgByteFormat fmt = BF_R8G8B8A8;
        if (desc.Format == DXGI_FORMAT_B8G8R8A8_UNORM ||
            desc.Format == DXGI_FORMAT_B8G8R8X8_UNORM ||
            desc.Format == DXGI_FORMAT_B8G8R8A8_TYPELESS ||
            desc.Format == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB ||
            desc.Format == DXGI_FORMAT_B8G8R8X8_TYPELESS ||
            desc.Format == DXGI_FORMAT_B8G8R8X8_UNORM_SRGB)
        {
            fmt = BF_B8G8R8A8;
        }
       QByteArray rawData = PackImageData(fmt, (char*)resource->pData, desc.Height, desc.Width);
       uint32_t rows = *(uint32_t*)(rawData.data() + 1);
       uint32_t columns = *(uint32_t*)(rawData.data() + 1 + 4);
       QImage screenshot = RawDataToQImage(fmt, rawData.data() + 1 + 4 + 4, rows, columns);

       QByteArray arr;
       QBuffer buffer(&arr);
       buffer.open(QIODevice::WriteOnly);
       screenshot.save(&buffer, "JPG");
       buffer.close();

       Mat frame = imdecode(std::vector<uchar>(arr.begin(), arr.end()), 1);
       VideoWriter oVideoWriter("TestVideo.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), frames_per_second, frame_size, true);
       oVideoWriter << frame;
       oVideoWriter.release();

I want to skip step 1 and step 2 and promptly transform texture into cv::Mat, but I am not exactly sure how to get it. Here is an example of the script:

        char* buffer = new char[desc.Width * desc.Height * 4];
        char* mappedData = static_cast<char*>(resource->pData);

        memcpy(buffer, mappedData, desc.Width * desc.Height * 4);

        // OpenCV IplImage Convertion
        IplImage* frame = cvCreateImageHeader(cvSize(desc.Width, desc.Height), IPL_DEPTH_8U, 4);
        frame->imageData = (char*)buffer;
        frame->imageDataOrigin = frame->imageData;
        Mat mat = cvarrToMat(frame, true);
        imshow("Frame", mat);

       VideoWriter oVideoWriter("TestVideo.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), frames_per_second, frame_size, true);
       oVideoWriter << mat;
       oVideoWriter.release();

Or is it possible to directly get cv :: Mat from the texture:

Mat frame(desc.Height, desc.Width, CV_8U, resource->pData, (int)resource->RowPitch)
cv::directx::convertFromD3D11Texture2D(texture, frame)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...