Lightsout
Lightsout

Reputation: 3757

OpenCV matchTemplate minVal maxVal only return 0 and 1

I am running the example code for opencv's matchTemplate function. I would like to know how "good" the match is and eliminate the data if the match quality is below a threshold.

    /// Do the Matching and Normalize
  matchTemplate( img, templ, result, match_method );
  normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );

  /// Localizing the best match with minMaxLoc
  double minVal; double maxVal; Point minLoc; Point maxLoc;
  Point matchLoc;

  minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );

  cout << "minVal" << minVal << "maxVal" << maxVal << endl;

I am printing out minVal and maxVal for matches running with different templ and img they all come out to 0 and 1. How do I fix this so that they give me different values for match quality?

full example code I ran from opencv.org

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>

using namespace std;
using namespace cv;

/// Global Variables
Mat img; Mat templ; Mat result;
char* image_window = "Source Image";
char* result_window = "Result window";

int match_method;
int max_Trackbar = 5;

/// Function Headers
void MatchingMethod( int, void* );

/** @function main */
int main( int argc, char** argv )
{
  /// Load image and template
  img = imread( argv[1], 1 );
  templ = imread( argv[2], 1 );

  /// Create windows
  namedWindow( image_window, CV_WINDOW_AUTOSIZE );
  namedWindow( result_window, CV_WINDOW_AUTOSIZE );

  /// Create Trackbar
  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 );

  MatchingMethod( 0, 0 );

  waitKey(0);
  return 0;
}

/**
 * @function MatchingMethod
 * @brief Trackbar callback
 */
void MatchingMethod( int, void* )
{
  /// Source image to display
  Mat img_display;
  img.copyTo( img_display );

  /// 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, CV_32FC1 );

  /// Do the Matching and Normalize
  matchTemplate( img, templ, result, match_method );
  normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );

  /// Localizing the best match with minMaxLoc
  double minVal; double maxVal; Point minLoc; Point maxLoc;
  Point matchLoc;

  minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
  //^^^^^^^^^^^^^^^^^^ ONLY GETTING 0 AND 1 HERE ^^^^^^^^^^^^^^^^^^^^^

  /// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better
  if( match_method  == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )
    { matchLoc = minLoc; }
  else
    { matchLoc = maxLoc; }

  /// 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( 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 );

  return;
}

Upvotes: 0

Views: 2157

Answers (1)

szym
szym

Reputation: 5846

Simple idea: remove the normalize call. It compresses the template match result into 0..1. See if maxVal gives you something meaningful if you don't normalize.

Detailed explanation

What you see is entirely expected.

After normalize(result, result, 0, 1, NORM_MINMAX, ...) the result matrix will have all values scaled (linearly) and shifted to fit the range 0..1. See: normalize doc And: What does cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC1);

minMaxLoc returns the values and locations of the min/max extrema. Therefore after that normalize, you'll always get minVal == 0, maxVal == 1. See: minMaxLoc doc

The interesting part of the minMaxLoc output here are the locations in minLoc and maxLoc. They will be the Point where the min and max are found.

If matchTemplate works well, you will see lots of low values and just one or a few peaks where the template matches well. maxLoc will have the coordinates of the top peak. The remaining values set by minMaxLoc tell you essentially nothing and you can ignore them. (As you can see in the sample code, some match methods will yield results that should interpreted the other way: low is good match, high is bad match -- in that case you should look at minLoc).

Upvotes: 2

Related Questions