1#include <iostream>
2
3#include "opencv2/imgproc.hpp"
4#include "opencv2/highgui.hpp"
5#include "opencv2/cudafilters.hpp"
6#include "opencv2/cudaimgproc.hpp"
7
8using namespace std;
9using namespace cv;
10
11class App
12{
13public:
14    App(int argc, const char* argv[]);
15
16    int run();
17
18private:
19    void help();
20
21    void OpenClose();
22    void ErodeDilate();
23
24    static void OpenCloseCallback(int, void*);
25    static void ErodeDilateCallback(int, void*);
26
27    cuda::GpuMat src, dst;
28
29    int element_shape;
30
31    int max_iters;
32    int open_close_pos;
33    int erode_dilate_pos;
34};
35
36App::App(int argc, const char* argv[])
37{
38    element_shape = MORPH_RECT;
39    open_close_pos = erode_dilate_pos = max_iters = 10;
40
41    if (argc == 2 && String(argv[1]) == "--help")
42    {
43        help();
44        exit(0);
45    }
46
47    String filename = argc == 2 ? argv[1] : "../data/baboon.jpg";
48
49    Mat img = imread(filename);
50    if (img.empty())
51    {
52        cerr << "Can't open image " << filename.c_str() << endl;
53        exit(-1);
54    }
55
56    src.upload(img);
57    if (src.channels() == 3)
58    {
59        // gpu support only 4th channel images
60        cuda::GpuMat src4ch;
61        cuda::cvtColor(src, src4ch, COLOR_BGR2BGRA);
62        src = src4ch;
63    }
64
65    help();
66
67    cuda::printShortCudaDeviceInfo(cuda::getDevice());
68}
69
70int App::run()
71{
72    // create windows for output images
73    namedWindow("Open/Close");
74    namedWindow("Erode/Dilate");
75
76    createTrackbar("iterations", "Open/Close", &open_close_pos, max_iters * 2 + 1, OpenCloseCallback, this);
77    createTrackbar("iterations", "Erode/Dilate", &erode_dilate_pos, max_iters * 2 + 1, ErodeDilateCallback, this);
78
79    for(;;)
80    {
81        OpenClose();
82        ErodeDilate();
83
84        char c = (char) waitKey();
85
86        switch (c)
87        {
88        case 27:
89            return 0;
90            break;
91
92        case 'e':
93            element_shape = MORPH_ELLIPSE;
94            break;
95
96        case 'r':
97            element_shape = MORPH_RECT;
98            break;
99
100        case 'c':
101            element_shape = MORPH_CROSS;
102            break;
103
104        case ' ':
105            element_shape = (element_shape + 1) % 3;
106            break;
107        }
108    }
109}
110
111void App::help()
112{
113    cout << "Show off image morphology: erosion, dialation, open and close \n";
114    cout << "Call: \n";
115    cout << "   gpu-example-morphology [image] \n";
116    cout << "This program also shows use of rect, ellipse and cross kernels \n" << endl;
117
118    cout << "Hot keys: \n";
119    cout << "\tESC - quit the program \n";
120    cout << "\tr - use rectangle structuring element \n";
121    cout << "\te - use elliptic structuring element \n";
122    cout << "\tc - use cross-shaped structuring element \n";
123    cout << "\tSPACE - loop through all the options \n" << endl;
124}
125
126void App::OpenClose()
127{
128    int n = open_close_pos - max_iters;
129    int an = n > 0 ? n : -n;
130
131    Mat element = getStructuringElement(element_shape, Size(an*2+1, an*2+1), Point(an, an));
132
133    if (n < 0)
134    {
135        Ptr<cuda::Filter> openFilter = cuda::createMorphologyFilter(MORPH_OPEN, src.type(), element);
136        openFilter->apply(src, dst);
137    }
138    else
139    {
140        Ptr<cuda::Filter> closeFilter = cuda::createMorphologyFilter(MORPH_CLOSE, src.type(), element);
141        closeFilter->apply(src, dst);
142    }
143
144    Mat h_dst(dst);
145    imshow("Open/Close", h_dst);
146}
147
148void App::ErodeDilate()
149{
150    int n = erode_dilate_pos - max_iters;
151    int an = n > 0 ? n : -n;
152
153    Mat element = getStructuringElement(element_shape, Size(an*2+1, an*2+1), Point(an, an));
154
155    if (n < 0)
156    {
157        Ptr<cuda::Filter> erodeFilter = cuda::createMorphologyFilter(MORPH_ERODE, src.type(), element);
158        erodeFilter->apply(src, dst);
159    }
160    else
161    {
162        Ptr<cuda::Filter> dilateFilter = cuda::createMorphologyFilter(MORPH_DILATE, src.type(), element);
163        dilateFilter->apply(src, dst);
164    }
165
166    Mat h_dst(dst);
167    imshow("Erode/Dilate", h_dst);
168}
169
170void App::OpenCloseCallback(int, void* data)
171{
172    App* thiz = (App*) data;
173    thiz->OpenClose();
174}
175
176void App::ErodeDilateCallback(int, void* data)
177{
178    App* thiz = (App*) data;
179    thiz->ErodeDilate();
180}
181
182int main(int argc, const char* argv[])
183{
184    App app(argc, argv);
185    return app.run();
186}
187