【发布时间】:2017-03-01 21:23:33
【问题描述】:
我正在开发的应用程序目前正在截取基于 DirectX 的游戏的屏幕截图。
使用 IDirect3DDevice9::GetBackBuffer 会产生 IDirect3DDevice9 对象。
现在我正在寻找一种直接获取原始图像的方法,因为我需要稍后在OpenCV中对其进行处理。
我发现的唯一例子是在OpenCV directx samples,所以我尝试用以下方式初始化cv::Mat:
IDirect3DSurface9* pSurface = nullptr;
auto cops = pDevice->CreateOffscreenPlainSurface(ScreenWidth, ScreenHeight, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL);
auto gfbd = pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pSurface);
D3DLOCKED_RECT lockedRect;
ZeroMemory(&lockedRect, sizeof(D3DLOCKED_RECT));
pSurface->LockRect(&lockedRect, 0, D3DLOCK_READONLY);
//**** OpenCV
cv::Mat D3DSurface(ScreenHeight, ScreenWidth, CV_8UC4, lockedRect.pBits, lockedRect.Pitch);
cv::imshow("D3DSurface", D3DSurface);
不幸的是,它抛出了以下异常:d:\lib\opencv\build\install\include\opencv2\core\mat.inl.hpp:410: error: (-215) total() == 0 || data != 函数 cv::Mat::Mat 中的 NULL
我知道我可以通过将IDirect3DSurface9 保存到一个文件然后用cv::imread 读取它来做到这一点,但我宁愿避免不必要的磁盘操作,除非没有其他办法。
顺便说一句,将IDirect3DSurface9 保存到文件中工作正常,我使用以下方法进行了检查:
D3DXSaveSurfaceToFile(L"D:\\ss1.bmp", D3DXIFF_BMP, pSurface, NULL, NULL);
编辑:
正如@Asesh提到的,我尝试使用D3DXSaveSurfaceToFileInMemory,现在代码是这样的:
LPD3DXBUFFER buffer;
D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_BMP, pSurface, NULL, NULL);
DWORD imSize = buffer->GetBufferSize();
void* imgBuffer = buffer->GetBufferPointer();
//**** OpenCV
cv::Mat D3DSurface(ScreenHeight, ScreenWidth, CV_8UC4, imgBuffer);
cv::imshow("D3DSurface", D3DSurface);
cv::Mat创建成功,但是变形了。图片反转应该没问题,但是不知道颜色有什么问题:
在cv::Mat 构造函数中使用CV_8UC3 会导致:
原始屏幕截图如下所示:(D3DXSaveSurfaceToFile 的结果)
【问题讨论】:
-
您可以使用 D3DXSaveSurfaceToFileInMemory 将表面保存在内存中
-
@Asesh 谢谢 :) 我能够成功创建
cv::Mat,但现在图像有问题。我在上面制作和编辑。 -
看起来它是后缓冲区而不是前缓冲区。您是否使用了指向 IDirect3DSurface9 的相同指针?如果是,那么您可以检查 D3DXSaveSurfaceToFileInMemory 和 D3DXSaveSurfaceToFile 的结果吗?
-
也就是说,只要将 D3DXSaveSurfaceToFileInMemory 的内容写入一个文件,并将结果与 D3DXSaveSurfaceToFile 的输出进行比较即可。
-
您的 pSurface 的格式是什么?您可以使用 GetDesc 获取它并检查 D3DSURFACE_DESC 结构的 Format 字段。如果不是 d3dformat_x8r8g8b8 则不能直接使用 CV_8UC4/CV_8UC3。
标签: c++ opencv image-processing directx mat