2017-07-07 6 views
0

だから、すぐに金属に着く。私はC++プログラムを書いていますが、その目的は画面を入力画像として取り込み、オブジェクト検出器(dlib)で処理することですが、スワップチェーンとコンテキスト/コンテンツへのポインタをどのように取得できるかを理解するのに苦労しています。スクリーン。DirectX Tool Kitのscreengrabによるデスクトップ/スクリーンショットキャプチャは可能ですか?

ScreenGrab (DirectX Tool Kit)の次のコードは、このトリックを行うことができるようです。問題は、私にそれを働かせる方法がわからないことです。 (私は使用していない1と呼ばれるdirectxtk_desktop_2015もある、directxtk_uwpと呼ばれる)私は、ライブラリを取得するにはVisual Studioの2017年にNuGetを使用していると私は、次の6つのエラーを取得しています:

  • エラーC2065 : 'swapChain':宣言されていない識別子
  • エラーC2227: - : 'immContext':宣言されていない識別子
  • エラーC2228:左の左 '> GetBufferは、' ジェネリック型
  • エラーC2065 /クラス/構造体/共用体を指している必要があります'.Get'にはクラス/構造体/共用体が必要です
  • エラーC2653: 'DX':クラスまたは名前空間名ではありません
  • エラーC3861: 'ThrowIfFailed':識別子がのscreengrabのwikiページから挿入されたサンプルコードを実行しているから

が見つかりません:

#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プログラミングから来ています。これは1年前から積極的に開発しています。ですから、わかりやすく理解することができれば幸いです^^

ちょっとわかりました。私は、次のコードで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の答えを見たことがありますが、私は画面のコンテキストとスワップチェーンを取得する方法を知りません。 ありがとうございます。

+0

回避策を使用しているサンプルコードでは、自分で作成したレンダリングターゲットテクスチャのスクリーンショット(直接作成したものや独自のスワップチェーンから取得したもの)を取得しようとしていることを前提としています。これはあなた自身のアプリケーションのために意図されているように動作しますが、デスクトップ全体のスクリーンショットをとることは、DXGI APIの使用を必要とする別の問題です。いくつかのオプションについては、[この記事](https://www.codeproject.com/Articles/5051/Various-methods-for-capturing-the-screen#Capture%20It%20the%20GDI%20way)をご覧ください。 。 –

+0

DirectX Tool Kit [wiki](https://github.com/Microsoft/DirectXTK/wiki)のサンプルコードは、[チュートリアル](https://github.com/Microsoft/DirectXTK)で簡単に見ていると仮定しています/ wiki/Getting-Started)ここで私は[ThrowIfFailed](https://github.com/Microsoft/DirectXTK/wiki/ThrowIfFailed)をカバーしています。 –

+0

ありがとう、チャック!私はあなたがおそらく変数名で見ることができるように、そのページを見つけることができた、私はちょうどそのサイトを覚えていない。 DirectXの動作方法は決してありませんでしたが、それはかなり早い段階であり、今はもっと理解していると思います。しかし、あなたがDirectX11に関するリンクされた質問で言ったように、DirectX9は時代遅れではありませんか?とにかく、あなたの助けが大いにありがとう! – EvilFeline

答えて

0

もうちょっと見た後、偉大なチャックの指導を受けて!私は、スクリーンショットをディスクに保存すると(描画マウスを削除した場合、grabImage関数の最初に8ミリ秒のオーバーヘッドがある場合)、約3.5倍の速さで解決策を見つけました。コードhereが表示されます。ディスクに10枚の画像を保存するミリ秒単位の結果として時間を以下に示します。

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-> 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 

はあなたにもそれを完全に取り除くことができ、それが原因のようですが」空白の "/黒の画像ファイルが最初に表示されます。私にとっては、キャプチャを開始する前に2つの空の画像しかありませんでした。全体のinit関数の後に遅れて、私はオーバーヘッドなしで最初のイメージも取得しています。ありがとうございました。

関連する問題