init - 初始化项目

This commit is contained in:
Lee Nony
2022-05-06 01:58:53 +08:00
commit 90a5cc7cb6
6772 changed files with 2837787 additions and 0 deletions

View File

@@ -0,0 +1,174 @@
Canny Edge Detector {#tutorial_canny_detector}
===================
@tableofcontents
@prev_tutorial{tutorial_laplace_operator}
@next_tutorial{tutorial_hough_lines}
| | |
| -: | :- |
| Original author | Ana Huamán |
| Compatibility | OpenCV >= 3.0 |
Goal
----
In this tutorial you will learn how to:
- Use the OpenCV function @ref cv::Canny to implement the Canny Edge Detector.
Theory
------
The *Canny Edge detector* @cite Canny86 was developed by John F. Canny in 1986. Also known to many as the
*optimal detector*, the Canny algorithm aims to satisfy three main criteria:
- **Low error rate:** Meaning a good detection of only existent edges.
- **Good localization:** The distance between edge pixels detected and real edge pixels have
to be minimized.
- **Minimal response:** Only one detector response per edge.
### Steps
-# Filter out any noise. The Gaussian filter is used for this purpose. An example of a Gaussian
kernel of \f$size = 5\f$ that might be used is shown below:
\f[K = \dfrac{1}{159}\begin{bmatrix}
2 & 4 & 5 & 4 & 2 \\
4 & 9 & 12 & 9 & 4 \\
5 & 12 & 15 & 12 & 5 \\
4 & 9 & 12 & 9 & 4 \\
2 & 4 & 5 & 4 & 2
\end{bmatrix}\f]
-# Find the intensity gradient of the image. For this, we follow a procedure analogous to Sobel:
-# Apply a pair of convolution masks (in \f$x\f$ and \f$y\f$ directions:
\f[G_{x} = \begin{bmatrix}
-1 & 0 & +1 \\
-2 & 0 & +2 \\
-1 & 0 & +1
\end{bmatrix}\f]\f[G_{y} = \begin{bmatrix}
-1 & -2 & -1 \\
0 & 0 & 0 \\
+1 & +2 & +1
\end{bmatrix}\f]
-# Find the gradient strength and direction with:
\f[\begin{array}{l}
G = \sqrt{ G_{x}^{2} + G_{y}^{2} } \\
\theta = \arctan(\dfrac{ G_{y} }{ G_{x} })
\end{array}\f]
The direction is rounded to one of four possible angles (namely 0, 45, 90 or 135)
-# *Non-maximum* suppression is applied. This removes pixels that are not considered to be part of
an edge. Hence, only thin lines (candidate edges) will remain.
-# *Hysteresis*: The final step. Canny does use two thresholds (upper and lower):
-# If a pixel gradient is higher than the *upper* threshold, the pixel is accepted as an edge
-# If a pixel gradient value is below the *lower* threshold, then it is rejected.
-# If the pixel gradient is between the two thresholds, then it will be accepted only if it is
connected to a pixel that is above the *upper* threshold.
Canny recommended a *upper*:*lower* ratio between 2:1 and 3:1.
-# For more details, you can always consult your favorite Computer Vision book.
Code
----
@add_toggle_cpp
- The tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp)
@include samples/cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp
@end_toggle
@add_toggle_java
- The tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/ImgTrans/canny_detector/CannyDetectorDemo.java)
@include samples/java/tutorial_code/ImgTrans/canny_detector/CannyDetectorDemo.java
@end_toggle
@add_toggle_python
- The tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/ImgTrans/canny_detector/CannyDetector_Demo.py)
@include samples/python/tutorial_code/ImgTrans/canny_detector/CannyDetector_Demo.py
@end_toggle
- **What does this program do?**
- Asks the user to enter a numerical value to set the lower threshold for our *Canny Edge
Detector* (by means of a Trackbar).
- Applies the *Canny Detector* and generates a **mask** (bright lines representing the edges
on a black background).
- Applies the mask obtained on the original image and display it in a window.
Explanation (C++ code)
----------------------
-# Create some needed variables:
@snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp variables
Note the following:
-# We establish a ratio of lower:upper threshold of 3:1 (with the variable *ratio*).
-# We set the kernel size of \f$3\f$ (for the Sobel operations to be performed internally by the
Canny function).
-# We set a maximum value for the lower Threshold of \f$100\f$.
-# Loads the source image:
@snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp load
-# Create a matrix of the same type and size of *src* (to be *dst*):
@snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp create_mat
-# Convert the image to grayscale (using the function @ref cv::cvtColor ):
@snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp convert_to_gray
-# Create a window to display the results:
@snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp create_window
-# Create a Trackbar for the user to enter the lower threshold for our Canny detector:
@snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp create_trackbar
Observe the following:
-# The variable to be controlled by the Trackbar is *lowThreshold* with a limit of
*max_lowThreshold* (which we set to 100 previously)
-# Each time the Trackbar registers an action, the callback function *CannyThreshold* will be
invoked.
-# Let's check the *CannyThreshold* function, step by step:
-# First, we blur the image with a filter of kernel size 3:
@snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp reduce_noise
-# Second, we apply the OpenCV function @ref cv::Canny :
@snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp canny
where the arguments are:
- *detected_edges*: Source image, grayscale
- *detected_edges*: Output of the detector (can be the same as the input)
- *lowThreshold*: The value entered by the user moving the Trackbar
- *highThreshold*: Set in the program as three times the lower threshold (following
Canny's recommendation)
- *kernel_size*: We defined it to be 3 (the size of the Sobel kernel to be used
internally)
-# We fill a *dst* image with zeros (meaning the image is completely black).
@snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp fill
-# Finally, we will use the function @ref cv::Mat::copyTo to map only the areas of the image that are
identified as edges (on a black background).
@ref cv::Mat::copyTo copy the *src* image onto *dst*. However, it will only copy the pixels in the
locations where they have non-zero values. Since the output of the Canny detector is the edge
contours on a black background, the resulting *dst* will be black in all the area but the
detected edges.
@snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp copyto
-# We display our result:
@snippet cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp display
Result
------
- After compiling the code above, we can run it giving as argument the path to an image. For
example, using as an input the following image:
![](images/Canny_Detector_Tutorial_Original_Image.jpg)
- Moving the slider, trying different threshold, we obtain the following result:
![](images/Canny_Detector_Tutorial_Result.jpg)
- Notice how the image is superposed to the black background on the edge regions.

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -0,0 +1,243 @@
Adding borders to your images {#tutorial_copyMakeBorder}
=============================
@tableofcontents
@prev_tutorial{tutorial_filter_2d}
@next_tutorial{tutorial_sobel_derivatives}
| | |
| -: | :- |
| Original author | Ana Huamán |
| Compatibility | OpenCV >= 3.0 |
Goal
----
In this tutorial you will learn how to:
- Use the OpenCV function **copyMakeBorder()** to set the borders (extra padding to your
image).
Theory
------
@note The explanation below belongs to the book **Learning OpenCV** by Bradski and Kaehler.
-# In our previous tutorial we learned to use convolution to operate on images. One problem that
naturally arises is how to handle the boundaries. How can we convolve them if the evaluated
points are at the edge of the image?
-# What most of OpenCV functions do is to copy a given image onto another slightly larger image and
then automatically pads the boundary (by any of the methods explained in the sample code just
below). This way, the convolution can be performed over the needed pixels without problems (the
extra padding is cut after the operation is done).
-# In this tutorial, we will briefly explore two ways of defining the extra padding (border) for an
image:
-# **BORDER_CONSTANT**: Pad the image with a constant value (i.e. black or \f$0\f$
-# **BORDER_REPLICATE**: The row or column at the very edge of the original is replicated to
the extra border.
This will be seen more clearly in the Code section.
- **What does this program do?**
- Load an image
- Let the user choose what kind of padding use in the input image. There are two options:
-# *Constant value border*: Applies a padding of a constant value for the whole border.
This value will be updated randomly each 0.5 seconds.
-# *Replicated border*: The border will be replicated from the pixel values at the edges of
the original image.
The user chooses either option by pressing 'c' (constant) or 'r' (replicate)
- The program finishes when the user presses 'ESC'
Code
----
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/copyMakeBorder_demo.cpp)
@include samples/cpp/tutorial_code/ImgTrans/copyMakeBorder_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/MakeBorder/CopyMakeBorder.java)
@include samples/java/tutorial_code/ImgTrans/MakeBorder/CopyMakeBorder.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/MakeBorder/copy_make_border.py)
@include samples/python/tutorial_code/ImgTrans/MakeBorder/copy_make_border.py
@end_toggle
Explanation
-----------
#### Declare the variables
First we declare the variables we are going to use:
@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp variables
@end_toggle
@add_toggle_java
@snippet java/tutorial_code/ImgTrans/MakeBorder/CopyMakeBorder.java variables
@end_toggle
@add_toggle_python
@snippet python/tutorial_code/ImgTrans/MakeBorder/copy_make_border.py variables
@end_toggle
Especial attention deserves the variable *rng* which is a random number generator. We use it to
generate the random border color, as we will see soon.
#### Load an image
As usual we load our source image *src*:
@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp load
@end_toggle
@add_toggle_java
@snippet java/tutorial_code/ImgTrans/MakeBorder/CopyMakeBorder.java load
@end_toggle
@add_toggle_python
@snippet python/tutorial_code/ImgTrans/MakeBorder/copy_make_border.py load
@end_toggle
#### Create a window
After giving a short intro of how to use the program, we create a window:
@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp create_window
@end_toggle
@add_toggle_java
@snippet java/tutorial_code/ImgTrans/MakeBorder/CopyMakeBorder.java create_window
@end_toggle
@add_toggle_python
@snippet python/tutorial_code/ImgTrans/MakeBorder/copy_make_border.py create_window
@end_toggle
#### Initialize arguments
Now we initialize the argument that defines the size of the borders (*top*, *bottom*, *left* and
*right*). We give them a value of 5% the size of *src*.
@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp init_arguments
@end_toggle
@add_toggle_java
@snippet java/tutorial_code/ImgTrans/MakeBorder/CopyMakeBorder.java init_arguments
@end_toggle
@add_toggle_python
@snippet python/tutorial_code/ImgTrans/MakeBorder/copy_make_border.py init_arguments
@end_toggle
#### Loop
The program runs in an infinite loop while the key **ESC** isn't pressed.
If the user presses '**c**' or '**r**', the *borderType* variable
takes the value of *BORDER_CONSTANT* or *BORDER_REPLICATE* respectively:
@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp check_keypress
@end_toggle
@add_toggle_java
@snippet java/tutorial_code/ImgTrans/MakeBorder/CopyMakeBorder.java check_keypress
@end_toggle
@add_toggle_python
@snippet python/tutorial_code/ImgTrans/MakeBorder/copy_make_border.py check_keypress
@end_toggle
#### Random color
In each iteration (after 0.5 seconds), the random border color (*value*) is updated...
@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp update_value
@end_toggle
@add_toggle_java
@snippet java/tutorial_code/ImgTrans/MakeBorder/CopyMakeBorder.java update_value
@end_toggle
@add_toggle_python
@snippet python/tutorial_code/ImgTrans/MakeBorder/copy_make_border.py update_value
@end_toggle
This value is a set of three numbers picked randomly in the range \f$[0,255]\f$.
#### Form a border around the image
Finally, we call the function **copyMakeBorder()** to apply the respective padding:
@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp copymakeborder
@end_toggle
@add_toggle_java
@snippet java/tutorial_code/ImgTrans/MakeBorder/CopyMakeBorder.java copymakeborder
@end_toggle
@add_toggle_python
@snippet python/tutorial_code/ImgTrans/MakeBorder/copy_make_border.py copymakeborder
@end_toggle
- The arguments are:
-# *src*: Source image
-# *dst*: Destination image
-# *top*, *bottom*, *left*, *right*: Length in pixels of the borders at each side of the image.
We define them as being 5% of the original size of the image.
-# *borderType*: Define what type of border is applied. It can be constant or replicate for
this example.
-# *value*: If *borderType* is *BORDER_CONSTANT*, this is the value used to fill the border
pixels.
#### Display the results
We display our output image in the image created previously
@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp display
@end_toggle
@add_toggle_java
@snippet java/tutorial_code/ImgTrans/MakeBorder/CopyMakeBorder.java display
@end_toggle
@add_toggle_python
@snippet python/tutorial_code/ImgTrans/MakeBorder/copy_make_border.py display
@end_toggle
Results
-------
-# After compiling the code above, you can execute it giving as argument the path of an image. The
result should be:
- By default, it begins with the border set to BORDER_CONSTANT. Hence, a succession of random
colored borders will be shown.
- If you press 'r', the border will become a replica of the edge pixels.
- If you press 'c', the random colored borders will appear again
- If you press 'ESC' the program will exit.
Below some screenshot showing how the border changes color and how the *BORDER_REPLICATE*
option looks:
![](images/CopyMakeBorder_Tutorial_Results.jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,177 @@
Image Segmentation with Distance Transform and Watershed Algorithm {#tutorial_distance_transform}
=============
@tableofcontents
@prev_tutorial{tutorial_point_polygon_test}
@next_tutorial{tutorial_out_of_focus_deblur_filter}
| | |
| -: | :- |
| Original author | Theodore Tsesmelis |
| Compatibility | OpenCV >= 3.0 |
Goal
----
In this tutorial you will learn how to:
- Use the OpenCV function @ref cv::filter2D in order to perform some laplacian filtering for image sharpening
- Use the OpenCV function @ref cv::distanceTransform in order to obtain the derived representation of a binary image, where the value of each pixel is replaced by its distance to the nearest background pixel
- Use the OpenCV function @ref cv::watershed in order to isolate objects in the image from the background
Theory
------
Code
----
@add_toggle_cpp
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/imageSegmentation.cpp).
@include samples/cpp/tutorial_code/ImgTrans/imageSegmentation.cpp
@end_toggle
@add_toggle_java
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/ImgTrans/distance_transformation/ImageSegmentationDemo.java)
@include samples/java/tutorial_code/ImgTrans/distance_transformation/ImageSegmentationDemo.java
@end_toggle
@add_toggle_python
This tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/ImgTrans/distance_transformation/imageSegmentation.py)
@include samples/python/tutorial_code/ImgTrans/distance_transformation/imageSegmentation.py
@end_toggle
Explanation / Result
--------------------
- Load the source image and check if it is loaded without any problem, then show it:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/imageSegmentation.cpp load_image
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/distance_transformation/ImageSegmentationDemo.java load_image
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/distance_transformation/imageSegmentation.py load_image
@end_toggle
![](images/source.jpeg)
- Then if we have an image with a white background, it is good to transform it to black. This will help us to discriminate the foreground objects easier when we will apply the Distance Transform:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/imageSegmentation.cpp black_bg
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/distance_transformation/ImageSegmentationDemo.java black_bg
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/distance_transformation/imageSegmentation.py black_bg
@end_toggle
![](images/black_bg.jpeg)
- Afterwards we will sharpen our image in order to acute the edges of the foreground objects. We will apply a laplacian filter with a quite strong filter (an approximation of second derivative):
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/imageSegmentation.cpp sharp
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/distance_transformation/ImageSegmentationDemo.java sharp
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/distance_transformation/imageSegmentation.py sharp
@end_toggle
![](images/laplace.jpeg)
![](images/sharp.jpeg)
- Now we transform our new sharpened source image to a grayscale and a binary one, respectively:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/imageSegmentation.cpp bin
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/distance_transformation/ImageSegmentationDemo.java bin
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/distance_transformation/imageSegmentation.py bin
@end_toggle
![](images/bin.jpeg)
- We are ready now to apply the Distance Transform on the binary image. Moreover, we normalize the output image in order to be able visualize and threshold the result:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/imageSegmentation.cpp dist
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/distance_transformation/ImageSegmentationDemo.java dist
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/distance_transformation/imageSegmentation.py dist
@end_toggle
![](images/dist_transf.jpeg)
- We threshold the *dist* image and then perform some morphology operation (i.e. dilation) in order to extract the peaks from the above image:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/imageSegmentation.cpp peaks
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/distance_transformation/ImageSegmentationDemo.java peaks
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/distance_transformation/imageSegmentation.py peaks
@end_toggle
![](images/peaks.jpeg)
- From each blob then we create a seed/marker for the watershed algorithm with the help of the @ref cv::findContours function:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/imageSegmentation.cpp seeds
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/distance_transformation/ImageSegmentationDemo.java seeds
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/distance_transformation/imageSegmentation.py seeds
@end_toggle
![](images/markers.jpeg)
- Finally, we can apply the watershed algorithm, and visualize the result:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/imageSegmentation.cpp watershed
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/distance_transformation/ImageSegmentationDemo.java watershed
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/distance_transformation/imageSegmentation.py watershed
@end_toggle
![](images/final.jpeg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@@ -0,0 +1,183 @@
Making your own linear filters! {#tutorial_filter_2d}
===============================
@tableofcontents
@prev_tutorial{tutorial_threshold_inRange}
@next_tutorial{tutorial_copyMakeBorder}
| | |
| -: | :- |
| Original author | Ana Huamán |
| Compatibility | OpenCV >= 3.0 |
Goal
----
In this tutorial you will learn how to:
- Use the OpenCV function **filter2D()** to create your own linear filters.
Theory
------
@note The explanation below belongs to the book **Learning OpenCV** by Bradski and Kaehler.
### Correlation
In a very general sense, correlation is an operation between every part of an image and an operator
(kernel).
### What is a kernel?
A kernel is essentially a fixed size array of numerical coefficients along with an *anchor point* in
that array, which is typically located at the center.
![](images/filter_2d_tutorial_kernel_theory.png)
### How does correlation with a kernel work?
Assume you want to know the resulting value of a particular location in the image. The value of the
correlation is calculated in the following way:
-# Place the kernel anchor on top of a determined pixel, with the rest of the kernel overlaying the
corresponding local pixels in the image.
-# Multiply the kernel coefficients by the corresponding image pixel values and sum the result.
-# Place the result to the location of the *anchor* in the input image.
-# Repeat the process for all pixels by scanning the kernel over the entire image.
Expressing the procedure above in the form of an equation we would have:
\f[H(x,y) = \sum_{i=0}^{M_{i} - 1} \sum_{j=0}^{M_{j}-1} I(x+i - a_{i}, y + j - a_{j})K(i,j)\f]
Fortunately, OpenCV provides you with the function **filter2D()** so you do not have to code all
these operations.
### What does this program do?
- Loads an image
- Performs a *normalized box filter*. For instance, for a kernel of size \f$size = 3\f$, the
kernel would be:
\f[K = \dfrac{1}{3 \cdot 3} \begin{bmatrix}
1 & 1 & 1 \\
1 & 1 & 1 \\
1 & 1 & 1
\end{bmatrix}\f]
The program will perform the filter operation with kernels of sizes 3, 5, 7, 9 and 11.
- The filter output (with each kernel) will be shown during 500 milliseconds
Code
----
The tutorial code's is shown in the lines below.
@add_toggle_cpp
You can also download it from
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp)
@include cpp/tutorial_code/ImgTrans/filter2D_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/Filter2D/Filter2D_Demo.java)
@include java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.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/Filter2D/filter2D.py)
@include python/tutorial_code/ImgTrans/Filter2D/filter2D.py
@end_toggle
Explanation
-----------
#### Load an image
@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp load
@end_toggle
@add_toggle_java
@snippet java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java load
@end_toggle
@add_toggle_python
@snippet python/tutorial_code/ImgTrans/Filter2D/filter2D.py load
@end_toggle
#### Initialize the arguments
@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp init_arguments
@end_toggle
@add_toggle_java
@snippet java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java init_arguments
@end_toggle
@add_toggle_python
@snippet python/tutorial_code/ImgTrans/Filter2D/filter2D.py init_arguments
@end_toggle
##### Loop
Perform an infinite loop updating the kernel size and applying our linear filter to the input
image. Let's analyze that more in detail:
- First we define the kernel our filter is going to use. Here it is:
@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp update_kernel
@end_toggle
@add_toggle_java
@snippet java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java update_kernel
@end_toggle
@add_toggle_python
@snippet python/tutorial_code/ImgTrans/Filter2D/filter2D.py update_kernel
@end_toggle
The first line is to update the *kernel_size* to odd values in the range: \f$[3,11]\f$.
The second line actually builds the kernel by setting its value to a matrix filled with
\f$1's\f$ and normalizing it by dividing it between the number of elements.
- After setting the kernel, we can generate the filter by using the function **filter2D()** :
@add_toggle_cpp
@snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp apply_filter
@end_toggle
@add_toggle_java
@snippet java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java apply_filter
@end_toggle
@add_toggle_python
@snippet python/tutorial_code/ImgTrans/Filter2D/filter2D.py apply_filter
@end_toggle
- The arguments denote:
- *src*: Source image
- *dst*: Destination image
- *ddepth*: The depth of *dst*. A negative value (such as \f$-1\f$) indicates that the depth is
the same as the source.
- *kernel*: The kernel to be scanned through the image
- *anchor*: The position of the anchor relative to its kernel. The location *Point(-1, -1)*
indicates the center by default.
- *delta*: A value to be added to each pixel during the correlation. By default it is \f$0\f$
- *BORDER_DEFAULT*: We let this value by default (more details in the following tutorial)
- Our program will effectuate a *while* loop, each 500 ms the kernel size of our filter will be
updated in the range indicated.
Results
-------
-# After compiling the code above, you can execute it giving as argument the path of an image. The
result should be a window that shows an image blurred by a normalized filter. Each 0.5 seconds
the kernel size should change, as can be seen in the series of snapshots below:
![](images/filter_2d_tutorial_result.jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,182 @@
Hough Circle Transform {#tutorial_hough_circle}
======================
@tableofcontents
@prev_tutorial{tutorial_hough_lines}
@next_tutorial{tutorial_remap}
| | |
| -: | :- |
| Original author | Ana Huamán |
| Compatibility | OpenCV >= 3.0 |
Goal
----
In this tutorial you will learn how to:
- Use the OpenCV function **HoughCircles()** to detect circles in an image.
Theory
------
### Hough Circle Transform
- The Hough Circle Transform works in a *roughly* analogous way to the Hough Line Transform
explained in the previous tutorial.
- In the line detection case, a line was defined by two parameters \f$(r, \theta)\f$. In the circle
case, we need three parameters to define a circle:
\f[C : ( x_{center}, y_{center}, r )\f]
where \f$(x_{center}, y_{center})\f$ define the center position (green point) and \f$r\f$ is the radius,
which allows us to completely define a circle, as it can be seen below:
![](images/Hough_Circle_Tutorial_Theory_0.jpg)
- For sake of efficiency, OpenCV implements a detection method slightly trickier than the standard
Hough Transform: *The Hough gradient method*, which is made up of two main stages. The first
stage involves edge detection and finding the possible circle centers and the second stage finds
the best radius for each candidate center. For more details, please check the book *Learning
OpenCV* or your favorite Computer Vision bibliography
#### What does this program do?
- Loads an image and blur it to reduce the noise
- Applies the *Hough Circle Transform* to the blurred image .
- Display the detected circle in a window.
Code
----
@add_toggle_cpp
The sample code that we will explain can be downloaded from
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgTrans/houghcircles.cpp).
A slightly fancier version (which shows trackbars for changing the threshold values) can be found
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgTrans/HoughCircle_Demo.cpp).
@include samples/cpp/tutorial_code/ImgTrans/houghcircles.cpp
@end_toggle
@add_toggle_java
The sample code that we will explain can be downloaded from
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java).
@include samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java
@end_toggle
@add_toggle_python
The sample code that we will explain can be downloaded from
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py).
@include samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py
@end_toggle
Explanation
-----------
The image we used can be found [here](https://raw.githubusercontent.com/opencv/opencv/master/samples/data/smarties.png)
#### Load an image:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/houghcircles.cpp load
@end_toggle
@add_toggle_java
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py load
@end_toggle
@add_toggle_python
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java load
@end_toggle
#### Convert it to grayscale:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/houghcircles.cpp convert_to_gray
@end_toggle
@add_toggle_java
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py convert_to_gray
@end_toggle
@add_toggle_python
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java convert_to_gray
@end_toggle
#### Apply a Median blur to reduce noise and avoid false circle detection:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/houghcircles.cpp reduce_noise
@end_toggle
@add_toggle_java
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py reduce_noise
@end_toggle
@add_toggle_python
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java reduce_noise
@end_toggle
#### Proceed to apply Hough Circle Transform:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/houghcircles.cpp houghcircles
@end_toggle
@add_toggle_java
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py houghcircles
@end_toggle
@add_toggle_python
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java houghcircles
@end_toggle
- with the arguments:
- *gray*: Input image (grayscale).
- *circles*: A vector that stores sets of 3 values: \f$x_{c}, y_{c}, r\f$ for each detected
circle.
- *HOUGH_GRADIENT*: Define the detection method. Currently this is the only one available in
OpenCV.
- *dp = 1*: The inverse ratio of resolution.
- *min_dist = gray.rows/16*: Minimum distance between detected centers.
- *param_1 = 200*: Upper threshold for the internal Canny edge detector.
- *param_2* = 100\*: Threshold for center detection.
- *min_radius = 0*: Minimum radius to be detected. If unknown, put zero as default.
- *max_radius = 0*: Maximum radius to be detected. If unknown, put zero as default.
#### Draw the detected circles:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/houghcircles.cpp draw
@end_toggle
@add_toggle_java
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py draw
@end_toggle
@add_toggle_python
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java draw
@end_toggle
You can see that we will draw the circle(s) on red and the center(s) with a small green dot
#### Display the detected circle(s) and wait for the user to exit the program:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/houghcircles.cpp display
@end_toggle
@add_toggle_java
@snippet samples/python/tutorial_code/ImgTrans/HoughCircle/hough_circle.py display
@end_toggle
@add_toggle_python
@snippet samples/java/tutorial_code/ImgTrans/HoughCircle/HoughCircles.java display
@end_toggle
Result
------
The result of running the code above with a test image is shown below:
![](images/Hough_Circle_Tutorial_Result.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

@@ -0,0 +1,289 @@
Hough Line Transform {#tutorial_hough_lines}
====================
@tableofcontents
@prev_tutorial{tutorial_canny_detector}
@next_tutorial{tutorial_hough_circle}
| | |
| -: | :- |
| Original author | Ana Huamán |
| Compatibility | OpenCV >= 3.0 |
Goal
----
In this tutorial you will learn how to:
- Use the OpenCV functions **HoughLines()** and **HoughLinesP()** to detect lines in an
image.
Theory
------
@note The explanation below belongs to the book **Learning OpenCV** by Bradski and Kaehler.
Hough Line Transform
--------------------
-# The Hough Line Transform is a transform used to detect straight lines.
-# To apply the Transform, first an edge detection pre-processing is desirable.
### How does it work?
-# As you know, a line in the image space can be expressed with two variables. For example:
-# In the **Cartesian coordinate system:** Parameters: \f$(m,b)\f$.
-# In the **Polar coordinate system:** Parameters: \f$(r,\theta)\f$
![](images/Hough_Lines_Tutorial_Theory_0.jpg)
For Hough Transforms, we will express lines in the *Polar system*. Hence, a line equation can be
written as:
\f[y = \left ( -\dfrac{\cos \theta}{\sin \theta} \right ) x + \left ( \dfrac{r}{\sin \theta} \right )\f]
Arranging the terms: \f$r = x \cos \theta + y \sin \theta\f$
-# In general for each point \f$(x_{0}, y_{0})\f$, we can define the family of lines that goes through
that point as:
\f[r_{\theta} = x_{0} \cdot \cos \theta + y_{0} \cdot \sin \theta\f]
Meaning that each pair \f$(r_{\theta},\theta)\f$ represents each line that passes by
\f$(x_{0}, y_{0})\f$.
-# If for a given \f$(x_{0}, y_{0})\f$ we plot the family of lines that goes through it, we get a
sinusoid. For instance, for \f$x_{0} = 8\f$ and \f$y_{0} = 6\f$ we get the following plot (in a plane
\f$\theta\f$ - \f$r\f$):
![](images/Hough_Lines_Tutorial_Theory_1.jpg)
We consider only points such that \f$r > 0\f$ and \f$0< \theta < 2 \pi\f$.
-# We can do the same operation above for all the points in an image. If the curves of two
different points intersect in the plane \f$\theta\f$ - \f$r\f$, that means that both points belong to a
same line. For instance, following with the example above and drawing the plot for two more
points: \f$x_{1} = 4\f$, \f$y_{1} = 9\f$ and \f$x_{2} = 12\f$, \f$y_{2} = 3\f$, we get:
![](images/Hough_Lines_Tutorial_Theory_2.jpg)
The three plots intersect in one single point \f$(0.925, 9.6)\f$, these coordinates are the
parameters (\f$\theta, r\f$) or the line in which \f$(x_{0}, y_{0})\f$, \f$(x_{1}, y_{1})\f$ and
\f$(x_{2}, y_{2})\f$ lay.
-# What does all the stuff above mean? It means that in general, a line can be *detected* by
finding the number of intersections between curves.The more curves intersecting means that the
line represented by that intersection have more points. In general, we can define a *threshold*
of the minimum number of intersections needed to *detect* a line.
-# This is what the Hough Line Transform does. It keeps track of the intersection between curves of
every point in the image. If the number of intersections is above some *threshold*, then it
declares it as a line with the parameters \f$(\theta, r_{\theta})\f$ of the intersection point.
### Standard and Probabilistic Hough Line Transform
OpenCV implements two kind of Hough Line Transforms:
a. **The Standard Hough Transform**
- It consists in pretty much what we just explained in the previous section. It gives you as
result a vector of couples \f$(\theta, r_{\theta})\f$
- In OpenCV it is implemented with the function **HoughLines()**
b. **The Probabilistic Hough Line Transform**
- A more efficient implementation of the Hough Line Transform. It gives as output the extremes
of the detected lines \f$(x_{0}, y_{0}, x_{1}, y_{1})\f$
- In OpenCV it is implemented with the function **HoughLinesP()**
### What does this program do?
- Loads an image
- Applies a *Standard Hough Line Transform* and a *Probabilistic Line Transform*.
- Display the original image and the detected line in three windows.
Code
----
@add_toggle_cpp
The sample code that we will explain can be downloaded from
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgTrans/houghlines.cpp).
A slightly fancier version (which shows both Hough standard and probabilistic
with trackbars for changing the threshold values) can be found
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgTrans/HoughLines_Demo.cpp).
@include samples/cpp/tutorial_code/ImgTrans/houghlines.cpp
@end_toggle
@add_toggle_java
The sample code that we will explain can be downloaded from
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java).
@include samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java
@end_toggle
@add_toggle_python
The sample code that we will explain can be downloaded from
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py).
@include samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py
@end_toggle
Explanation
-----------
#### Load an image:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp load
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java load
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py load
@end_toggle
#### Detect the edges of the image by using a Canny detector:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp edge_detection
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java edge_detection
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py edge_detection
@end_toggle
Now we will apply the Hough Line Transform. We will explain how to use both OpenCV functions
available for this purpose.
#### Standard Hough Line Transform:
First, you apply the Transform:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp hough_lines
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java hough_lines
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py hough_lines
@end_toggle
- with the following arguments:
- *dst*: Output of the edge detector. It should be a grayscale image (although in fact it
is a binary one)
- *lines*: A vector that will store the parameters \f$(r,\theta)\f$ of the detected lines
- *rho* : The resolution of the parameter \f$r\f$ in pixels. We use **1** pixel.
- *theta*: The resolution of the parameter \f$\theta\f$ in radians. We use **1 degree**
(CV_PI/180)
- *threshold*: The minimum number of intersections to "*detect*" a line
- *srn* and *stn*: Default parameters to zero. Check OpenCV reference for more info.
And then you display the result by drawing the lines.
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp draw_lines
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java draw_lines
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py draw_lines
@end_toggle
#### Probabilistic Hough Line Transform
First you apply the transform:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp hough_lines_p
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java hough_lines_p
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py hough_lines_p
@end_toggle
- with the arguments:
- *dst*: Output of the edge detector. It should be a grayscale image (although in fact it
is a binary one)
- *lines*: A vector that will store the parameters
\f$(x_{start}, y_{start}, x_{end}, y_{end})\f$ of the detected lines
- *rho* : The resolution of the parameter \f$r\f$ in pixels. We use **1** pixel.
- *theta*: The resolution of the parameter \f$\theta\f$ in radians. We use **1 degree**
(CV_PI/180)
- *threshold*: The minimum number of intersections to "*detect*" a line
- *minLineLength*: The minimum number of points that can form a line. Lines with less than
this number of points are disregarded.
- *maxLineGap*: The maximum gap between two points to be considered in the same line.
And then you display the result by drawing the lines.
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp draw_lines_p
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java draw_lines_p
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py draw_lines_p
@end_toggle
#### Display the original image and the detected lines:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp imshow
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java imshow
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py imshow
@end_toggle
#### Wait until the user exits the program
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp exit
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java exit
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py exit
@end_toggle
Result
------
@note
The results below are obtained using the slightly fancier version we mentioned in the *Code*
section. It still implements the same stuff as above, only adding the Trackbar for the
Threshold.
Using an input image such as a [sudoku image](https://raw.githubusercontent.com/opencv/opencv/master/samples/data/sudoku.png).
We get the following result by using the Standard Hough Line Transform:
![](images/hough_lines_result1.png)
And by using the Probabilistic Hough Line Transform:
![](images/hough_lines_result2.png)
You may observe that the number of lines detected vary while you change the *threshold*. The
explanation is sort of evident: If you establish a higher threshold, fewer lines will be detected
(since you will need more points to declare a line detected).

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@@ -0,0 +1,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/master/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/master/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/master/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)

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,201 @@
Remapping {#tutorial_remap}
=========
@tableofcontents
@prev_tutorial{tutorial_hough_circle}
@next_tutorial{tutorial_warp_affine}
| | |
| -: | :- |
| Original author | Ana Huamán |
| Compatibility | OpenCV >= 3.0 |
Goal
----
In this tutorial you will learn how to:
a. Use the OpenCV function @ref cv::remap to implement simple remapping routines.
Theory
------
### What is remapping?
- It is the process of taking pixels from one place in the image and locating them in another
position in a new image.
- To accomplish the mapping process, it might be necessary to do some interpolation for
non-integer pixel locations, since there will not always be a one-to-one-pixel correspondence
between source and destination images.
- We can express the remap for every pixel location \f$(x,y)\f$ as:
\f[g(x,y) = f ( h(x,y) )\f]
where \f$g()\f$ is the remapped image, \f$f()\f$ the source image and \f$h(x,y)\f$ is the mapping function
that operates on \f$(x,y)\f$.
- Let's think in a quick example. Imagine that we have an image \f$I\f$ and, say, we want to do a
remap such that:
\f[h(x,y) = (I.cols - x, y )\f]
What would happen? It is easily seen that the image would flip in the \f$x\f$ direction. For
instance, consider the input image:
![](images/Remap_Tutorial_Theory_0.jpg)
observe how the red circle changes positions with respect to x (considering \f$x\f$ the horizontal
direction):
![](images/Remap_Tutorial_Theory_1.jpg)
- In OpenCV, the function @ref cv::remap offers a simple remapping implementation.
Code
----
- **What does this program do?**
- Loads an image
- Each second, apply 1 of 4 different remapping processes to the image and display them
indefinitely in a window.
- Wait for the user to exit the program
@add_toggle_cpp
- The tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/Remap_Demo.cpp)
@include samples/cpp/tutorial_code/ImgTrans/Remap_Demo.cpp
@end_toggle
@add_toggle_java
- The tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/ImgTrans/remap/RemapDemo.java)
@include samples/java/tutorial_code/ImgTrans/remap/RemapDemo.java
@end_toggle
@add_toggle_python
- The tutorial code's is shown lines below. You can also download it from
[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/ImgTrans/remap/Remap_Demo.py)
@include samples/python/tutorial_code/ImgTrans/remap/Remap_Demo.py
@end_toggle
Explanation
-----------
- Load an image:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/Remap_Demo.cpp Load
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/remap/RemapDemo.java Load
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/remap/Remap_Demo.py Load
@end_toggle
- Create the destination image and the two mapping matrices (for x and y )
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/Remap_Demo.cpp Create
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/remap/RemapDemo.java Create
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/remap/Remap_Demo.py Create
@end_toggle
- Create a window to display results
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/Remap_Demo.cpp Window
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/remap/RemapDemo.java Window
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/remap/Remap_Demo.py Window
@end_toggle
- Establish a loop. Each 1000 ms we update our mapping matrices (*mat_x* and *mat_y*) and apply
them to our source image:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/Remap_Demo.cpp Loop
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/remap/RemapDemo.java Loop
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/remap/Remap_Demo.py Loop
@end_toggle
- The function that applies the remapping is @ref cv::remap . We give the following arguments:
- **src**: Source image
- **dst**: Destination image of same size as *src*
- **map_x**: The mapping function in the x direction. It is equivalent to the first component
of \f$h(i,j)\f$
- **map_y**: Same as above, but in y direction. Note that *map_y* and *map_x* are both of
the same size as *src*
- **INTER_LINEAR**: The type of interpolation to use for non-integer pixels. This is by
default.
- **BORDER_CONSTANT**: Default
How do we update our mapping matrices *mat_x* and *mat_y*? Go on reading:
- **Updating the mapping matrices:** We are going to perform 4 different mappings:
-# Reduce the picture to half its size and will display it in the middle:
\f[h(i,j) = ( 2 \times i - src.cols/2 + 0.5, 2 \times j - src.rows/2 + 0.5)\f]
for all pairs \f$(i,j)\f$ such that: \f$\dfrac{src.cols}{4}<i<\dfrac{3 \cdot src.cols}{4}\f$ and
\f$\dfrac{src.rows}{4}<j<\dfrac{3 \cdot src.rows}{4}\f$
-# Turn the image upside down: \f$h( i, j ) = (i, src.rows - j)\f$
-# Reflect the image from left to right: \f$h(i,j) = ( src.cols - i, j )\f$
-# Combination of b and c: \f$h(i,j) = ( src.cols - i, src.rows - j )\f$
This is expressed in the following snippet. Here, *map_x* represents the first coordinate of
*h(i,j)* and *map_y* the second coordinate.
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/Remap_Demo.cpp Update
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/remap/RemapDemo.java Update
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/remap/Remap_Demo.py Update
@end_toggle
Result
------
-# After compiling the code above, you can execute it giving as argument an image path. For
instance, by using the following image:
![](images/Remap_Tutorial_Original_Image.jpg)
-# This is the result of reducing it to half the size and centering it:
![](images/Remap_Tutorial_Result_0.jpg)
-# Turning it upside down:
![](images/Remap_Tutorial_Result_1.jpg)
-# Reflecting it in the x direction:
![](images/Remap_Tutorial_Result_2.jpg)
-# Reflecting it in both directions:
![](images/Remap_Tutorial_Result_3.jpg)

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

