text: #include <iostream>
  
  #include "opencv2/imgproc.hpp"
  #include "opencv2/highgui.hpp"
  #include "opencv2/cudafilters.hpp"
  #include "opencv2/cudaimgproc.hpp"
  
  using namespace std;
  using namespace cv;
  
  class App
  {
  public:
      App(int argc, const char* argv[]);
  
      int run();
  
  private:
      void help();
  
      void OpenClose();
      void ErodeDilate();
  
      static void OpenCloseCallback(int, void*);
      static void ErodeDilateCallback(int, void*);
  
      cuda::GpuMat src, dst;
  
      int element_shape;
  
      int max_iters;
      int open_close_pos;
      int erode_dilate_pos;
  };
  
  App::App(int argc, const char* argv[])
  {
      element_shape = MORPH_RECT;
      open_close_pos = erode_dilate_pos = max_iters = 10;
  
      if (argc == 2 && String(argv[1]) == "--help")
      {
          help();
          exit(0);
      }
  
      String filename = argc == 2 ? argv[1] : "../data/baboon.jpg";
  
      Mat img = imread(filename);
      if (img.empty())
      {
          cerr << "Can't open image " << filename.c_str() << endl;
          exit(-1);
      }
  
      src.upload(img);
      if (src.channels() == 3)
      {
          // gpu support only 4th channel images
          cuda::GpuMat src4ch;
          cuda::cvtColor(src, src4ch, COLOR_BGR2BGRA);
          src = src4ch;
      }
  
      help();
  
      cuda::printShortCudaDeviceInfo(cuda::getDevice());
  }
  
  int App::run()
  {
      // create windows for output images
      namedWindow("Open/Close");
      namedWindow("Erode/Dilate");
  
      createTrackbar("iterations", "Open/Close", &open_close_pos, max_iters * 2 + 1, OpenCloseCallback, this);
      createTrackbar("iterations", "Erode/Dilate", &erode_dilate_pos, max_iters * 2 + 1, ErodeDilateCallback, this);
  
      for(;;)
      {
          OpenClose();
          ErodeDilate();
  
          char c = (char) waitKey();
  
          switch (c)
          {
          case 27:
              return 0;
              break;
  
          case 'e':
              element_shape = MORPH_ELLIPSE;
              break;
  
          case 'r':
              element_shape = MORPH_RECT;
              break;
  
          case 'c':
              element_shape = MORPH_CROSS;
              break;
  
          case ' ':
              element_shape = (element_shape + 1) % 3;
              break;
          }
      }
  }
  
  void App::help()
  {
      cout << "Show off image morphology: erosion, dialation, open and close \n";
      cout << "Call: \n";
      cout << "   gpu-example-morphology [image] \n";
      cout << "This program also shows use of rect, ellipse and cross kernels \n" << endl;
  
      cout << "Hot keys: \n";
      cout << "\tESC - quit the program \n";
      cout << "\tr - use rectangle structuring element \n";
      cout << "\te - use elliptic structuring element \n";
      cout << "\tc - use cross-shaped structuring element \n";
      cout << "\tSPACE - loop through all the options \n" << endl;
  }
  
  void App::OpenClose()
  {
      int n = open_close_pos - max_iters;
      int an = n > 0 ? n : -n;
  
      Mat element = getStructuringElement(element_shape, Size(an*2+1, an*2+1), Point(an, an));
  
      if (n < 0)
      {
          Ptr<cuda::Filter> openFilter = cuda::createMorphologyFilter(MORPH_OPEN, src.type(), element);
          openFilter->apply(src, dst);
      }
      else
      {
          Ptr<cuda::Filter> closeFilter = cuda::createMorphologyFilter(MORPH_CLOSE, src.type(), element);
          closeFilter->apply(src, dst);
      }
  
      Mat h_dst(dst);
      imshow("Open/Close", h_dst);
  }
  
  void App::ErodeDilate()
  {
      int n = erode_dilate_pos - max_iters;
      int an = n > 0 ? n : -n;
  
      Mat element = getStructuringElement(element_shape, Size(an*2+1, an*2+1), Point(an, an));
  
      if (n < 0)
      {
          Ptr<cuda::Filter> erodeFilter = cuda::createMorphologyFilter(MORPH_ERODE, src.type(), element);
          erodeFilter->apply(src, dst);
      }
      else
      {
          Ptr<cuda::Filter> dilateFilter = cuda::createMorphologyFilter(MORPH_DILATE, src.type(), element);
          dilateFilter->apply(src, dst);
      }
  
      Mat h_dst(dst);
      imshow("Erode/Dilate", h_dst);
  }
  
  void App::OpenCloseCallback(int, void* data)
  {
      App* thiz = (App*) data;
      thiz->OpenClose();
  }
  
  void App::ErodeDilateCallback(int, void* data)
  {
      App* thiz = (App*) data;
      thiz->ErodeDilate();
  }
  
  int main(int argc, const char* argv[])
  {
      App app(argc, argv);
      return app.run();
  }
  