OpenCV Template Matching example in Android
Asked Answered
T

2

27

I'm a beginner to OpenCV. I'm trying to do a sample android application to match a template image in a given image using OpenCV Template matching. I searched in the internet and I couldn't find a proper android or java code which satisfy my requirement. But I have C++ code. I dont know how to translate it. http://docs.opencv.org/doc/tutorials/imgproc/histograms/template_matching/template_matching.html

Can you please help me to find a proper java or android code. Or else please help me with translate this C++ code into java, which I can use inside android application.

Thank you in advance.

C++ code

#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_cols, result_rows, 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() );

  /// 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;
}
Tucket answered 8/6, 2013 at 15:34 Comment(9)
google for android-ndkFunereal
you mean to convert it using ndk? For OpenCV has a separate Android Library. I'm struggling to match these methods and types to exact methods and types in that library.Tucket
have you run the examples for the android sdk?Funereal
yes, but only some of them worked :(Tucket
yea those are the things, that not working.Tucket
let us continue this discussion in chatTucket
its not that simple I can give a one sentence answer, there are many factors like what OS you are using and what your target OS is, there is a step by step exampleFunereal
My target is 2.3.3 Ginger Bread. I found something.. I think this helps me.. #15799191Tucket
FYI, using correlation coefficient matching, a good match returns 1, no match returns 0, and a mismatch returns as low as -1.Salty
Y
47

I was facing the same problem you did. No source in Java available. Some search in the JavaDoc and some hints for const values later, I wrote this, which is almost the sample code above written in Java:

package opencv;

import org.opencv.core.Core;
import org.opencv.core.Core.MinMaxLocResult;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.highgui.Highgui;
import org.opencv.imgproc.Imgproc;

class MatchingDemo {
    public void run(String inFile, String templateFile, String outFile, int match_method) {
        System.out.println("\nRunning Template Matching");

        Mat img = Highgui.imread(inFile);
        Mat templ = Highgui.imread(templateFile);

        // / Create the result matrix
        int result_cols = img.cols() - templ.cols() + 1;
        int result_rows = img.rows() - templ.rows() + 1;
        Mat result = new Mat(result_rows, result_cols, CvType.CV_32FC1);

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

        // / Localizing the best match with minMaxLoc
        MinMaxLocResult mmr = Core.minMaxLoc(result);

        Point matchLoc;
        if (match_method == Imgproc.TM_SQDIFF || match_method == Imgproc.TM_SQDIFF_NORMED) {
            matchLoc = mmr.minLoc;
        } else {
            matchLoc = mmr.maxLoc;
        }

        // / Show me what you got
        Core.rectangle(img, matchLoc, new Point(matchLoc.x + templ.cols(),
                matchLoc.y + templ.rows()), new Scalar(0, 255, 0));

        // Save the visualized detection.
        System.out.println("Writing "+ outFile);
        Highgui.imwrite(outFile, img);

    }
}

public class TemplateMatching {
    public static void main(String[] args) {
        System.loadLibrary("opencv_java246");
        new MatchingDemo().run(args[0], args[1], args[2], Imgproc.TM_CCOEFF);
    }
}

Now, run the program with the following options: lena.png template.png templatematch.png and you should receive the same result I did. Make sure the files are accessible by your runtime and, of course, opencv 2.4.6 library is registered to your classpath.

lena.png template.png templatematch.png

Yuu answered 7/7, 2013 at 21:51 Comment(12)
I used your code but when i match it with a different image then also the rectangle is drawn even if the image is not matched ? and how do i get to know if there is a match or not like a Boolean stating that its a match or not (i mean something like that is there ?)Procrustean
I don't know. To get more people taking a look at your problem, post a new question please. It may be of interest for more people.Yuu
But its your code right? It draws rectangle even for a false match why is that ?Procrustean
There is no "wrong" match using matchTemplate(...). The result gives you "best matching (potential) object is in this location" only. So you need to add a check for an threshold of mmr.minVal or mmr.maxVal as stated in the answer https://mcmap.net/q/505823/-what-is-the-opencv-template-matching-max-min-value-range-need-to-be-used-as-a-theshold-c-java. And yes, I wrote this JAVA port.Yuu
This does not with photos captured from the camera. My scenario is that I have a template predefined, and I want to detect the template area from the captured image. Any idea how to get it working with camera captured images?Panpipe
@Panpipe I think you should post a new question and tell, what image format is used (camera picture may be raw, jpeg or smth else) along with some code sample and image data if possible.Yuu
I posted a new question: #19454105Panpipe
@Yuu thank you for your effort it worked like a charm, I have one simple question, if there are multiple "mouth" in the image just one is selected right? is it possible to detect multiple markers?Covenantor
@micfra, do you have some ideia or reference about how to select an image and search for similar images in a directory using javacv? I already did it using javax.media.jai.JAI, in the meantime, javacv is very advanced, so I think javacv can produces accurate results.Eudemonia
@cassio-seffrin you might use the algorithm above. Choose the pattern image, iterate the directory and let the CV search for your for the pattern in each file.Yuu
Highgui no longer available in OpenCV 3 anymore. Use Imgcodecs instead https://mcmap.net/q/403279/-highgui-is-missing-from-opencv-3-0-0-jarRicercare
@Yuu or can someone help me in this matter, I really need to do this. #61876957Brigettebrigg
B
7

If you want to use OpenCV 3 and more you should use this code

because there is no Highgui in OpenCV 3 and you should use imgcodecs instead.

import org.opencv.core.Core;
import org.opencv.core.Core.MinMaxLocResult;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

class MatchingDemo {
    public void run(String inFile, String templateFile, String outFile,
        int match_method) {
    System.out.println("\nRunning Template Matching");

    Mat img = Imgcodecs.imread(inFile);
    Mat templ = Imgcodecs.imread(templateFile);

    // / Create the result matrix
    int result_cols = img.cols() - templ.cols() + 1;
    int result_rows = img.rows() - templ.rows() + 1;
    Mat result = new Mat(result_rows, result_cols, CvType.CV_32FC1);

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

    // / Localizing the best match with minMaxLoc
    MinMaxLocResult mmr = Core.minMaxLoc(result);

    Point matchLoc;
    if (match_method == Imgproc.TM_SQDIFF
            || match_method == Imgproc.TM_SQDIFF_NORMED) {
        matchLoc = mmr.minLoc;
    } else {
        matchLoc = mmr.maxLoc;
    }

    // / Show me what you got
    Imgproc.rectangle(img, matchLoc, new Point(matchLoc.x + templ.cols(),
            matchLoc.y + templ.rows()), new Scalar(0, 255, 0));

    // Save the visualized detection.
    System.out.println("Writing " + outFile);
    Imgcodecs.imwrite(outFile, img);

}
}

public class TemplateMatching {

public static void main(String[] args) {
    System.loadLibrary("opencv_java300");
    new MatchingDemo().run(args[0], args[1], args[2], Imgproc.TM_CCOEFF);
}

}
Bloodline answered 18/10, 2017 at 8:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.