@prev_tutorial{tutorial_copyMakeBorder} @next_tutorial{tutorial_laplace_operator}
| | | | -: | :- | | Original author | Ana Huamán | | Compatibility | OpenCV >= 3.0 |
In this tutorial you will learn how to:
@note The explanation below belongs to the book Learning OpenCV by Bradski and Kaehler.
-# In the last two tutorials we have seen applicative examples of convolutions. One of the most
important convolutions is the computation of derivatives in an image (or an approximation to
them).
-# Why may be important the calculus of the derivatives in an image? Let's imagine we want to
detect the *edges* present in the image. For instance:
![](images/Sobel_Derivatives_Tutorial_Theory_0.jpg)
You can easily notice that in an *edge*, the pixel intensity *changes* in a notorious way. A
good way to express *changes* is by using *derivatives*. A high change in gradient indicates a
major change in the image.
-# To be more graphical, let's assume we have a 1D-image. An edge is shown by the "jump" in
intensity in the plot below:
![](images/Sobel_Derivatives_Tutorial_Theory_Intensity_Function.jpg)
-# The edge "jump" can be seen more easily if we take the first derivative (actually, here appears
as a maximum)
![](images/Sobel_Derivatives_Tutorial_Theory_dIntensity_Function.jpg)
-# So, from the explanation above, we can deduce that a method to detect edges in an image can be
performed by locating pixel locations where the gradient is higher than its neighbors (or to
generalize, higher than a threshold).
-# More detailed explanation, please refer to Learning OpenCV by Bradski and Kaehler
-# The Sobel Operator is a discrete differentiation operator. It computes an approximation of the
gradient of an image intensity function.
-# The Sobel Operator combines Gaussian smoothing and differentiation.
Assuming that the image to be operated is \f$I\f$:
-# We calculate two derivatives:
-# **Horizontal changes**: This is computed by convolving \f$I\f$ with a kernel \f$G_{x}\f$ with odd
size. For example for a kernel size of 3, \f$G_{x}\f$ would be computed as:
\f[G_{x} = \begin{bmatrix}
-1 & 0 & +1 \\
-2 & 0 & +2 \\
-1 & 0 & +1
\end{bmatrix} * I\f]
-# **Vertical changes**: This is computed by convolving \f$I\f$ with a kernel \f$G_{y}\f$ with odd
size. For example for a kernel size of 3, \f$G_{y}\f$ would be computed as:
\f[G_{y} = \begin{bmatrix}
-1 & -2 & -1 \\
0 & 0 & 0 \\
+1 & +2 & +1
\end{bmatrix} * I\f]
-# At each point of the image we calculate an approximation of the gradient in that point by
combining both results above:
\f[G = \sqrt{ G_{x}^{2} + G_{y}^{2} }\f]
Although sometimes the following simpler equation is used:
\f[G = |G_{x}| + |G_{y}|\f]
When the size of the kernel is `3`, the Sobel kernel shown above may produce noticeable
inaccuracies (after all, Sobel is only an approximation of the derivative). OpenCV addresses
this inaccuracy for kernels of size 3 by using the **Scharr()** function. This is as fast
but more accurate than the standard Sobel function. It implements the following kernels:
\f[G_{x} = \begin{bmatrix}
-3 & 0 & +3 \\
-10 & 0 & +10 \\
-3 & 0 & +3
\end{bmatrix}\f]\f[G_{y} = \begin{bmatrix}
-3 & -10 & -3 \\
0 & 0 & 0 \\
+3 & +10 & +3
\end{bmatrix}\f]
You can check out more information of this function in the OpenCV reference - **Scharr()** .
Also, in the sample code below, you will notice that above the code for **Sobel()** function
there is also code for the **Scharr()** function commented. Uncommenting it (and obviously
commenting the Sobel stuff) should give you an idea of how this function works.
-# What does this program do?
- Applies the *Sobel Operator* and generates as output an image with the detected *edges*
bright on a darker background.
-# The tutorial code's is shown lines below.
@add_toggle_cpp You can also download it from here @include samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp @end_toggle
@add_toggle_java You can also download it from here @include samples/java/tutorial_code/ImgTrans/SobelDemo/SobelDemo.java @end_toggle
@add_toggle_python You can also download it from here @include samples/python/tutorial_code/ImgTrans/SobelDemo/sobel_demo.py @end_toggle
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp variables
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp load
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp reduce_noise
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp convert_to_gray
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp sobel
We calculate the "derivatives" in x and y directions. For this, we use the function Sobel() as shown below: The function takes the following arguments:
Notice that to calculate the gradient in x direction we use: \f$x{order}= 1\f$ and \f$y{order} = 0\f$. We do analogously for the y direction.
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp convert
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp blend
We try to approximate the gradient by adding both directional gradients (note that this is not an exact calculation at all! but it is good for our purposes).
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp display
-# Here is the output of applying our basic detector to lena.jpg:
![](images/Sobel_Derivatives_Tutorial_Result.jpg)