1 /**
2  * @file Morphology_3(Extract_Lines).cpp
3  * @brief Use morphology transformations for extracting horizontal and vertical lines sample code
4  * @author OpenCV team
5  */
6 
7 #include <opencv2/core.hpp>
8 #include <opencv2/imgproc.hpp>
9 #include <opencv2/highgui.hpp>
10 #include <iostream>
11 
12 void show_wait_destroy(const char* winname, cv::Mat img);
13 
14 using namespace std;
15 using namespace cv;
16 
main(int argc,char ** argv)17 int main(int argc, char** argv)
18 {
19     //! [load_image]
20     CommandLineParser parser(argc, argv, "{@input | notes.png | input image}");
21     Mat src = imread( samples::findFile( parser.get<String>("@input") ), IMREAD_COLOR);
22     if (src.empty())
23     {
24         cout << "Could not open or find the image!\n" << endl;
25         cout << "Usage: " << argv[0] << " <Input image>" << endl;
26         return -1;
27     }
28 
29     // Show source image
30     imshow("src", src);
31     //! [load_image]
32 
33     //! [gray]
34     // Transform source image to gray if it is not already
35     Mat gray;
36 
37     if (src.channels() == 3)
38     {
39         cvtColor(src, gray, COLOR_BGR2GRAY);
40     }
41     else
42     {
43         gray = src;
44     }
45 
46     // Show gray image
47     show_wait_destroy("gray", gray);
48     //! [gray]
49 
50     //! [bin]
51     // Apply adaptiveThreshold at the bitwise_not of gray, notice the ~ symbol
52     Mat bw;
53     adaptiveThreshold(~gray, bw, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
54 
55     // Show binary image
56     show_wait_destroy("binary", bw);
57     //! [bin]
58 
59     //! [init]
60     // Create the images that will use to extract the horizontal and vertical lines
61     Mat horizontal = bw.clone();
62     Mat vertical = bw.clone();
63     //! [init]
64 
65     //! [horiz]
66     // Specify size on horizontal axis
67     int horizontal_size = horizontal.cols / 30;
68 
69     // Create structure element for extracting horizontal lines through morphology operations
70     Mat horizontalStructure = getStructuringElement(MORPH_RECT, Size(horizontal_size, 1));
71 
72     // Apply morphology operations
73     erode(horizontal, horizontal, horizontalStructure, Point(-1, -1));
74     dilate(horizontal, horizontal, horizontalStructure, Point(-1, -1));
75 
76     // Show extracted horizontal lines
77     show_wait_destroy("horizontal", horizontal);
78     //! [horiz]
79 
80     //! [vert]
81     // Specify size on vertical axis
82     int vertical_size = vertical.rows / 30;
83 
84     // Create structure element for extracting vertical lines through morphology operations
85     Mat verticalStructure = getStructuringElement(MORPH_RECT, Size(1, vertical_size));
86 
87     // Apply morphology operations
88     erode(vertical, vertical, verticalStructure, Point(-1, -1));
89     dilate(vertical, vertical, verticalStructure, Point(-1, -1));
90 
91     // Show extracted vertical lines
92     show_wait_destroy("vertical", vertical);
93     //! [vert]
94 
95     //! [smooth]
96     // Inverse vertical image
97     bitwise_not(vertical, vertical);
98     show_wait_destroy("vertical_bit", vertical);
99 
100     // Extract edges and smooth image according to the logic
101     // 1. extract edges
102     // 2. dilate(edges)
103     // 3. src.copyTo(smooth)
104     // 4. blur smooth img
105     // 5. smooth.copyTo(src, edges)
106 
107     // Step 1
108     Mat edges;
109     adaptiveThreshold(vertical, edges, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 3, -2);
110     show_wait_destroy("edges", edges);
111 
112     // Step 2
113     Mat kernel = Mat::ones(2, 2, CV_8UC1);
114     dilate(edges, edges, kernel);
115     show_wait_destroy("dilate", edges);
116 
117     // Step 3
118     Mat smooth;
119     vertical.copyTo(smooth);
120 
121     // Step 4
122     blur(smooth, smooth, Size(2, 2));
123 
124     // Step 5
125     smooth.copyTo(vertical, edges);
126 
127     // Show final result
128     show_wait_destroy("smooth - final", vertical);
129     //! [smooth]
130 
131     return 0;
132 }
133 
show_wait_destroy(const char * winname,cv::Mat img)134 void show_wait_destroy(const char* winname, cv::Mat img) {
135     imshow(winname, img);
136     moveWindow(winname, 500, 0);
137     waitKey(0);
138     destroyWindow(winname);
139 }
140