所以,马上换上金属。我正在编写一个c ++程序,其目的是将屏幕作为输入图像并使用对象检测器(来自dlib)处理它,但是我很难理解如何获得指向swapChain和context / content的指针。屏幕。
来自ScreenGrab (DirectX Tool Kit)的以下代码似乎能够解决问题。问题是我不知道如何让它发挥作用。我在Visual Studio 2017中使用NuGet来获取库(称为directxtk_uwp,还有一个名为directxtk_desktop_2015,我没有使用它。)我得到以下六个错误:
- 错误C2065:'swapChain':未声明的标识符
- 错误C2227:' - > GetBuffer'的左边必须指向class / struct / union / generic type
- 错误C2065:'immContext':未声明的标识符
- 错误C2228:'。Get'的左边必须有class / struct / union
- 错误C2653:'DX':不是类或命名空间名称
- 错误C3861:'ThrowIfFailed':找不到标识符
从ScreenGrab wiki-page:
运行插入的示例代码#include <ScreenGrab.h>
#include <wrl\client.h>
#include <Wincodec.h>
int main() {
using namespace DirectX;
using namespace Microsoft::WRL;
ComPtr<ID3D11Texture2D> backBuffer;
HRESULT hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
reinterpret_cast<LPVOID*>(backBuffer.GetAddressOf()));
if (SUCCEEDED(hr))
{
hr = SaveWICTextureToFile(immContext.Get(), backBuffer.Get(),
GUID_ContainerFormatJpeg, L"SCREENSHOT.JPG");
}
DX::ThrowIfFailed(hr);
return 0;
}
我刚开始用c ++编程,来自Java编程,我已经积极开发了一年。所以保持简单易懂,将不胜感激^^
为了清楚起见,我想要一些相当快的东西。我已经使用以下代码获得了一个使用GDI的screengrab:
#include <iostream>
#include <Windows.h>
#include <Wincodec.h>
#include <ctime>
#include <cstring>
#include <atlimage.h>
#include <d3d9.h>
using namespace std;
int main()
{
try
{
int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
HWND hDesktopWnd = GetDesktopWindow();
HDC hDesktopDC = GetDC(hDesktopWnd);
HDC hCaptureDC = CreateCompatibleDC(hDesktopDC);
for (int i = 0; i < 10;i++) {
clock_t begin = clock();
HBITMAP hCaptureBitmap = CreateCompatibleBitmap(hDesktopDC,
nScreenWidth, nScreenHeight);
SelectObject(hCaptureDC, hCaptureBitmap);
BitBlt(hCaptureDC, 0, 0, nScreenWidth, nScreenHeight,
hDesktopDC, 0, 0, SRCCOPY | CAPTUREBLT);
CImage image;
image.Attach(hCaptureBitmap);
image.Save("test.jpg");
DeleteObject(hCaptureBitmap);
cout << double(clock() - begin) / (clock_t)1000 << endl;
}
ReleaseDC(hDesktopWnd, hDesktopDC);
DeleteDC(hCaptureDC);
IDirect3DSurface9 *surface;
system("pause");
}
catch (exception& e)
{
cout << "\nexception thrown!" << endl;
cout << e.what() << endl;
system("pause");
}
}
导致以下结果:
0.091
0.05
0.052
0.06
0.047
0.05
0.057
0.06
0.06
0.051
正如你所看到的,这实际上只能达到每秒1 /0.47≈21帧。我也看过this回答,但是我再也不知道如何获取屏幕的上下文和swapChain。 谢谢。
答案 0 :(得分:0)
所以经过一段时间的观察并在伟大的查克的指导下!我找到了一个解决方案,将屏幕截图保存到磁盘的速度提高了3.5倍(如果你删除了绘图鼠标,并且在grabImage函数的开头有8毫秒的开销)。您可以看到代码here。以下是将十张图像保存到磁盘的结果时间(以毫秒为单位):
0.015
0.017
0.012
0.021
0.012
0.019
0.012
0.022
0.018
0.015
总结这些和GDI程序中的其他人,我们得到0.578 /0.163≈3.546倍的速度。请记住,我已经替换了这部分:
// Copy image into GDI drawing texture
lImmediateContext->CopyResource(lGDIImage, lAcquiredDesktopImage);
// Draw cursor image into GDI drawing texture
CComPtrCustom<IDXGISurface1> lIDXGISurface1;
hr = lGDIImage->QueryInterface(IID_PPV_ARGS(&lIDXGISurface1));
if (FAILED(hr))
return false;
CURSORINFO lCursorInfo = { 0 };
lCursorInfo.cbSize = sizeof(lCursorInfo);
auto lBoolres = GetCursorInfo(&lCursorInfo);
if (lBoolres == TRUE)
{
if (lCursorInfo.flags == CURSOR_SHOWING)
{
auto lCursorPosition = lCursorInfo.ptScreenPos;
auto lCursorSize = lCursorInfo.cbSize;
HDC lHDC;
lIDXGISurface1->GetDC(FALSE, &lHDC);
DrawIconEx(
lHDC,
lCursorPosition.x,
lCursorPosition.y,
lCursorInfo.hCursor,
0,
0,
0,
0,
DI_NORMAL | DI_DEFAULTSIZE);
lIDXGISurface1->ReleaseDC(nullptr);
}
}
// Copy image into CPU access texture
lImmediateContext->CopyResource(lDestImage, lGDIImage);
使用以下行:
lImmediateContext-&gt; CopyResource(lDestImage,lAcquiredDesktopImage);
因为我不需要光标。事实上,考虑到我将在屏幕上检测事物可能会更糟糕。如前所述,我还从此处重新定位了行Sleep(8); // not sure if required
:
hr = lDevice->CreateTexture2D(&desc, NULL, &lDestImage);
if (FAILED(hr))
return false;
if (lDestImage == nullptr)
return false;
return true;
}
bool grabImage() {
int lTryCount = 4;
do
{
Sleep(8); // not sure if required
到这里,在init函数中:
hr = lDevice->CreateTexture2D(&desc, NULL, &lDestImage);
if (FAILED(hr))
return false;
if (lDestImage == nullptr)
return false;
Sleep(8);
return true;
}
bool grabImage() {
int lTryCount = 4;
do
{
//Sleep(5); // not sure if required
你也可以完全删除它,虽然这似乎在一开始就会导致“空白”/黑色图像文件。对我来说,在它开始捕捉之前只有两张空白图像。在整个init函数之后的延迟,我也得到了第一个图像,没有开销。谢谢。