1/*
2// Sample demonstrating interoperability of OpenCV UMat with Direct X surface
3// Base class for Direct X application
4*/
5#include <string>
6#include <iostream>
7#include <queue>
8
9#include "opencv2/core.hpp"
10#include "opencv2/core/directx.hpp"
11#include "opencv2/core/ocl.hpp"
12#include "opencv2/imgproc.hpp"
13#include "opencv2/videoio.hpp"
14
15#include "winapp.hpp"
16
17#define SAFE_RELEASE(p) if (p) { p->Release(); p = NULL; }
18
19
20class D3DSample : public WinApp
21{
22public:
23    enum MODE
24    {
25        MODE_NOP,
26        MODE_CPU,
27        MODE_GPU
28    };
29
30    D3DSample(int width, int height, std::string& window_name, cv::VideoCapture& cap) :
31        WinApp(width, height, window_name)
32    {
33        m_shutdown          = false;
34        m_mode              = MODE_NOP;
35        m_modeStr[0]        = cv::String("No processing");
36        m_modeStr[1]        = cv::String("Processing on CPU");
37        m_modeStr[2]        = cv::String("Processing on GPU");
38        m_disableProcessing = false;
39        m_cap               = cap;
40    }
41
42    ~D3DSample() {}
43
44    virtual int create() { return WinApp::create(); }
45    virtual int render() = 0;
46    virtual int cleanup()
47    {
48        m_shutdown = true;
49        return WinApp::cleanup();
50    }
51
52    static float getFps()
53    {
54        static std::queue<int64> time_queue;
55
56        int64 now = cv::getTickCount();
57        int64 then = 0;
58        time_queue.push(now);
59
60        if (time_queue.size() >= 2)
61            then = time_queue.front();
62
63        if (time_queue.size() >= 25)
64            time_queue.pop();
65
66        size_t sz = time_queue.size();
67
68        float fps = sz * (float)cv::getTickFrequency() / (now - then);
69
70        return fps;
71    }
72
73protected:
74    virtual LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
75    {
76        switch (message)
77        {
78        case WM_CHAR:
79            if (wParam >= '0' && wParam <= '2')
80            {
81                m_mode = static_cast<MODE>((char)wParam - '0');
82                return 0;
83            }
84            else if (wParam == VK_SPACE)
85            {
86                m_disableProcessing = !m_disableProcessing;
87                return 0;
88            }
89            else if (wParam == VK_ESCAPE)
90            {
91                return cleanup();
92            }
93            break;
94
95        case WM_CLOSE:
96            return cleanup();
97
98        case WM_DESTROY:
99            ::PostQuitMessage(0);
100            return 0;
101        }
102
103        return ::DefWindowProc(hWnd, message, wParam, lParam);
104    }
105
106    // do render at idle
107    virtual int idle() { return render(); }
108
109protected:
110    bool               m_shutdown;
111    bool               m_disableProcessing;
112    MODE               m_mode;
113    cv::String         m_modeStr[3];
114    cv::VideoCapture   m_cap;
115    cv::Mat            m_frame_bgr;
116    cv::Mat            m_frame_rgba;
117};
118
119
120static void help()
121{
122    printf(
123        "\nSample demonstrating interoperability of DirectX and OpenCL with OpenCV.\n"
124        "Hot keys: \n"
125        "    0 - no processing\n"
126        "    1 - blur DX surface on CPU through OpenCV\n"
127        "    2 - blur DX surface on GPU through OpenCV using OpenCL\n"
128        "  ESC - exit\n\n");
129}
130
131
132static const char* keys =
133{
134    "{c camera | true  | use camera or not}"
135    "{f file   |       | movie file name  }"
136    "{h help   | false | print help info  }"
137};
138
139
140template <typename TApp>
141int d3d_app(int argc, char** argv, std::string& title)
142{
143    cv::CommandLineParser parser(argc, argv, keys); \
144    bool   useCamera = parser.has("camera"); \
145    string file      = parser.get<string>("file"); \
146    bool   showHelp  = parser.get<bool>("help"); \
147
148    if (showHelp)
149        help();
150
151    parser.printMessage();
152
153    cv::VideoCapture cap;
154
155    if (useCamera)
156        cap.open(0);
157    else
158        cap.open(file.c_str());
159
160    if (!cap.isOpened())
161    {
162        printf("can not open camera or video file\n");
163        return -1;
164    }
165
166    int width  = (int)cap.get(CAP_PROP_FRAME_WIDTH);
167    int height = (int)cap.get(CAP_PROP_FRAME_HEIGHT);
168
169    std::string wndname = title;
170
171    TApp app(width, height, wndname, cap);
172
173    try
174    {
175        app.create();
176        return app.run();
177    }
178
179    catch (cv::Exception& e)
180    {
181        std::cerr << "Exception: " << e.what() << std::endl;
182        return 10;
183    }
184
185    catch (...)
186    {
187        std::cerr << "FATAL ERROR: Unknown exception" << std::endl;
188        return 11;
189    }
190}
191