使用dxgi截图的时候如果桌面不发生变化好像就不会正常捕获,用imshow展现出来的窗口会黑屏,这是我的代码,我需要如何改进
#include <dxgi1_2.h>
#include <d3d11.h>
#include <wrl/client.h>
#include <opencv2/opencv.hpp>
#include <iostream>
using Microsoft::WRL::ComPtr;
cv::Mat capture_screen_dxgi() {
// 初始化 D3D11 设备和上下文
ComPtr<ID3D11Device> d3dDevice;
ComPtr<ID3D11DeviceContext> d3dContext;
D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &d3dDevice, nullptr, &d3dContext);
// 获取 DXGI 设备
ComPtr<IDXGIDevice> dxgiDevice;
d3dDevice.As(&dxgiDevice);
// 获取 DXGI 工厂
ComPtr<IDXGIAdapter> dxgiAdapter;
dxgiDevice->GetAdapter(&dxgiAdapter);
ComPtr<IDXGIFactory2> dxgiFactory;
dxgiAdapter->GetParent(__uuidof(IDXGIFactory2), &dxgiFactory);
// 获取输出(即屏幕)
ComPtr<IDXGIOutput> dxgiOutput;
dxgiAdapter->EnumOutputs(0, &dxgiOutput);
// 获取输出的描述
DXGI_OUTPUT_DESC outputDesc;
dxgiOutput->GetDesc(&outputDesc);
// 创建输出复制(duplication)接口
ComPtr<IDXGIOutput1> dxgiOutput1;
dxgiOutput.As(&dxgiOutput1);
ComPtr<IDXGIOutputDuplication> outputDuplication;
dxgiOutput1->DuplicateOutput(d3dDevice.Get(), &outputDuplication);
// 轮询并获取屏幕帧
DXGI_OUTDUPL_FRAME_INFO frameInfo;
ComPtr<IDXGIResource> desktopResource;
HRESULT hr = outputDuplication->AcquireNextFrame(500, &frameInfo, &desktopResource);
if (FAILED(hr)) {
std::cerr << "Failed to acquire frame from output duplication!" << std::endl;
return cv::Mat();
}
// 获取帧资源
ComPtr<ID3D11Texture2D> acquiredDesktopImage;
desktopResource.As(&acquiredDesktopImage);
// 获取屏幕描述
D3D11_TEXTURE2D_DESC textureDesc;
acquiredDesktopImage->GetDesc(&textureDesc);
// 创建 CPU 访问的纹理
D3D11_TEXTURE2D_DESC cpuTextureDesc = textureDesc;
cpuTextureDesc.Usage = D3D11_USAGE_STAGING;
cpuTextureDesc.BindFlags = 0;
cpuTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
cpuTextureDesc.MiscFlags = 0;
ComPtr<ID3D11Texture2D> cpuTexture;
d3dDevice->CreateTexture2D(&cpuTextureDesc, nullptr, &cpuTexture);
// 将屏幕图像拷贝到 CPU 访问的纹理中
d3dContext->CopyResource(cpuTexture.Get(), acquiredDesktopImage.Get());
// 映射纹理以获取数据
D3D11_MAPPED_SUBRESOURCE mappedResource;
d3dContext->Map(cpuTexture.Get(), 0, D3D11_MAP_READ, 0, &mappedResource);
// 创建 OpenCV Mat 对象
cv::Mat screenshot(textureDesc.Height, textureDesc.Width, CV_8UC4, mappedResource.pData, mappedResource.RowPitch);
// 解锁资源
d3dContext->Unmap(cpuTexture.Get(), 0);
outputDuplication->ReleaseFrame();
// 转换为 BGR 格式
cv::cvtColor(screenshot, screenshot, cv::COLOR_BGRA2BGR);
return screenshot;
}