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