Skip to content

Commit d068e27

Browse files
committed
Tutorial Morph Lines Detection
1 parent 18bc4db commit d068e27

File tree

6 files changed

+527
-119
lines changed

6 files changed

+527
-119
lines changed

doc/tutorials/imgproc/morph_lines_detection/moprh_lines_detection.md

Lines changed: 0 additions & 86 deletions
This file was deleted.
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
Extract horizontal and vertical lines by using morphological operations {#tutorial_morph_lines_detection}
2+
=============
3+
4+
@prev_tutorial{tutorial_hitOrMiss}
5+
@next_tutorial{tutorial_pyramids}
6+
7+
Goal
8+
----
9+
10+
In this tutorial you will learn how to:
11+
12+
- Apply two very common morphology operators (i.e. Dilation and Erosion), with the creation of custom kernels, in order to extract straight lines on the horizontal and vertical axes. For this purpose, you will use the following OpenCV functions:
13+
- **erode()**
14+
- **dilate()**
15+
- **getStructuringElement()**
16+
17+
in an example where your goal will be to extract the music notes from a music sheet.
18+
19+
Theory
20+
------
21+
22+
### Morphology Operations
23+
Morphology is a set of image processing operations that process images based on predefined *structuring elements* known also as kernels. The value of each pixel in the output image is based on a comparison of the corresponding pixel in the input image with its neighbors. By choosing the size and shape of the kernel, you can construct a morphological operation that is sensitive to specific shapes regarding the input image.
24+
25+
Two of the most basic morphological operations are dilation and erosion. Dilation adds pixels to the boundaries of the object in an image, while erosion does exactly the opposite. The amount of pixels added or removed, respectively depends on the size and shape of the structuring element used to process the image. In general the rules followed from these two operations have as follows:
26+
27+
- __Dilation__: The value of the output pixel is the <b><em>maximum</em></b> value of all the pixels that fall within the structuring element's size and shape. For example in a binary image, if any of the pixels of the input image falling within the range of the kernel is set to the value 1, the corresponding pixel of the output image will be set to 1 as well. The latter applies to any type of image (e.g. grayscale, bgr, etc).
28+
29+
![Dilation on a Binary Image](images/morph21.gif)
30+
31+
![Dilation on a Grayscale Image](images/morph6.gif)
32+
33+
- __Erosion__: The vise versa applies for the erosion operation. The value of the output pixel is the <b><em>minimum</em></b> value of all the pixels that fall within the structuring element's size and shape. Look the at the example figures below:
34+
35+
![Erosion on a Binary Image](images/morph211.png)
36+
37+
![Erosion on a Grayscale Image](images/morph61.png)
38+
39+
### Structuring Elements
40+
41+
As it can be seen above and in general in any morphological operation the structuring element used to probe the input image, is the most important part.
42+
43+
A structuring element is a matrix consisting of only 0's and 1's that can have any arbitrary shape and size. Typically are much smaller than the image being processed, while the pixels with values of 1 define the neighborhood. The center pixel of the structuring element, called the origin, identifies the pixel of interest -- the pixel being processed.
44+
45+
For example, the following illustrates a diamond-shaped structuring element of 7x7 size.
46+
47+
![A Diamond-Shaped Structuring Element and its Origin](images/morph12.gif)
48+
49+
A structuring element can have many common shapes, such as lines, diamonds, disks, periodic lines, and circles and sizes. You typically choose a structuring element the same size and shape as the objects you want to process/extract in the input image. For example, to find lines in an image, create a linear structuring element as you will see later.
50+
51+
Code
52+
----
53+
54+
This tutorial code's is shown lines below.
55+
56+
@add_toggle_cpp
57+
You can also download it from [here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.cpp).
58+
@include samples/cpp/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.cpp
59+
@end_toggle
60+
61+
@add_toggle_java
62+
You can also download it from [here](https://raw.githubusercontent.com/opencv/opencv/master/samples/java/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.java).
63+
@include samples/java/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.java
64+
@end_toggle
65+
66+
@add_toggle_python
67+
You can also download it from [here](https://raw.githubusercontent.com/opencv/opencv/master/samples/python/tutorial_code/imgProc/morph_lines_detection/morph_lines_detection.py).
68+
@include samples/python/tutorial_code/imgProc/morph_lines_detection/morph_lines_detection.py
69+
@end_toggle
70+
71+
Explanation / Result
72+
--------------------
73+
74+
Get image from [here](https://raw.githubusercontent.com/opencv/opencv/master/doc/tutorials/imgproc/morph_lines_detection/images/src.png) .
75+
76+
#### Load Image
77+
78+
@add_toggle_cpp
79+
@snippet samples/cpp/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.cpp load_image
80+
@end_toggle
81+
82+
@add_toggle_java
83+
@snippet samples/java/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.java load_image
84+
@end_toggle
85+
86+
@add_toggle_python
87+
@snippet samples/python/tutorial_code/imgProc/morph_lines_detection/morph_lines_detection.py load_image
88+
@end_toggle
89+
90+
![](images/src.png)
91+
92+
#### Grayscale
93+
94+
@add_toggle_cpp
95+
@snippet samples/cpp/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.cpp gray
96+
@end_toggle
97+
98+
@add_toggle_java
99+
@snippet samples/java/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.java gray
100+
@end_toggle
101+
102+
@add_toggle_python
103+
@snippet samples/python/tutorial_code/imgProc/morph_lines_detection/morph_lines_detection.py gray
104+
@end_toggle
105+
106+
![](images/gray.png)
107+
108+
#### Grayscale to Binary image
109+
110+
@add_toggle_cpp
111+
@snippet samples/cpp/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.cpp bin
112+
@end_toggle
113+
114+
@add_toggle_java
115+
@snippet samples/java/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.java bin
116+
@end_toggle
117+
118+
@add_toggle_python
119+
@snippet samples/python/tutorial_code/imgProc/morph_lines_detection/morph_lines_detection.py bin
120+
@end_toggle
121+
122+
![](images/binary.png)
123+
124+
#### Output images
125+
126+
Now we are ready to apply morphological operations in order to extract the horizontal and vertical lines and as a consequence to separate the the music notes from the music sheet, but first let's initialize the output images that we will use for that reason:
127+
128+
@add_toggle_cpp
129+
@snippet samples/cpp/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.cpp init
130+
@end_toggle
131+
132+
@add_toggle_java
133+
@snippet samples/java/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.java init
134+
@end_toggle
135+
136+
@add_toggle_python
137+
@snippet samples/python/tutorial_code/imgProc/morph_lines_detection/morph_lines_detection.py init
138+
@end_toggle
139+
140+
#### Structure elements
141+
142+
As we specified in the theory in order to extract the object that we desire, we need to create the corresponding structure element. Since we want to extract the horizontal lines, a corresponding structure element for that purpose will have the following shape:
143+
![](images/linear_horiz.png)
144+
and in the source code this is represented by the following code snippet:
145+
146+
@add_toggle_cpp
147+
@snippet samples/cpp/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.cpp horiz
148+
@end_toggle
149+
150+
@add_toggle_java
151+
@snippet samples/java/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.java horiz
152+
@end_toggle
153+
154+
@add_toggle_python
155+
@snippet samples/python/tutorial_code/imgProc/morph_lines_detection/morph_lines_detection.py horiz
156+
@end_toggle
157+
158+
![](images/horiz.png)
159+
160+
The same applies for the vertical lines, with the corresponding structure element:
161+
![](images/linear_vert.png)
162+
and again this is represented as follows:
163+
164+
@add_toggle_cpp
165+
@snippet samples/cpp/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.cpp vert
166+
@end_toggle
167+
168+
@add_toggle_java
169+
@snippet samples/java/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.java vert
170+
@end_toggle
171+
172+
@add_toggle_python
173+
@snippet samples/python/tutorial_code/imgProc/morph_lines_detection/morph_lines_detection.py vert
174+
@end_toggle
175+
176+
![](images/vert.png)
177+
178+
#### Refine edges / Result
179+
180+
As you can see we are almost there. However, at that point you will notice that the edges of the notes are a bit rough. For that reason we need to refine the edges in order to obtain a smoother result:
181+
182+
@add_toggle_cpp
183+
@snippet samples/cpp/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.cpp smooth
184+
@end_toggle
185+
186+
@add_toggle_java
187+
@snippet samples/java/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.java smooth
188+
@end_toggle
189+
190+
@add_toggle_python
191+
@snippet samples/python/tutorial_code/imgProc/morph_lines_detection/morph_lines_detection.py smooth
192+
@end_toggle
193+
194+
![](images/smooth.png)

doc/tutorials/imgproc/table_of_content_imgproc.markdown

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ In this section you will learn about the image processing (manipulation) functio
3939

4040
Learn how to find patterns in binary images using the Hit-or-Miss operation
4141

42-
- @subpage tutorial_moprh_lines_detection
42+
- @subpage tutorial_morph_lines_detection
43+
44+
*Languages:* C++, Java, Python
4345

4446
*Compatibility:* \> OpenCV 2.0
4547

0 commit comments

Comments
 (0)