init - 初始化项目
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.4 KiB |
@@ -0,0 +1,197 @@
|
||||
Sobel Derivatives {#tutorial_sobel_derivatives}
|
||||
=================
|
||||
|
||||
@tableofcontents
|
||||
|
||||
@prev_tutorial{tutorial_copyMakeBorder}
|
||||
@next_tutorial{tutorial_laplace_operator}
|
||||
|
||||
| | |
|
||||
| -: | :- |
|
||||
| Original author | Ana Huamán |
|
||||
| Compatibility | OpenCV >= 3.0 |
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
- Use the OpenCV function **Sobel()** to calculate the derivatives from an image.
|
||||
- Use the OpenCV function **Scharr()** to calculate a more accurate derivative for a kernel of
|
||||
size \f$3 \cdot 3\f$
|
||||
|
||||
Theory
|
||||
------
|
||||
|
||||
@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:
|
||||
|
||||

|
||||
|
||||
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:
|
||||
|
||||

|
||||
|
||||
-# The edge "jump" can be seen more easily if we take the first derivative (actually, here appears
|
||||
as a maximum)
|
||||
|
||||

|
||||
|
||||
-# 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
|
||||
|
||||
### Sobel Operator
|
||||
|
||||
-# 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.
|
||||
|
||||
#### Formulation
|
||||
|
||||
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]
|
||||
|
||||
@note
|
||||
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]
|
||||
@note
|
||||
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.
|
||||
|
||||
Code
|
||||
----
|
||||
|
||||
-# **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](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp)
|
||||
@include samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
You can also download it from
|
||||
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/java/tutorial_code/ImgTrans/SobelDemo/SobelDemo.java)
|
||||
@include samples/java/tutorial_code/ImgTrans/SobelDemo/SobelDemo.java
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
You can also download it from
|
||||
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/python/tutorial_code/ImgTrans/SobelDemo/sobel_demo.py)
|
||||
@include samples/python/tutorial_code/ImgTrans/SobelDemo/sobel_demo.py
|
||||
@end_toggle
|
||||
|
||||
Explanation
|
||||
-----------
|
||||
|
||||
#### Declare variables
|
||||
|
||||
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp variables
|
||||
|
||||
#### Load source image
|
||||
|
||||
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp load
|
||||
|
||||
#### Reduce noise
|
||||
|
||||
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp reduce_noise
|
||||
|
||||
#### Grayscale
|
||||
|
||||
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp convert_to_gray
|
||||
|
||||
#### Sobel Operator
|
||||
|
||||
@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:
|
||||
|
||||
- *src_gray*: In our example, the input image. Here it is *CV_8U*
|
||||
- *grad_x* / *grad_y* : The output image.
|
||||
- *ddepth*: The depth of the output image. We set it to *CV_16S* to avoid overflow.
|
||||
- *x_order*: The order of the derivative in **x** direction.
|
||||
- *y_order*: The order of the derivative in **y** direction.
|
||||
- *scale*, *delta* and *BORDER_DEFAULT*: We use default values.
|
||||
|
||||
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.
|
||||
|
||||
#### Convert output to a CV_8U image
|
||||
|
||||
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp convert
|
||||
|
||||
#### Gradient
|
||||
|
||||
@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).
|
||||
|
||||
#### Show results
|
||||
|
||||
@snippet cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp display
|
||||
|
||||
Results
|
||||
-------
|
||||
|
||||
-# Here is the output of applying our basic detector to *lena.jpg*:
|
||||
|
||||

|
||||
Reference in New Issue
Block a user