File: laplace_operator.markdown

package info (click to toggle)
opencv 4.6.0%2Bdfsg-12
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 276,172 kB
  • sloc: cpp: 1,079,020; xml: 682,526; python: 43,885; lisp: 30,943; java: 25,642; ansic: 7,968; javascript: 5,956; objc: 2,039; sh: 1,017; cs: 601; perl: 494; makefile: 179
file content (204 lines) | stat: -rw-r--r-- 6,569 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
Laplace Operator {#tutorial_laplace_operator}
================

@tableofcontents

@prev_tutorial{tutorial_sobel_derivatives}
@next_tutorial{tutorial_canny_detector}

|    |    |
| -: | :- |
| Original author | Ana Huamán |
| Compatibility | OpenCV >= 3.0 |

Goal
----

In this tutorial you will learn how to:

-   Use the OpenCV function **Laplacian()** to implement a discrete analog of the *Laplacian
    operator*.

Theory
------

-#  In the previous tutorial we learned how to use the *Sobel Operator*. It was based on the fact
    that in the edge area, the pixel intensity shows a "jump" or a high variation of intensity.
    Getting the first derivative of the intensity, we observed that an edge is characterized by a
    maximum, as it can be seen in the figure:

    ![](images/Laplace_Operator_Tutorial_Theory_Previous.jpg)

-#  And...what happens if we take the second derivative?

    ![](images/Laplace_Operator_Tutorial_Theory_ddIntensity.jpg)

    You can observe that the second derivative is zero! So, we can also use this criterion to
    attempt to detect edges in an image. However, note that zeros will not only appear in edges
    (they can actually appear in other meaningless locations); this can be solved by applying
    filtering where needed.

### Laplacian Operator

-#  From the explanation above, we deduce that the second derivative can be used to *detect edges*.
    Since images are "*2D*", we would need to take the derivative in both dimensions. Here, the
    Laplacian operator comes handy.
-#  The *Laplacian operator* is defined by:

\f[Laplace(f) = \dfrac{\partial^{2} f}{\partial x^{2}} + \dfrac{\partial^{2} f}{\partial y^{2}}\f]

-#  The Laplacian operator is implemented in OpenCV by the function **Laplacian()** . In fact,
    since the Laplacian uses the gradient of images, it calls internally the *Sobel* operator to
    perform its computation.

Code
----

-#  **What does this program do?**
    -   Loads an image
    -   Remove noise by applying a Gaussian blur and then convert the original image to grayscale
    -   Applies a Laplacian operator to the grayscale image and stores the output image
    -   Display the result in a window

@add_toggle_cpp
-#  The tutorial code's is shown lines below. You can also download it from
    [here](https://raw.githubusercontent.com/opencv/opencv/4.x/samples/cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp)
    @include samples/cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp
@end_toggle

@add_toggle_java
-#  The tutorial code's is shown lines below. You can also download it from
    [here](https://raw.githubusercontent.com/opencv/opencv/4.x/samples/java/tutorial_code/ImgTrans/LaPlace/LaplaceDemo.java)
    @include samples/java/tutorial_code/ImgTrans/LaPlace/LaplaceDemo.java
@end_toggle

@add_toggle_python
-#  The tutorial code's is shown lines below. You can also download it from
    [here](https://raw.githubusercontent.com/opencv/opencv/4.x/samples/python/tutorial_code/ImgTrans/LaPlace/laplace_demo.py)
    @include samples/python/tutorial_code/ImgTrans/LaPlace/laplace_demo.py
@end_toggle

Explanation
-----------

#### Declare variables

@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp variables
@end_toggle

@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/LaPlace/LaplaceDemo.java variables
@end_toggle

@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/LaPlace/laplace_demo.py variables
@end_toggle

#### Load source image

@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp load
@end_toggle

@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/LaPlace/LaplaceDemo.java load
@end_toggle

@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/LaPlace/laplace_demo.py load
@end_toggle

#### Reduce noise

@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp reduce_noise
@end_toggle

@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/LaPlace/LaplaceDemo.java reduce_noise
@end_toggle

@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/LaPlace/laplace_demo.py reduce_noise
@end_toggle

#### Grayscale

@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp convert_to_gray
@end_toggle

@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/LaPlace/LaplaceDemo.java convert_to_gray
@end_toggle

@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/LaPlace/laplace_demo.py convert_to_gray
@end_toggle

#### Laplacian operator

@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp laplacian
@end_toggle

@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/LaPlace/LaplaceDemo.java laplacian
@end_toggle

@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/LaPlace/laplace_demo.py laplacian
@end_toggle

-   The arguments are:
    -   *src_gray*: The input image.
    -   *dst*: Destination (output) image
    -   *ddepth*: Depth of the destination image. Since our input is *CV_8U* we define *ddepth* =
        *CV_16S* to avoid overflow
    -   *kernel_size*: The kernel size of the Sobel operator to be applied internally. We use 3 in
        this example.
    -   *scale*, *delta* and *BORDER_DEFAULT*: We leave them as default values.

#### Convert output to a *CV_8U* image

@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp convert
@end_toggle

@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/LaPlace/LaplaceDemo.java convert
@end_toggle

@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/LaPlace/laplace_demo.py convert
@end_toggle

#### Display the result

@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp display
@end_toggle

@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/LaPlace/LaplaceDemo.java display
@end_toggle

@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/LaPlace/laplace_demo.py display
@end_toggle

Results
-------

-#  After compiling the code above, we can run it giving as argument the path to an image. For
    example, using as an input:

    ![](images/Laplace_Operator_Tutorial_Original_Image.jpg)

-#  We obtain the following result. Notice how the trees and the silhouette of the cow are
    approximately well defined (except in areas in which the intensity are very similar, i.e. around
    the cow's head). Also, note that the roof of the house behind the trees (right side) is
    notoriously marked. This is due to the fact that the contrast is higher in that region.

    ![](images/Laplace_Operator_Tutorial_Result.jpg)