1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Sample demonstrating interoperability of OpenCV UMat with Direct X surface 3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Base class for Direct X application 4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler*/ 5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <string> 6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <iostream> 7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <queue> 8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/core.hpp" 10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/core/directx.hpp" 11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/core/ocl.hpp" 12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/imgproc.hpp" 13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/videoio.hpp" 14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "winapp.hpp" 16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define SAFE_RELEASE(p) if (p) { p->Release(); p = NULL; } 18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerclass D3DSample : public WinApp 21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerpublic: 23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler enum MODE 24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler MODE_NOP, 26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler MODE_CPU, 27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler MODE_GPU 28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler }; 29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler D3DSample(int width, int height, std::string& window_name, cv::VideoCapture& cap) : 31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler WinApp(width, height, window_name) 32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler m_shutdown = false; 34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler m_mode = MODE_NOP; 35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler m_modeStr[0] = cv::String("No processing"); 36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler m_modeStr[1] = cv::String("Processing on CPU"); 37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler m_modeStr[2] = cv::String("Processing on GPU"); 38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler m_disableProcessing = false; 39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler m_cap = cap; 40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ~D3DSample() {} 43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler virtual int create() { return WinApp::create(); } 45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler virtual int render() = 0; 46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler virtual int cleanup() 47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler m_shutdown = true; 49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return WinApp::cleanup(); 50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 52793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler static float getFps() 53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler static std::queue<int64> time_queue; 55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int64 now = cv::getTickCount(); 57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int64 then = 0; 58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler time_queue.push(now); 59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (time_queue.size() >= 2) 61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler then = time_queue.front(); 62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (time_queue.size() >= 25) 64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler time_queue.pop(); 65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler size_t sz = time_queue.size(); 67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler float fps = sz * (float)cv::getTickFrequency() / (now - then); 69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return fps; 71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerprotected: 74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler virtual LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler switch (message) 77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case WM_CHAR: 79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (wParam >= '0' && wParam <= '2') 80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler m_mode = static_cast<MODE>((char)wParam - '0'); 82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return 0; 83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else if (wParam == VK_SPACE) 85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler m_disableProcessing = !m_disableProcessing; 87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return 0; 88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else if (wParam == VK_ESCAPE) 90793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return cleanup(); 92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case WM_CLOSE: 96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return cleanup(); 97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case WM_DESTROY: 99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ::PostQuitMessage(0); 100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return 0; 101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return ::DefWindowProc(hWnd, message, wParam, lParam); 104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // do render at idle 107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler virtual int idle() { return render(); } 108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerprotected: 110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool m_shutdown; 111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool m_disableProcessing; 112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler MODE m_mode; 113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::String m_modeStr[3]; 114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::VideoCapture m_cap; 115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::Mat m_frame_bgr; 116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::Mat m_frame_rgba; 117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}; 118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void help() 121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler printf( 123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "\nSample demonstrating interoperability of DirectX and OpenCL with OpenCV.\n" 124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "Hot keys: \n" 125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler " 0 - no processing\n" 126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler " 1 - blur DX surface on CPU through OpenCV\n" 127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler " 2 - blur DX surface on GPU through OpenCV using OpenCL\n" 128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler " ESC - exit\n\n"); 129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic const char* keys = 133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "{c camera | true | use camera or not}" 135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "{f file | | movie file name }" 136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "{h help | false | print help info }" 137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}; 138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertemplate <typename TApp> 141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerint d3d_app(int argc, char** argv, std::string& title) 142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::CommandLineParser parser(argc, argv, keys); \ 144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool useCamera = parser.has("camera"); \ 145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler string file = parser.get<string>("file"); \ 146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool showHelp = parser.get<bool>("help"); \ 147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (showHelp) 149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler help(); 150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler parser.printMessage(); 152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::VideoCapture cap; 154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (useCamera) 156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cap.open(0); 157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cap.open(file.c_str()); 159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (!cap.isOpened()) 161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler printf("can not open camera or video file\n"); 163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return -1; 164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int width = (int)cap.get(CAP_PROP_FRAME_WIDTH); 167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int height = (int)cap.get(CAP_PROP_FRAME_HEIGHT); 168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::string wndname = title; 170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler TApp app(width, height, wndname, cap); 172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler try 174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler app.create(); 176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return app.run(); 177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler catch (cv::Exception& e) 180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::cerr << "Exception: " << e.what() << std::endl; 182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return 10; 183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler catch (...) 186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::cerr << "FATAL ERROR: Unknown exception" << std::endl; 188793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return 11; 189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 191