mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 07:43:03 +04:00
Extending template_matching tutorial with Java (#8043)
* Extending template_matching tutorial with Java * adding mask to java version of the tutorial * adding the python toggle and code * updating table of content * adding py and java to table of content * adding mask to python * going back to markdown with duplicated text * non duplicated text
This commit is contained in:
committed by
Maksim Shabunin
parent
3b669149d2
commit
2055bcc807
@@ -1,14 +1,17 @@
|
||||
Template Matching {#tutorial_template_matching}
|
||||
=================
|
||||
|
||||
@prev_tutorial{tutorial_back_projection}
|
||||
@next_tutorial{tutorial_find_contours}
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
In this tutorial you will learn how to:
|
||||
|
||||
- Use the OpenCV function @ref cv::matchTemplate to search for matches between an image patch and
|
||||
- Use the OpenCV function **matchTemplate()** to search for matches between an image patch and
|
||||
an input image
|
||||
- Use the OpenCV function @ref cv::minMaxLoc to find the maximum and minimum values (as well as
|
||||
- Use the OpenCV function **minMaxLoc()** to find the maximum and minimum values (as well as
|
||||
their positions) in a given array.
|
||||
|
||||
Theory
|
||||
@@ -42,7 +45,7 @@ that should be used to find the match.
|
||||
- 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)**.
|
||||
- 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:
|
||||
|
||||

|
||||
@@ -51,9 +54,8 @@ that should be used to find the match.
|
||||
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 use the function @ref cv::minMaxLoc to locate the highest value (or lower,
|
||||
depending of the type of matching method) in the *R* matrix.
|
||||
- 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:
|
||||
@@ -81,7 +83,7 @@ that should be used to find the match.
|
||||
|
||||
### Which are the matching methods available in OpenCV?
|
||||
|
||||
Good question. OpenCV implements Template matching in the function @ref cv::matchTemplate . The
|
||||
Good question. OpenCV implements Template matching in the function **matchTemplate()**. The
|
||||
available methods are 6:
|
||||
|
||||
-# **method=CV_TM_SQDIFF**
|
||||
@@ -117,119 +119,176 @@ 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 @ref cv::matchTemplate
|
||||
- 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
|
||||
- Declare some global variables, such as the image, template and result matrices, as well as the
|
||||
match method and the window names:
|
||||
@code{.cpp}
|
||||
Mat img; Mat templ; Mat result;
|
||||
char* image_window = "Source Image";
|
||||
char* result_window = "Result window";
|
||||
|
||||
int match_method;
|
||||
int max_Trackbar = 5;
|
||||
@endcode
|
||||
-# Load the source image, template, and optionally, if supported for the matching method, a mask:
|
||||
@code{.cpp}
|
||||
bool method_accepts_mask = (CV_TM_SQDIFF == match_method || match_method == CV_TM_CCORR_NORMED);
|
||||
if (use_mask && method_accepts_mask)
|
||||
{ matchTemplate( img, templ, result, match_method, mask); }
|
||||
else
|
||||
{ matchTemplate( img, templ, result, match_method); }
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp declare
|
||||
@end_toggle
|
||||
|
||||
@endcode
|
||||
-# Create the windows to show the results:
|
||||
@code{.cpp}
|
||||
namedWindow( image_window, WINDOW_AUTOSIZE );
|
||||
namedWindow( result_window, WINDOW_AUTOSIZE );
|
||||
@endcode
|
||||
-# Create the Trackbar to enter the kind of matching method to be used. When a change is detected
|
||||
the callback function **MatchingMethod** is called.
|
||||
@code{.cpp}
|
||||
char* trackbar_label = "Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED";
|
||||
createTrackbar( trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod );
|
||||
@endcode
|
||||
-# Wait until user exits the program.
|
||||
@code{.cpp}
|
||||
waitKey(0);
|
||||
return 0;
|
||||
@endcode
|
||||
-# Let's check out the callback function. First, it makes a copy of the source image:
|
||||
@code{.cpp}
|
||||
Mat img_display;
|
||||
img.copyTo( img_display );
|
||||
@endcode
|
||||
-# Next, it creates the result matrix that will store the matching results for each template
|
||||
location. Observe in detail the size of the result matrix (which matches all possible locations
|
||||
for it)
|
||||
@code{.cpp}
|
||||
int result_cols = img.cols - templ.cols + 1;
|
||||
int result_rows = img.rows - templ.rows + 1;
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java declare
|
||||
@end_toggle
|
||||
|
||||
result.create( result_rows, result_cols, CV_32FC1 );
|
||||
@endcode
|
||||
-# Perform the template matching operation:
|
||||
@code{.cpp}
|
||||
bool method_accepts_mask = (CV_TM_SQDIFF == match_method || match_method == CV_TM_CCORR_NORMED);
|
||||
if (use_mask && method_accepts_mask)
|
||||
{ matchTemplate( img, templ, result, match_method, mask); }
|
||||
else
|
||||
{ matchTemplate( img, templ, result, match_method); }
|
||||
@endcode
|
||||
the arguments are naturally the input image **I**, the template **T**, the result **R**, the
|
||||
match_method (given by the Trackbar), and optionally the mask image **M**
|
||||
@add_toggle_python
|
||||
@snippet samples/python/tutorial_code/imgProc/match_template/match_template.py global_variables
|
||||
@end_toggle
|
||||
|
||||
-# We normalize the results:
|
||||
@code{.cpp}
|
||||
normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );
|
||||
@endcode
|
||||
-# We localize the minimum and maximum values in the result matrix **R** by using @ref
|
||||
cv::minMaxLoc .
|
||||
@code{.cpp}
|
||||
double minVal; double maxVal; Point minLoc; Point maxLoc;
|
||||
Point matchLoc;
|
||||
- Load the source image, template, and optionally, if supported for the matching method, a mask:
|
||||
|
||||
minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
|
||||
@endcode
|
||||
the function calls as arguments:
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp load_image
|
||||
@end_toggle
|
||||
|
||||
- **result:** The source array
|
||||
- **&minVal** and **&maxVal:** Variables to save the minimum and maximum values in **result**
|
||||
- **&minLoc** and **&maxLoc:** The Point locations of the minimum and maximum values in the
|
||||
array.
|
||||
- **Mat():** Optional mask
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java load_image
|
||||
@end_toggle
|
||||
|
||||
-# For the first two methods ( TM_SQDIFF and MT_SQDIFF_NORMED ) the best match are the lowest
|
||||
@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:
|
||||
@code{.cpp}
|
||||
if( match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED )
|
||||
{ matchLoc = minLoc; }
|
||||
else
|
||||
{ matchLoc = maxLoc; }
|
||||
@endcode
|
||||
-# Display the source image and the result matrix. Draw a rectangle around the highest possible
|
||||
matching area:
|
||||
@code{.cpp}
|
||||
rectangle( img_display, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
|
||||
rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
|
||||
|
||||
imshow( image_window, img_display );
|
||||
imshow( result_window, result );
|
||||
@endcode
|
||||
@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
|
||||
-------
|
||||
|
||||
@@ -173,6 +173,8 @@ In this section you will learn about the image processing (manipulation) functio
|
||||
|
||||
- @subpage tutorial_template_matching
|
||||
|
||||
*Languages:* C++, Java, Python
|
||||
|
||||
*Compatibility:* \> OpenCV 2.0
|
||||
|
||||
*Author:* Ana Huamán
|
||||
|
||||
Reference in New Issue
Block a user