View File

@@ -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:
![](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
### 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*:
![](images/Sobel_Derivatives_Tutorial_Result.jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@@ -0,0 +1,285 @@
Affine Transformations {#tutorial_warp_affine}
======================
@tableofcontents
@prev_tutorial{tutorial_remap}
@next_tutorial{tutorial_histogram_equalization}
| | |
| -: | :- |
| Original author | Ana Huamán |
| Compatibility | OpenCV >= 3.0 |
Goal
----
In this tutorial you will learn how to:
- Use the OpenCV function @ref cv::warpAffine to implement simple remapping routines.
- Use the OpenCV function @ref cv::getRotationMatrix2D to obtain a \f$2 \times 3\f$ rotation matrix
Theory
------
### What is an Affine Transformation?
-# A transformation that can be expressed in the form of a *matrix multiplication* (linear
transformation) followed by a *vector addition* (translation).
-# From the above, we can use an Affine Transformation to express:
-# Rotations (linear transformation)
-# Translations (vector addition)
-# Scale operations (linear transformation)
you can see that, in essence, an Affine Transformation represents a **relation** between two
images.
-# The usual way to represent an Affine Transformation is by using a \f$2 \times 3\f$ matrix.
\f[
A = \begin{bmatrix}
a_{00} & a_{01} \\
a_{10} & a_{11}
\end{bmatrix}_{2 \times 2}
B = \begin{bmatrix}
b_{00} \\
b_{10}
\end{bmatrix}_{2 \times 1}
\f]
\f[
M = \begin{bmatrix}
A & B
\end{bmatrix}
=
\begin{bmatrix}
a_{00} & a_{01} & b_{00} \\
a_{10} & a_{11} & b_{10}
\end{bmatrix}_{2 \times 3}
\f]
Considering that we want to transform a 2D vector \f$X = \begin{bmatrix}x \\ y\end{bmatrix}\f$ by
using \f$A\f$ and \f$B\f$, we can do the same with:
\f$T = A \cdot \begin{bmatrix}x \\ y\end{bmatrix} + B\f$ or \f$T = M \cdot [x, y, 1]^{T}\f$
\f[T = \begin{bmatrix}
a_{00}x + a_{01}y + b_{00} \\
a_{10}x + a_{11}y + b_{10}
\end{bmatrix}\f]
### How do we get an Affine Transformation?
-# We mentioned that an Affine Transformation is basically a **relation**
between two images. The information about this relation can come, roughly, in two ways:
-# We know both \f$X\f$ and T and we also know that they are related. Then our task is to find \f$M\f$
-# We know \f$M\f$ and \f$X\f$. To obtain \f$T\f$ we only need to apply \f$T = M \cdot X\f$. Our information
for \f$M\f$ may be explicit (i.e. have the 2-by-3 matrix) or it can come as a geometric relation
between points.
-# Let's explain this in a better way (b). Since \f$M\f$ relates 2 images, we can analyze the simplest
case in which it relates three points in both images. Look at the figure below:
![](images/Warp_Affine_Tutorial_Theory_0.jpg)
the points 1, 2 and 3 (forming a triangle in image 1) are mapped into image 2, still forming a
triangle, but now they have changed notoriously. If we find the Affine Transformation with these
3 points (you can choose them as you like), then we can apply this found relation to all the
pixels in an image.
Code
----
- **What does this program do?**
- Loads an image
- Applies an Affine Transform to the image. This transform is obtained from the relation
between three points. We use the function @ref cv::warpAffine for that purpose.
- Applies a Rotation to the image after being transformed. This rotation is with respect to
the image center
- Waits until the user exits the program
@add_toggle_cpp
- The tutorial's code is shown below. You can also download it
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgProc/Smoothing/Smoothing.cpp)
@include samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp
@end_toggle
@add_toggle_java
- The tutorial's code is shown below. You can also download it
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgProc/Smoothing/Smoothing.cpp)
@include samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java
@end_toggle
@add_toggle_python
- The tutorial's code is shown below. You can also download it
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py)
@include samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py
@end_toggle
Explanation
-----------
- Load an image:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Load the image
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Load the image
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Load the image
@end_toggle
- **Affine Transform:** As we explained in lines above, we need two sets of 3 points to derive the
affine transform relation. Have a look:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Set your 3 points to calculate the Affine Transform
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Set your 3 points to calculate the Affine Transform
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Set your 3 points to calculate the Affine Transform
@end_toggle
You may want to draw these points to get a better idea on how they change. Their locations are
approximately the same as the ones depicted in the example figure (in the Theory section). You
may note that the size and orientation of the triangle defined by the 3 points change.
- Armed with both sets of points, we calculate the Affine Transform by using OpenCV function @ref
cv::getAffineTransform :
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Get the Affine Transform
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Get the Affine Transform
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Get the Affine Transform
@end_toggle
We get a \f$2 \times 3\f$ matrix as an output (in this case **warp_mat**)
- We then apply the Affine Transform just found to the src image
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Apply the Affine Transform just found to the src image
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Apply the Affine Transform just found to the src image
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Apply the Affine Transform just found to the src image
@end_toggle
with the following arguments:
- **src**: Input image
- **warp_dst**: Output image
- **warp_mat**: Affine transform
- **warp_dst.size()**: The desired size of the output image
We just got our first transformed image! We will display it in one bit. Before that, we also
want to rotate it...
- **Rotate:** To rotate an image, we need to know two things:
-# The center with respect to which the image will rotate
-# The angle to be rotated. In OpenCV a positive angle is counter-clockwise
-# *Optional:* A scale factor
We define these parameters with the following snippet:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Compute a rotation matrix with respect to the center of the image
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Compute a rotation matrix with respect to the center of the image
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Compute a rotation matrix with respect to the center of the image
@end_toggle
- We generate the rotation matrix with the OpenCV function @ref cv::getRotationMatrix2D , which
returns a \f$2 \times 3\f$ matrix (in this case *rot_mat*)
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Get the rotation matrix with the specifications above
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Get the rotation matrix with the specifications above
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Get the rotation matrix with the specifications above
@end_toggle
- We now apply the found rotation to the output of our previous Transformation:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Rotate the warped image
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Rotate the warped image
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Rotate the warped image
@end_toggle
- Finally, we display our results in two windows plus the original image for good measure:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Show what you got
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Show what you got
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Show what you got
@end_toggle
- We just have to wait until the user exits the program
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Wait until user exits the program
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Wait until user exits the program
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Wait until user exits the program
@end_toggle
Result
------
- After compiling the code above, we can give it the path of an image as argument. For instance,
for a picture like:
![](images/Warp_Affine_Tutorial_Original_Image.jpg)
after applying the first Affine Transform we obtain:
![](images/Warp_Affine_Tutorial_Result_Warp.jpg)
and finally, after applying a negative rotation (remember negative means clockwise) and a scale
factor, we get:
![](images/Warp_Affine_Tutorial_Result_Warp_Rotate.jpg)