Commit 2055bcc8 authored by Cartucho's avatar Cartucho Committed by Maksim Shabunin

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
parent 3b669149
...@@ -67,7 +67,7 @@ $("h2").each(function() { ...@@ -67,7 +67,7 @@ $("h2").each(function() {
$smallerHeadings = $(this).nextUntil("h2").filter("h3").add($(this).nextUntil("h2").find("h3")); $smallerHeadings = $(this).nextUntil("h2").filter("h3").add($(this).nextUntil("h2").find("h3"));
if ($smallerHeadings.length) { if ($smallerHeadings.length) {
$smallerHeadings.each(function() { $smallerHeadings.each(function() {
var $elements = $(this).nextUntil("h3").filter("div.newInnerHTML"); var $elements = $(this).nextUntil("h2,h3").filter("div.newInnerHTML");
buttonsToAdd($elements, $(this), "h3"); buttonsToAdd($elements, $(this), "h3");
}); });
} else { } else {
......
Template Matching {#tutorial_template_matching} Template Matching {#tutorial_template_matching}
================= =================
@prev_tutorial{tutorial_back_projection}
@next_tutorial{tutorial_find_contours}
Goal Goal
---- ----
In this tutorial you will learn how to: 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 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. their positions) in a given array.
Theory Theory
...@@ -42,7 +45,7 @@ that should be used to find the match. ...@@ -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 - 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 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). 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: Each location \f$(x,y)\f$ in **R** contains the match metric:
![](images/Template_Matching_Template_Theory_Result.jpg) ![](images/Template_Matching_Template_Theory_Result.jpg)
...@@ -51,9 +54,8 @@ that should be used to find the match. ...@@ -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 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 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. 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
- In practice, we use the function @ref cv::minMaxLoc to locate the highest value (or lower, the *R* matrix, using the function **minMaxLoc()**
depending of the type of matching method) in the *R* matrix.
### How does the mask work? ### How does the mask work?
- If masking is needed for the match, three components are required: - If masking is needed for the match, three components are required:
...@@ -81,7 +83,7 @@ that should be used to find the match. ...@@ -81,7 +83,7 @@ that should be used to find the match.
### Which are the matching methods available in OpenCV? ### 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: available methods are 6:
-# **method=CV_TM_SQDIFF** -# **method=CV_TM_SQDIFF**
...@@ -117,119 +119,176 @@ Code ...@@ -117,119 +119,176 @@ Code
- **What does this program do?** - **What does this program do?**
- Loads an input image, an image patch (*template*), and optionally a mask - 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 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 entering its selection in the Trackbar. If a mask is supplied, it will only be used for
the methods that support masking the methods that support masking
- Normalize the output of the matching procedure - Normalize the output of the matching procedure
- Localize the location with higher matching probability - Localize the location with higher matching probability
- Draw a rectangle around the area corresponding to the highest match - Draw a rectangle around the area corresponding to the highest match
@add_toggle_cpp
- **Downloadable code**: Click - **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp) [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp)
- **Code at glance:** - **Code at glance:**
@include samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp @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 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: match method and the window names:
@code{.cpp}
Mat img; Mat templ; Mat result; @add_toggle_cpp
char* image_window = "Source Image"; @snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp declare
char* result_window = "Result window"; @end_toggle
int match_method; @add_toggle_java
int max_Trackbar = 5; @snippet samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java declare
@endcode @end_toggle
-# Load the source image, template, and optionally, if supported for the matching method, a mask:
@code{.cpp} @add_toggle_python
bool method_accepts_mask = (CV_TM_SQDIFF == match_method || match_method == CV_TM_CCORR_NORMED); @snippet samples/python/tutorial_code/imgProc/match_template/match_template.py global_variables
if (use_mask && method_accepts_mask) @end_toggle
{ matchTemplate( img, templ, result, match_method, mask); }
else - Load the source image, template, and optionally, if supported for the matching method, a mask:
{ matchTemplate( img, templ, result, match_method); }
@add_toggle_cpp
@endcode @snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp load_image
-# Create the windows to show the results: @end_toggle
@code{.cpp}
namedWindow( image_window, WINDOW_AUTOSIZE ); @add_toggle_java
namedWindow( result_window, WINDOW_AUTOSIZE ); @snippet samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java load_image
@endcode @end_toggle
-# Create the Trackbar to enter the kind of matching method to be used. When a change is detected
the callback function **MatchingMethod** is called. @add_toggle_python
@code{.cpp} @snippet samples/python/tutorial_code/imgProc/match_template/match_template.py load_image
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"; @end_toggle
createTrackbar( trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod );
@endcode - Create the Trackbar to enter the kind of matching method to be used. When a change is detected
-# Wait until user exits the program. the callback function is called.
@code{.cpp}
waitKey(0); @add_toggle_cpp
return 0; @snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp create_trackbar
@endcode @end_toggle
-# Let's check out the callback function. First, it makes a copy of the source image:
@code{.cpp} @add_toggle_java
Mat img_display; @snippet samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java create_trackbar
img.copyTo( img_display ); @end_toggle
@endcode
-# Next, it creates the result matrix that will store the matching results for each template @add_toggle_python
location. Observe in detail the size of the result matrix (which matches all possible locations @snippet samples/python/tutorial_code/imgProc/match_template/match_template.py create_trackbar
for it) @end_toggle
@code{.cpp}
int result_cols = img.cols - templ.cols + 1; - Let's check out the callback function. First, it makes a copy of the source image:
int result_rows = img.rows - templ.rows + 1;
@add_toggle_cpp
result.create( result_rows, result_cols, CV_32FC1 ); @snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp copy_source
@endcode @end_toggle
-# Perform the template matching operation:
@code{.cpp} @add_toggle_java
bool method_accepts_mask = (CV_TM_SQDIFF == match_method || match_method == CV_TM_CCORR_NORMED); @snippet samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java copy_source
if (use_mask && method_accepts_mask) @end_toggle
{ matchTemplate( img, templ, result, match_method, mask); }
else @add_toggle_python
{ matchTemplate( img, templ, result, match_method); } @snippet samples/python/tutorial_code/imgProc/match_template/match_template.py copy_source
@endcode @end_toggle
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** - 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),
-# We normalize the results: and optionally the mask image **M**.
@code{.cpp}
normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() ); @add_toggle_cpp
@endcode @snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp match_template
-# We localize the minimum and maximum values in the result matrix **R** by using @ref @end_toggle
cv::minMaxLoc .
@code{.cpp} @add_toggle_java
double minVal; double maxVal; Point minLoc; Point maxLoc; @snippet samples/java/tutorial_code/ImgProc/tutorial_template_matching/MatchTemplateDemo.java match_template
Point matchLoc; @end_toggle
minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() ); @add_toggle_python
@endcode @snippet samples/python/tutorial_code/imgProc/match_template/match_template.py match_template
the function calls as arguments: @end_toggle
- **result:** The source array - We normalize the results:
- **&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 @add_toggle_cpp
array. @snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp normalize
- **Mat():** Optional mask @end_toggle
-# For the first two methods ( TM_SQDIFF and MT_SQDIFF_NORMED ) the best match are the lowest @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 values. For all the others, higher values represent better matches. So, we save the
corresponding value in the **matchLoc** variable: corresponding value in the **matchLoc** variable:
@code{.cpp}
if( match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED ) @add_toggle_cpp
{ matchLoc = minLoc; } @snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp match_loc
else @end_toggle
{ matchLoc = maxLoc; }
@endcode @add_toggle_java
-# Display the source image and the result matrix. Draw a rectangle around the highest possible @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: 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 ); @add_toggle_cpp
imshow( result_window, result ); @snippet samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp imshow
@endcode @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 Results
------- -------
......
...@@ -173,6 +173,8 @@ In this section you will learn about the image processing (manipulation) functio ...@@ -173,6 +173,8 @@ In this section you will learn about the image processing (manipulation) functio
- @subpage tutorial_template_matching - @subpage tutorial_template_matching
*Languages:* C++, Java, Python
*Compatibility:* \> OpenCV 2.0 *Compatibility:* \> OpenCV 2.0
*Author:* Ana Huamán *Author:* Ana Huamán
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
using namespace std; using namespace std;
using namespace cv; using namespace cv;
//! [declare]
/// Global Variables /// Global Variables
bool use_mask; bool use_mask;
Mat img; Mat templ; Mat mask; Mat result; Mat img; Mat templ; Mat mask; Mat result;
...@@ -20,6 +21,7 @@ const char* result_window = "Result window"; ...@@ -20,6 +21,7 @@ const char* result_window = "Result window";
int match_method; int match_method;
int max_Trackbar = 5; int max_Trackbar = 5;
//! [declare]
/// Function Headers /// Function Headers
void MatchingMethod( int, void* ); void MatchingMethod( int, void* );
...@@ -36,6 +38,7 @@ int main( int argc, char** argv ) ...@@ -36,6 +38,7 @@ int main( int argc, char** argv )
return -1; return -1;
} }
//! [load_image]
/// Load image and template /// Load image and template
img = imread( argv[1], IMREAD_COLOR ); img = imread( argv[1], IMREAD_COLOR );
templ = imread( argv[2], IMREAD_COLOR ); templ = imread( argv[2], IMREAD_COLOR );
...@@ -50,19 +53,26 @@ int main( int argc, char** argv ) ...@@ -50,19 +53,26 @@ int main( int argc, char** argv )
cout << "Can't read one of the images" << endl; cout << "Can't read one of the images" << endl;
return -1; return -1;
} }
//! [load_image]
//! [create_windows]
/// Create windows /// Create windows
namedWindow( image_window, WINDOW_AUTOSIZE ); namedWindow( image_window, WINDOW_AUTOSIZE );
namedWindow( result_window, WINDOW_AUTOSIZE ); namedWindow( result_window, WINDOW_AUTOSIZE );
//! [create_windows]
//! [create_trackbar]
/// Create Trackbar /// Create Trackbar
const 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"; const 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 ); createTrackbar( trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod );
//! [create_trackbar]
MatchingMethod( 0, 0 ); MatchingMethod( 0, 0 );
//! [wait_key]
waitKey(0); waitKey(0);
return 0; return 0;
//! [wait_key]
} }
/** /**
...@@ -71,44 +81,57 @@ int main( int argc, char** argv ) ...@@ -71,44 +81,57 @@ int main( int argc, char** argv )
*/ */
void MatchingMethod( int, void* ) void MatchingMethod( int, void* )
{ {
//! [copy_source]
/// Source image to display /// Source image to display
Mat img_display; Mat img_display;
img.copyTo( img_display ); img.copyTo( img_display );
//! [copy_source]
//! [create_result_matrix]
/// Create the result matrix /// Create the result matrix
int result_cols = img.cols - templ.cols + 1; int result_cols = img.cols - templ.cols + 1;
int result_rows = img.rows - templ.rows + 1; int result_rows = img.rows - templ.rows + 1;
result.create( result_rows, result_cols, CV_32FC1 ); result.create( result_rows, result_cols, CV_32FC1 );
//! [create_result_matrix]
//! [match_template]
/// Do the Matching and Normalize /// Do the Matching and Normalize
bool method_accepts_mask = (CV_TM_SQDIFF == match_method || match_method == CV_TM_CCORR_NORMED); bool method_accepts_mask = (CV_TM_SQDIFF == match_method || match_method == CV_TM_CCORR_NORMED);
if (use_mask && method_accepts_mask) if (use_mask && method_accepts_mask)
{ matchTemplate( img, templ, result, match_method, mask); } { matchTemplate( img, templ, result, match_method, mask); }
else else
{ matchTemplate( img, templ, result, match_method); } { matchTemplate( img, templ, result, match_method); }
//! [match_template]
//! [normalize]
normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() ); normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );
//! [normalize]
//! [best_match]
/// Localizing the best match with minMaxLoc /// Localizing the best match with minMaxLoc
double minVal; double maxVal; Point minLoc; Point maxLoc; double minVal; double maxVal; Point minLoc; Point maxLoc;
Point matchLoc; Point matchLoc;
minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() ); minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
//! [best_match]
//! [match_loc]
/// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better /// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better
if( match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED ) if( match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED )
{ matchLoc = minLoc; } { matchLoc = minLoc; }
else else
{ matchLoc = maxLoc; } { matchLoc = maxLoc; }
//! [match_loc]
//! [imshow]
/// Show me what you got /// Show me what you got
rectangle( img_display, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 ); 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 ); rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
imshow( image_window, img_display ); imshow( image_window, img_display );
imshow( result_window, result ); imshow( result_window, result );
//! [imshow]
return; return;
} }
import org.opencv.core.*;
import org.opencv.core.Point;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.util.*;
class MatchTemplateDemoRun implements ChangeListener{
//! [declare]
/// Global Variables
Boolean use_mask = false;
Mat img = new Mat(), templ = new Mat();
Mat mask = new Mat();
int match_method;
JLabel imgDisplay = new JLabel(), resultDisplay = new JLabel();
//! [declare]
public void run(String[] args) {
if (args.length < 2)
{
System.out.println("Not enough parameters");
System.out.println("Program arguments:\n<image_name> <template_name> [<mask_name>]");
System.exit(-1);
}
//! [load_image]
/// Load image and template
img = Imgcodecs.imread( args[0], Imgcodecs.IMREAD_COLOR );
templ = Imgcodecs.imread( args[1], Imgcodecs.IMREAD_COLOR );
//! [load_image]
if(args.length > 2) {
use_mask = true;
mask = Imgcodecs.imread( args[2], Imgcodecs.IMREAD_COLOR );
}
if(img.empty() || templ.empty() || (use_mask && mask.empty()))
{
System.out.println("Can't read one of the images");
System.exit(-1);
}
matchingMethod();
createJFrame();
}
private void matchingMethod() {
Mat result = new Mat();
//! [copy_source]
/// Source image to display
Mat img_display = new Mat();
img.copyTo( img_display );
//! [copy_source]
//! [create_result_matrix]
/// Create the result matrix
int result_cols = img.cols() - templ.cols() + 1;
int result_rows = img.rows() - templ.rows() + 1;
result.create( result_rows, result_cols, CvType.CV_32FC1 );
//! [create_result_matrix]
//! [match_template]
/// Do the Matching and Normalize
Boolean method_accepts_mask = (Imgproc.TM_SQDIFF == match_method ||
match_method == Imgproc.TM_CCORR_NORMED);
if (use_mask && method_accepts_mask)
{ Imgproc.matchTemplate( img, templ, result, match_method, mask); }
else
{ Imgproc.matchTemplate( img, templ, result, match_method); }
//! [match_template]
//! [normalize]
Core.normalize( result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat() );
//! [normalize]
//! [best_match]
/// Localizing the best match with minMaxLoc
double minVal; double maxVal;
Point matchLoc;
Core.MinMaxLocResult mmr = Core.minMaxLoc( result );
//! [best_match]
//! [match_loc]
/// For SQDIFF and SQDIFF_NORMED, the best matches are lower values.
// For all the other methods, the higher the better
if( match_method == Imgproc.TM_SQDIFF || match_method == Imgproc.TM_SQDIFF_NORMED )
{ matchLoc = mmr.minLoc; }
else
{ matchLoc = mmr.maxLoc; }
//! [match_loc]
//! [imshow]
/// Show me what you got
Imgproc.rectangle(img_display, matchLoc, new Point(matchLoc.x + templ.cols(),
matchLoc.y + templ.rows()), new Scalar(0, 0, 0), 2, 8, 0);
Imgproc.rectangle(result, matchLoc, new Point(matchLoc.x + templ.cols(),
matchLoc.y + templ.rows()), new Scalar(0, 0, 0), 2, 8, 0);
Image tmpImg = toBufferedImage(img_display);
ImageIcon icon = new ImageIcon(tmpImg);
imgDisplay.setIcon(icon);
result.convertTo(result, CvType.CV_8UC1, 255.0);
tmpImg = toBufferedImage(result);
icon = new ImageIcon(tmpImg);
resultDisplay.setIcon(icon);
//! [imshow]
}
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
if (!source.getValueIsAdjusting()) {
match_method = (int)source.getValue();
matchingMethod();
}
}
public Image toBufferedImage(Mat m) {
int type = BufferedImage.TYPE_BYTE_GRAY;
if ( m.channels() > 1 ) {
type = BufferedImage.TYPE_3BYTE_BGR;
}
int bufferSize = m.channels()*m.cols()*m.rows();
byte [] b = new byte[bufferSize];
m.get(0,0,b); // get all the pixels
BufferedImage image = new BufferedImage(m.cols(),m.rows(), type);
final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
System.arraycopy(b, 0, targetPixels, 0, b.length);
return image;
}
private void createJFrame() {
String title = "Source image; Control; Result image";
JFrame frame = new JFrame(title);
frame.setLayout(new GridLayout(2, 2));
frame.add(imgDisplay);
//! [create_trackbar]
int min = 0, max = 5;
JSlider slider = new JSlider(JSlider.VERTICAL, min, max, match_method);
//! [create_trackbar]
slider.setPaintTicks(true);
slider.setPaintLabels(true);
// Set the spacing for the minor tick mark
slider.setMinorTickSpacing(1);
// Customizing the labels
Hashtable labelTable = new Hashtable();
labelTable.put( new Integer( 0 ), new JLabel("0 - SQDIFF") );
labelTable.put( new Integer( 1 ), new JLabel("1 - SQDIFF NORMED") );
labelTable.put( new Integer( 2 ), new JLabel("2 - TM CCORR") );
labelTable.put( new Integer( 3 ), new JLabel("3 - TM CCORR NORMED") );
labelTable.put( new Integer( 4 ), new JLabel("4 - TM COEFF") );
labelTable.put( new Integer( 5 ), new JLabel("5 - TM COEFF NORMED : (Method)") );
slider.setLabelTable( labelTable );
slider.addChangeListener(this);
frame.add(slider);
frame.add(resultDisplay);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
public class MatchTemplateDemo
{
public static void main(String[] args) {
// load the native OpenCV library
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// run code
new MatchTemplateDemoRun().run(args);
}
}
import sys
import cv2
## [global_variables]
use_mask = False
img = None
templ = None
mask = None
image_window = "Source Image"
result_window = "Result window"
match_method = 0
max_Trackbar = 5
## [global_variables]
def main(argv):
if (len(sys.argv) < 3):
print 'Not enough parameters'
print 'Usage:\nmatch_template_demo.py <image_name> <template_name> [<mask_name>]'
return -1
## [load_image]
global img
global templ
img = cv2.imread(sys.argv[1], cv2.IMREAD_COLOR)
templ = cv2.imread(sys.argv[2], cv2.IMREAD_COLOR)
if (len(sys.argv) > 3):
global use_mask
use_mask = True
global mask
mask = cv2.imread( sys.argv[3], cv2.IMREAD_COLOR )
if ((img is None) or (templ is None) or (use_mask and (mask is None))):
print 'Can\'t read one of the images'
return -1
## [load_image]
## [create_windows]
cv2.namedWindow( image_window, cv2.WINDOW_AUTOSIZE )
cv2.namedWindow( result_window, cv2.WINDOW_AUTOSIZE )
## [create_windows]
## [create_trackbar]
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'
cv2.createTrackbar( trackbar_label, image_window, match_method, max_Trackbar, MatchingMethod )
## [create_trackbar]
MatchingMethod(match_method)
## [wait_key]
cv2.waitKey(0)
return 0
## [wait_key]
def MatchingMethod(param):
global match_method
match_method = param
## [copy_source]
img_display = img.copy()
## [copy_source]
## [match_template]
method_accepts_mask = (cv2.TM_SQDIFF == match_method or match_method == cv2.TM_CCORR_NORMED)
if (use_mask and method_accepts_mask):
result = cv2.matchTemplate(img, templ, match_method, None, mask)
else:
result = cv2.matchTemplate(img, templ, match_method)
## [match_template]
## [normalize]
cv2.normalize( result, result, 0, 1, cv2.NORM_MINMAX, -1 )
## [normalize]
## [best_match]
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(result, None)
## [best_match]
## [match_loc]
if (match_method == cv2.TM_SQDIFF or match_method == cv2.TM_SQDIFF_NORMED):
matchLoc = minLoc
else:
matchLoc = maxLoc
## [match_loc]
## [imshow]
cv2.rectangle(img_display, matchLoc, (matchLoc[0] + templ.shape[0], matchLoc[1] + templ.shape[1]), (0,0,0), 2, 8, 0 )
cv2.rectangle(result, matchLoc, (matchLoc[0] + templ.shape[0], matchLoc[1] + templ.shape[1]), (0,0,0), 2, 8, 0 )
cv2.imshow(image_window, img_display)
cv2.imshow(result_window, result)
## [imshow]
pass
if __name__ == "__main__":
main(sys.argv[1:])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment