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,296 @@
Back Projection {#tutorial_back_projection}
===============
@tableofcontents
@prev_tutorial{tutorial_histogram_comparison}
@next_tutorial{tutorial_template_matching}
| | |
| -: | :- |
| Original author | Ana Huamán |
| Compatibility | OpenCV >= 3.0 |
Goal
----
In this tutorial you will learn:
- What is Back Projection and why it is useful
- How to use the OpenCV function @ref cv::calcBackProject to calculate Back Projection
- How to mix different channels of an image by using the OpenCV function @ref cv::mixChannels
Theory
------
### What is Back Projection?
- Back Projection is a way of recording how well the pixels of a given image fit the distribution
of pixels in a histogram model.
- To make it simpler: For Back Projection, you calculate the histogram model of a feature and then
use it to find this feature in an image.
- Application example: If you have a histogram of flesh color (say, a Hue-Saturation histogram ),
then you can use it to find flesh color areas in an image:
### How does it work?
- We explain this by using the skin example:
- Let's say you have gotten a skin histogram (Hue-Saturation) based on the image below. The
histogram besides is going to be our *model histogram* (which we know represents a sample of
skin tonality). You applied some mask to capture only the histogram of the skin area:
![T0](images/Back_Projection_Theory0.jpg)
![T1](images/Back_Projection_Theory1.jpg)
- Now, let's imagine that you get another hand image (Test Image) like the one below: (with its
respective histogram):
![T2](images/Back_Projection_Theory2.jpg)
![T3](images/Back_Projection_Theory3.jpg)
- What we want to do is to use our *model histogram* (that we know represents a skin tonality) to
detect skin areas in our Test Image. Here are the steps
-# In each pixel of our Test Image (i.e. \f$p(i,j)\f$ ), collect the data and find the
correspondent bin location for that pixel (i.e. \f$( h_{i,j}, s_{i,j} )\f$ ).
-# Lookup the *model histogram* in the correspondent bin - \f$( h_{i,j}, s_{i,j} )\f$ - and read
the bin value.
-# Store this bin value in a new image (*BackProjection*). Also, you may consider to normalize
the *model histogram* first, so the output for the Test Image can be visible for you.
-# Applying the steps above, we get the following BackProjection image for our Test Image:
![](images/Back_Projection_Theory4.jpg)
-# In terms of statistics, the values stored in *BackProjection* represent the *probability*
that a pixel in *Test Image* belongs to a skin area, based on the *model histogram* that we
use. For instance in our Test image, the brighter areas are more probable to be skin area
(as they actually are), whereas the darker areas have less probability (notice that these
"dark" areas belong to surfaces that have some shadow on it, which in turns affects the
detection).
Code
----
- **What does this program do?**
- Loads an image
- Convert the original to HSV format and separate only *Hue* channel to be used for the
Histogram (using the OpenCV function @ref cv::mixChannels )
- Let the user to enter the number of bins to be used in the calculation of the histogram.
- Calculate the histogram (and update it if the bins change) and the backprojection of the
same image.
- Display the backprojection and the histogram in windows.
@add_toggle_cpp
- **Downloadable code**:
- Click
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp)
for the basic version (explained in this tutorial).
- For stuff slightly fancier (using H-S histograms and floodFill to define a mask for the
skin area) you can check the [improved
demo](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo2.cpp)
- ...or you can always check out the classical
[camshiftdemo](https://github.com/opencv/opencv/tree/master/samples/cpp/camshiftdemo.cpp)
in samples.
- **Code at glance:**
@include samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp
@end_toggle
@add_toggle_java
- **Downloadable code**:
- Click
[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java)
for the basic version (explained in this tutorial).
- For stuff slightly fancier (using H-S histograms and floodFill to define a mask for the
skin area) you can check the [improved
demo](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo2.java)
- ...or you can always check out the classical
[camshiftdemo](https://github.com/opencv/opencv/tree/master/samples/cpp/camshiftdemo.cpp)
in samples.
- **Code at glance:**
@include samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java
@end_toggle
@add_toggle_python
- **Downloadable code**:
- Click
[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py)
for the basic version (explained in this tutorial).
- For stuff slightly fancier (using H-S histograms and floodFill to define a mask for the
skin area) you can check the [improved
demo](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo2.py)
- ...or you can always check out the classical
[camshiftdemo](https://github.com/opencv/opencv/tree/master/samples/cpp/camshiftdemo.cpp)
in samples.
- **Code at glance:**
@include samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py
@end_toggle
Explanation
-----------
- Read the input image:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Read the image
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Read the image
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Read the image
@end_toggle
- Transform it to HSV format:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Transform it to HSV
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Transform it to HSV
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Transform it to HSV
@end_toggle
- For this tutorial, we will use only the Hue value for our 1-D histogram (check out the fancier
code in the links above if you want to use the more standard H-S histogram, which yields better
results):
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Use only the Hue value
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Use only the Hue value
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Use only the Hue value
@end_toggle
- as you see, we use the function @ref cv::mixChannels to get only the channel 0 (Hue) from
the hsv image. It gets the following parameters:
- **&hsv:** The source array from which the channels will be copied
- **1:** The number of source arrays
- **&hue:** The destination array of the copied channels
- **1:** The number of destination arrays
- **ch[] = {0,0}:** The array of index pairs indicating how the channels are copied. In this
case, the Hue(0) channel of &hsv is being copied to the 0 channel of &hue (1-channel)
- **1:** Number of index pairs
- Create a Trackbar for the user to enter the bin values. Any change on the Trackbar means a call
to the **Hist_and_Backproj** callback function.
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Create Trackbar to enter the number of bins
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Create Trackbar to enter the number of bins
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Create Trackbar to enter the number of bins
@end_toggle
- Show the image and wait for the user to exit the program:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Show the image
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Show the image
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Show the image
@end_toggle
- **Hist_and_Backproj function:** Initialize the arguments needed for @ref cv::calcHist . The
number of bins comes from the Trackbar:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp initialize
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java initialize
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py initialize
@end_toggle
- Calculate the Histogram and normalize it to the range \f$[0,255]\f$
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Get the Histogram and normalize it
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Get the Histogram and normalize it
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Get the Histogram and normalize it
@end_toggle
- Get the Backprojection of the same image by calling the function @ref cv::calcBackProject
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Get Backprojection
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Get Backprojection
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Get Backprojection
@end_toggle
- all the arguments are known (the same as used to calculate the histogram), only we add the
backproj matrix, which will store the backprojection of the source image (&hue)
- Display backproj:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Draw the backproj
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Draw the backproj
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Draw the backproj
@end_toggle
- Draw the 1-D Hue histogram of the image:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Draw the histogram
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Draw the histogram
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Draw the histogram
@end_toggle
Results
-------
Here are the output by using a sample image ( guess what? Another hand ). You can play with the
bin values and you will observe how it affects the results:
![R0](images/Back_Projection1_Source_Image.jpg)
![R1](images/Back_Projection1_Histogram.jpg)
![R2](images/Back_Projection1_BackProj.jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@@ -0,0 +1,297 @@
Histogram Calculation {#tutorial_histogram_calculation}
=====================
@tableofcontents
@prev_tutorial{tutorial_histogram_equalization}
@next_tutorial{tutorial_histogram_comparison}
| | |
| -: | :- |
| Original author | Ana Huamán |
| Compatibility | OpenCV >= 3.0 |
Goal
----
In this tutorial you will learn how to:
- Use the OpenCV function @ref cv::split to divide an image into its correspondent planes.
- To calculate histograms of arrays of images by using the OpenCV function @ref cv::calcHist
- To normalize an array by using the function @ref cv::normalize
@note In the last tutorial (@ref tutorial_histogram_equalization) we talked about a particular kind of
histogram called *Image histogram*. Now we will considerate it in its more general concept. Read on!
### What are histograms?
- Histograms are collected *counts* of data organized into a set of predefined *bins*
- When we say *data* we are not restricting it to be intensity values (as we saw in the previous
Tutorial @ref tutorial_histogram_equalization). The data collected can be whatever feature you find
useful to describe your image.
- Let's see an example. Imagine that a Matrix contains information of an image (i.e. intensity in
the range \f$0-255\f$):
![](images/Histogram_Calculation_Theory_Hist0.jpg)
- What happens if we want to *count* this data in an organized way? Since we know that the *range*
of information value for this case is 256 values, we can segment our range in subparts (called
**bins**) like:
\f[\begin{array}{l}
[0, 255] = { [0, 15] \cup [16, 31] \cup ....\cup [240,255] } \\
range = { bin_{1} \cup bin_{2} \cup ....\cup bin_{n = 15} }
\end{array}\f]
and we can keep count of the number of pixels that fall in the range of each \f$bin_{i}\f$. Applying
this to the example above we get the image below ( axis x represents the bins and axis y the
number of pixels in each of them).
![](images/Histogram_Calculation_Theory_Hist1.jpg)
- This was just a simple example of how an histogram works and why it is useful. An histogram can
keep count not only of color intensities, but of whatever image features that we want to measure
(i.e. gradients, directions, etc).
- Let's identify some parts of the histogram:
-# **dims**: The number of parameters you want to collect data of. In our example, **dims = 1**
because we are only counting the intensity values of each pixel (in a greyscale image).
-# **bins**: It is the number of **subdivisions** in each dim. In our example, **bins = 16**
-# **range**: The limits for the values to be measured. In this case: **range = [0,255]**
- What if you want to count two features? In this case your resulting histogram would be a 3D plot
(in which x and y would be \f$bin_{x}\f$ and \f$bin_{y}\f$ for each feature and z would be the number of
counts for each combination of \f$(bin_{x}, bin_{y})\f$. The same would apply for more features (of
course it gets trickier).
### What OpenCV offers you
For simple purposes, OpenCV implements the function @ref cv::calcHist , which calculates the
histogram of a set of arrays (usually images or image planes). It can operate with up to 32
dimensions. We will see it in the code below!
Code
----
- **What does this program do?**
- Loads an image
- Splits the image into its R, G and B planes using the function @ref cv::split
- Calculate the Histogram of each 1-channel plane by calling the function @ref cv::calcHist
- Plot the three histograms in a window
@add_toggle_cpp
- **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp)
- **Code at glance:**
@include samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp
@end_toggle
@add_toggle_java
- **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java)
- **Code at glance:**
@include samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java
@end_toggle
@add_toggle_python
- **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py)
- **Code at glance:**
@include samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py
@end_toggle
Explanation
-----------
- Load the source image
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Load image
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Load image
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Load image
@end_toggle
- Separate the source image in its three R,G and B planes. For this we use the OpenCV function
@ref cv::split :
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Separate the image in 3 places ( B, G and R )
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Separate the image in 3 places ( B, G and R )
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Separate the image in 3 places ( B, G and R )
@end_toggle
our input is the image to be divided (this case with three channels) and the output is a vector
of Mat )
- Now we are ready to start configuring the **histograms** for each plane. Since we are working
with the B, G and R planes, we know that our values will range in the interval \f$[0,255]\f$
- Establish the number of bins (5, 10...):
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Establish the number of bins
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Establish the number of bins
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Establish the number of bins
@end_toggle
- Set the range of values (as we said, between 0 and 255 )
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Set the ranges ( for B,G,R) )
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Set the ranges ( for B,G,R) )
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Set the ranges ( for B,G,R) )
@end_toggle
- We want our bins to have the same size (uniform) and to clear the histograms in the
beginning, so:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Set histogram param
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Set histogram param
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Set histogram param
@end_toggle
- We proceed to calculate the histograms by using the OpenCV function @ref cv::calcHist :
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Compute the histograms
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Compute the histograms
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Compute the histograms
@end_toggle
- where the arguments are (**C++ code**):
- **&bgr_planes[0]:** The source array(s)
- **1**: The number of source arrays (in this case we are using 1. We can enter here also
a list of arrays )
- **0**: The channel (*dim*) to be measured. In this case it is just the intensity (each
array is single-channel) so we just write 0.
- **Mat()**: A mask to be used on the source array ( zeros indicating pixels to be ignored
). If not defined it is not used
- **b_hist**: The Mat object where the histogram will be stored
- **1**: The histogram dimensionality.
- **histSize:** The number of bins per each used dimension
- **histRange:** The range of values to be measured per each dimension
- **uniform** and **accumulate**: The bin sizes are the same and the histogram is cleared
at the beginning.
- Create an image to display the histograms:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Draw the histograms for B, G and R
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Draw the histograms for B, G and R
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Draw the histograms for B, G and R
@end_toggle
- Notice that before drawing, we first @ref cv::normalize the histogram so its values fall in the
range indicated by the parameters entered:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Normalize the result to ( 0, histImage.rows )
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Normalize the result to ( 0, histImage.rows )
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Normalize the result to ( 0, histImage.rows )
@end_toggle
- this function receives these arguments (**C++ code**):
- **b_hist:** Input array
- **b_hist:** Output normalized array (can be the same)
- **0** and **histImage.rows**: For this example, they are the lower and upper limits to
normalize the values of **r_hist**
- **NORM_MINMAX:** Argument that indicates the type of normalization (as described above, it
adjusts the values between the two limits set before)
- **-1:** Implies that the output normalized array will be the same type as the input
- **Mat():** Optional mask
- Observe that to access the bin (in this case in this 1D-Histogram):
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Draw for each channel
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Draw for each channel
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Draw for each channel
@end_toggle
we use the expression (**C++ code**):
@code{.cpp}
b_hist.at<float>(i)
@endcode
where \f$i\f$ indicates the dimension. If it were a 2D-histogram we would use something like:
@code{.cpp}
b_hist.at<float>( i, j )
@endcode
- Finally we display our histograms and wait for the user to exit:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Display
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Display
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Display
@end_toggle
Result
------
-# Using as input argument an image like the one shown below:
![](images/Histogram_Calculation_Original_Image.jpg)
-# Produces the following histogram:
![](images/Histogram_Calculation_Result.jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@@ -0,0 +1,196 @@
Histogram Comparison {#tutorial_histogram_comparison}
====================
@tableofcontents
@prev_tutorial{tutorial_histogram_calculation}
@next_tutorial{tutorial_back_projection}
| | |
| -: | :- |
| Original author | Ana Huamán |
| Compatibility | OpenCV >= 3.0 |
Goal
----
In this tutorial you will learn how to:
- Use the function @ref cv::compareHist to get a numerical parameter that express how well two
histograms match with each other.
- Use different metrics to compare histograms
Theory
------
- To compare two histograms ( \f$H_{1}\f$ and \f$H_{2}\f$ ), first we have to choose a *metric*
(\f$d(H_{1}, H_{2})\f$) to express how well both histograms match.
- OpenCV implements the function @ref cv::compareHist to perform a comparison. It also offers 4
different metrics to compute the matching:
-# **Correlation ( CV_COMP_CORREL )**
\f[d(H_1,H_2) = \frac{\sum_I (H_1(I) - \bar{H_1}) (H_2(I) - \bar{H_2})}{\sqrt{\sum_I(H_1(I) - \bar{H_1})^2 \sum_I(H_2(I) - \bar{H_2})^2}}\f]
where
\f[\bar{H_k} = \frac{1}{N} \sum _J H_k(J)\f]
and \f$N\f$ is the total number of histogram bins.
-# **Chi-Square ( CV_COMP_CHISQR )**
\f[d(H_1,H_2) = \sum _I \frac{\left(H_1(I)-H_2(I)\right)^2}{H_1(I)}\f]
-# **Intersection ( method=CV_COMP_INTERSECT )**
\f[d(H_1,H_2) = \sum _I \min (H_1(I), H_2(I))\f]
-# **Bhattacharyya distance ( CV_COMP_BHATTACHARYYA )**
\f[d(H_1,H_2) = \sqrt{1 - \frac{1}{\sqrt{\bar{H_1} \bar{H_2} N^2}} \sum_I \sqrt{H_1(I) \cdot H_2(I)}}\f]
Code
----
- **What does this program do?**
- Loads a *base image* and 2 *test images* to be compared with it.
- Generate 1 image that is the lower half of the *base image*
- Convert the images to HSV format
- Calculate the H-S histogram for all the images and normalize them in order to compare them.
- Compare the histogram of the *base image* with respect to the 2 test histograms, the
histogram of the lower half base image and with the same base image histogram.
- Display the numerical matching parameters obtained.
@add_toggle_cpp
- **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp)
- **Code at glance:**
@include samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp
@end_toggle
@add_toggle_java
- **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java)
- **Code at glance:**
@include samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java
@end_toggle
@add_toggle_python
- **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py)
- **Code at glance:**
@include samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py
@end_toggle
Explanation
-----------
- Load the base image (src_base) and the other two test images:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Load three images with different environment settings
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java Load three images with different environment settings
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py Load three images with different environment settings
@end_toggle
- Convert them to HSV format:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Convert to HSV
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java Convert to HSV
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py Convert to HSV
@end_toggle
- Also, create an image of half the base image (in HSV format):
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Convert to HSV half
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java Convert to HSV half
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py Convert to HSV half
@end_toggle
- Initialize the arguments to calculate the histograms (bins, ranges and channels H and S ).
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Using 50 bins for hue and 60 for saturation
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java Using 50 bins for hue and 60 for saturation
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py Using 50 bins for hue and 60 for saturation
@end_toggle
- Calculate the Histograms for the base image, the 2 test images and the half-down base image:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Calculate the histograms for the HSV images
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java Calculate the histograms for the HSV images
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py Calculate the histograms for the HSV images
@end_toggle
- Apply sequentially the 4 comparison methods between the histogram of the base image (hist_base)
and the other histograms:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Apply the histogram comparison methods
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java Apply the histogram comparison methods
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py Apply the histogram comparison methods
@end_toggle
Results
-------
-# We use as input the following images:
![Base_0](images/Histogram_Comparison_Source_0.jpg)
![Test_1](images/Histogram_Comparison_Source_1.jpg)
![Test_2](images/Histogram_Comparison_Source_2.jpg)
where the first one is the base (to be compared to the others), the other 2 are the test images.
We will also compare the first image with respect to itself and with respect of half the base
image.
-# We should expect a perfect match when we compare the base image histogram with itself. Also,
compared with the histogram of half the base image, it should present a high match since both
are from the same source. For the other two test images, we can observe that they have very
different lighting conditions, so the matching should not be very good:
-# Here the numeric results we got with OpenCV 3.4.1:
*Method* | Base - Base | Base - Half | Base - Test 1 | Base - Test 2
----------------- | ------------ | ------------ | -------------- | ---------------
*Correlation* | 1.000000 | 0.880438 | 0.20457 | 0.0664547
*Chi-square* | 0.000000 | 4.6834 | 2697.98 | 4763.8
*Intersection* | 18.8947 | 13.022 | 5.44085 | 2.58173
*Bhattacharyya* | 0.000000 | 0.237887 | 0.679826 | 0.874173
For the *Correlation* and *Intersection* methods, the higher the metric, the more accurate the
match. As we can see, the match *base-base* is the highest of all as expected. Also we can observe
that the match *base-half* is the second best match (as we predicted). For the other two metrics,
the less the result, the better the match. We can observe that the matches between the test 1 and
test 2 with respect to the base are worse, which again, was expected.

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -0,0 +1,200 @@
Histogram Equalization {#tutorial_histogram_equalization}
======================
@tableofcontents
@prev_tutorial{tutorial_warp_affine}
@next_tutorial{tutorial_histogram_calculation}
| | |
| -: | :- |
| Original author | Ana Huamán |
| Compatibility | OpenCV >= 3.0 |
Goal
----
In this tutorial you will learn:
- What an image histogram is and why it is useful
- To equalize histograms of images by using the OpenCV function @ref cv::equalizeHist
Theory
------
### What is an Image Histogram?
- It is a graphical representation of the intensity distribution of an image.
- It quantifies the number of pixels for each intensity value considered.
![](images/Histogram_Equalization_Theory_0.jpg)
### What is Histogram Equalization?
- It is a method that improves the contrast in an image, in order to stretch out the intensity
range (see also the corresponding <a href="https://en.wikipedia.org/wiki/Histogram_equalization">Wikipedia entry</a>).
- To make it clearer, from the image above, you can see that the pixels seem clustered around the
middle of the available range of intensities. What Histogram Equalization does is to *stretch
out* this range. Take a look at the figure below: The green circles indicate the
*underpopulated* intensities. After applying the equalization, we get an histogram like the
figure in the center. The resulting image is shown in the picture at right.
![](images/Histogram_Equalization_Theory_1.jpg)
### How does it work?
- Equalization implies *mapping* one distribution (the given histogram) to another distribution (a
wider and more uniform distribution of intensity values) so the intensity values are spread
over the whole range.
- To accomplish the equalization effect, the remapping should be the *cumulative distribution
function (cdf)* (more details, refer to *Learning OpenCV*). For the histogram \f$H(i)\f$, its
*cumulative distribution* \f$H^{'}(i)\f$ is:
\f[H^{'}(i) = \sum_{0 \le j < i} H(j)\f]
To use this as a remapping function, we have to normalize \f$H^{'}(i)\f$ such that the maximum value
is 255 ( or the maximum value for the intensity of the image ). From the example above, the
cumulative function is:
![](images/Histogram_Equalization_Theory_2.jpg)
- Finally, we use a simple remapping procedure to obtain the intensity values of the equalized
image:
\f[equalized( x, y ) = H^{'}( src(x,y) )\f]
Code
----
- **What does this program do?**
- Loads an image
- Convert the original image to grayscale
- Equalize the Histogram by using the OpenCV function @ref cv::equalizeHist
- Display the source and equalized images in a window.
@add_toggle_cpp
- **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp)
- **Code at glance:**
@include samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp
@end_toggle
@add_toggle_java
- **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java)
- **Code at glance:**
@include samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java
@end_toggle
@add_toggle_python
- **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py)
- **Code at glance:**
@include samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py
@end_toggle
Explanation
-----------
- Load the source image:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Load image
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Load image
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py Load image
@end_toggle
- Convert it to grayscale:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Convert to grayscale
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Convert to grayscale
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py Convert to grayscale
@end_toggle
- Apply histogram equalization with the function @ref cv::equalizeHist :
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Apply Histogram Equalization
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Apply Histogram Equalization
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py Apply Histogram Equalization
@end_toggle
As it can be easily seen, the only arguments are the original image and the output (equalized)
image.
- Display both images (original and equalized):
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Display results
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Display results
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py Display results
@end_toggle
- Wait until user exists the program
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Wait until user exits the program
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Wait until user exits the program
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py Wait until user exits the program
@end_toggle
Results
-------
-# To appreciate better the results of equalization, let's introduce an image with not much
contrast, such as:
![](images/Histogram_Equalization_Original_Image.jpg)
which, by the way, has this histogram:
![](images/Histogram_Equalization_Original_Histogram.jpg)
notice that the pixels are clustered around the center of the histogram.
-# After applying the equalization with our program, we get this result:
![](images/Histogram_Equalization_Equalized_Image.jpg)
this image has certainly more contrast. Check out its new histogram like this:
![](images/Histogram_Equalization_Equalized_Histogram.jpg)
Notice how the number of pixels is more distributed through the intensity range.
@note
Are you wondering how did we draw the Histogram figures shown above? Check out the following
tutorial!

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,327 @@
Template Matching {#tutorial_template_matching}
=================
@tableofcontents
@prev_tutorial{tutorial_back_projection}
@next_tutorial{tutorial_find_contours}
| | |
| -: | :- |
| Original author | Ana Huamán |
| Compatibility | OpenCV >= 3.0 |
Goal
----
In this tutorial you will learn how to:
- Use the OpenCV function **matchTemplate()** to search for matches between an image patch and
an input image
- Use the OpenCV function **minMaxLoc()** to find the maximum and minimum values (as well as
their positions) in a given array.
Theory
------
### What is template matching?
Template matching is a technique for finding areas of an image that match (are similar) to a
template image (patch).
While the patch must be a rectangle it may be that not all of the
rectangle is relevant. In such a case, a mask can be used to isolate the portion of the patch
that should be used to find the match.
### How does it work?
- We need two primary components:
-# **Source image (I):** The image in which we expect to find a match to the template image
-# **Template image (T):** The patch image which will be compared to the source image
our goal is to detect the highest matching area:
![](images/Template_Matching_Template_Theory_Summary.jpg)
- To identify the matching area, we have to *compare* the template image against the source image
by sliding it:
![](images/Template_Matching_Template_Theory_Sliding.jpg)
- By **sliding**, we mean moving the patch one pixel at a time (left to right, up to down). At
each location, a metric is calculated so it represents how "good" or "bad" the match at that
location is (or how similar the patch is to that particular area of the source image).
- For each location of **T** over **I**, you *store* the metric in the *result matrix* **R**.
Each location \f$(x,y)\f$ in **R** contains the match metric:
![](images/Template_Matching_Template_Theory_Result.jpg)
the image above is the result **R** of sliding the patch with a metric **TM_CCORR_NORMED**.
The brightest locations indicate the highest matches. As you can see, the location marked by the
red circle is probably the one with the highest value, so that location (the rectangle formed by
that point as a corner and width and height equal to the patch image) is considered the match.
- In practice, we locate the highest value (or lower, depending of the type of matching method) in
the *R* matrix, using the function **minMaxLoc()**
### How does the mask work?
- If masking is needed for the match, three components are required:
-# **Source image (I):** The image in which we expect to find a match to the template image
-# **Template image (T):** The patch image which will be compared to the source image
-# **Mask image (M):** The mask, a grayscale image that masks the template
- Only two matching methods currently accept a mask: TM_SQDIFF and TM_CCORR_NORMED (see
below for explanation of all the matching methods available in opencv).
- The mask must have the same dimensions as the template
- The mask should have a CV_8U or CV_32F depth and the same number of channels
as the template image. In CV_8U case, the mask values are treated as binary,
i.e. zero and non-zero. In CV_32F case, the values should fall into [0..1]
range and the template pixels will be multiplied by the corresponding mask pixel
values. Since the input images in the sample have the CV_8UC3 type, the mask
is also read as color image.
![](images/Template_Matching_Mask_Example.jpg)
### Which are the matching methods available in OpenCV?
Good question. OpenCV implements Template matching in the function **matchTemplate()**. The
available methods are 6:
-# **method=TM_SQDIFF**
\f[R(x,y)= \sum _{x',y'} (T(x',y')-I(x+x',y+y'))^2\f]
-# **method=TM_SQDIFF_NORMED**
\f[R(x,y)= \frac{\sum_{x',y'} (T(x',y')-I(x+x',y+y'))^2}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}\f]
-# **method=TM_CCORR**
\f[R(x,y)= \sum _{x',y'} (T(x',y') \cdot I(x+x',y+y'))\f]
-# **method=TM_CCORR_NORMED**
\f[R(x,y)= \frac{\sum_{x',y'} (T(x',y') \cdot I(x+x',y+y'))}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}\f]
-# **method=TM_CCOEFF**
\f[R(x,y)= \sum _{x',y'} (T'(x',y') \cdot I'(x+x',y+y'))\f]
where
\f[\begin{array}{l} T'(x',y')=T(x',y') - 1/(w \cdot h) \cdot \sum _{x'',y''} T(x'',y'') \\ I'(x+x',y+y')=I(x+x',y+y') - 1/(w \cdot h) \cdot \sum _{x'',y''} I(x+x'',y+y'') \end{array}\f]
-# **method=TM_CCOEFF_NORMED**
\f[R(x,y)= \frac{ \sum_{x',y'} (T'(x',y') \cdot I'(x+x',y+y')) }{ \sqrt{\sum_{x',y'}T'(x',y')^2 \cdot \sum_{x',y'} I'(x+x',y+y')^2} }\f]
Code
----
- **What does this program do?**
- Loads an input image, an image patch (*template*), and optionally a mask
- Perform a template matching procedure by using the OpenCV function **matchTemplate()**
with any of the 6 matching methods described before. The user can choose the method by
entering its selection in the Trackbar. If a mask is supplied, it will only be used for
the methods that support masking
- Normalize the output of the matching procedure
- Localize the location with higher matching probability
- Draw a rectangle around the area corresponding to the highest match
@add_toggle_cpp
- **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp)
- **Code at glance:**
@include samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp
@end_toggle
@add_toggle_java
- **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java)
- **Code at glance:**
@include samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java
@end_toggle
@add_toggle_python
- **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/imgProc/match_template/match_template.py)
- **Code at glance:**
@include samples/python/tutorial_code/imgProc/match_template/match_template.py
@end_toggle
Explanation
-----------
- Declare some global variables, such as the image, template and result matrices, as well as the
match method and the window names:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp declare
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java declare
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/imgProc/match_template/match_template.py global_variables
@end_toggle
- Load the source image, template, and optionally, if supported for the matching method, a mask:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp load_image
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java load_image
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/imgProc/match_template/match_template.py load_image
@end_toggle
- Create the Trackbar to enter the kind of matching method to be used. When a change is detected
the callback function is called.
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp create_trackbar
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java create_trackbar
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/imgProc/match_template/match_template.py create_trackbar
@end_toggle
- Let's check out the callback function. First, it makes a copy of the source image:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp copy_source
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java copy_source
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/imgProc/match_template/match_template.py copy_source
@end_toggle
- Perform the template matching operation. The arguments are naturally the input image **I**,
the template **T**, the result **R** and the match_method (given by the Trackbar),
and optionally the mask image **M**.
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp match_template
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java match_template
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/imgProc/match_template/match_template.py match_template
@end_toggle
- We normalize the results:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp normalize
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java normalize
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/imgProc/match_template/match_template.py normalize
@end_toggle
- We localize the minimum and maximum values in the result matrix **R** by using **minMaxLoc()**.
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp best_match
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java best_match
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/imgProc/match_template/match_template.py best_match
@end_toggle
- For the first two methods ( TM_SQDIFF and MT_SQDIFF_NORMED ) the best match are the lowest
values. For all the others, higher values represent better matches. So, we save the
corresponding value in the **matchLoc** variable:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp match_loc
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java match_loc
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/imgProc/match_template/match_template.py match_loc
@end_toggle
- Display the source image and the result matrix. Draw a rectangle around the highest possible
matching area:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp imshow
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java imshow
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/imgProc/match_template/match_template.py imshow
@end_toggle
Results
-------
-# Testing our program with an input image such as:
![](images/Template_Matching_Original_Image.jpg)
and a template image:
![](images/Template_Matching_Template_Image.jpg)
-# Generate the following result matrices (first row are the standard methods SQDIFF, CCORR and
CCOEFF, second row are the same methods in its normalized version). In the first column, the
darkest is the better match, for the other two columns, the brighter a location, the higher the
match.
![Result_0](images/Template_Matching_Correl_Result_0.jpg)
![Result_1](images/Template_Matching_Correl_Result_1.jpg)
![Result_2](images/Template_Matching_Correl_Result_2.jpg)
![Result_3](images/Template_Matching_Correl_Result_3.jpg)
![Result_4](images/Template_Matching_Correl_Result_4.jpg)
![Result_5](images/Template_Matching_Correl_Result_5.jpg)
-# The right match is shown below (black rectangle around the face of the guy at the right). Notice
that CCORR and CCDEFF gave erroneous best matches, however their normalized version did it
right, this may be due to the fact that we are only considering the "highest match" and not the
other possible high matches.
![](images/Template_Matching_Image_Result.jpg)