user1986708
user1986708

Reputation: 41

matchTemplate with openCV in java

i have a code like this:

Mat img = Highgui.imread(inFile);
Mat templ = Highgui.imread(templateFile);
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);
Imgproc.matchTemplate(img, templ, result, Imgproc.TM_CCOEFF);
/////Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
for (int i = 0; i < result_rows; i++)
for (int j = 0; j < result_cols; j++) 
  if(result.get(i, j)[0]>?)

     //match!

I need to parse the input image to find multiple occurrencies of the template image. I want to have a result like this:

result[0][0]= 15%
result[0][1]= 17%
result[x][y]= 47%

If i use TM_COEFF all results are [-xxxxxxxx.xxx,+xxxxxxxx.xxx]

If i use TM_SQDIFF all results are xxxxxxxx.xxx

If i use TM_CCORR all results are xxxxxxxx.xxx

How can i detect a match or a mismatch? What is the right condition into the if? If i normalized the matrix the application set a value to 1 and i can't detect if the template isn't stored into the image (all mismatch).

Thanks in advance

Upvotes: 2

Views: 8226

Answers (2)

zawhtut
zawhtut

Reputation: 8541

Another approach will be background differencing. You can observe the distortion.

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.highgui.Highgui;
import org.opencv.imgproc.Imgproc;


public class BackgroundDifference {
    public static void main(String[] arg){
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        Mat model = Highgui.imread("e:\\answers\\template.jpg",Highgui.CV_LOAD_IMAGE_GRAYSCALE);
        Mat scene = Highgui.imread("e:\\answers\\front7.jpg",Highgui.CV_LOAD_IMAGE_GRAYSCALE);
        Mat diff = new Mat();
        Core.absdiff(model,scene,diff);
        Imgproc.threshold(diff,diff,15,255,Imgproc.THRESH_BINARY);
        int distortion = Core.countNonZero(diff);
        System.out.println("distortion:"+distortion);
        Highgui.imwrite("e:\\answers\\diff.jpg",diff);
    }
}

enter image description here

enter image description here

enter image description here

Upvotes: 1

mehfoos yacoob
mehfoos yacoob

Reputation: 428

You can append "_NORMED" to the method names (For instance: CV_TM_COEFF_NORMED in C++; could be slightly different in Java) to get a sensible value for your purpose.

By 'sensible', I mean that you will get values in the range of 0 to 1 which can be multiplied by 100 for your purpose.

Note: For CV_TM_SQDIFF_NORMED, it will be in the range -1 to 0, and you will have to subtract the value from 1 in order to make sense of it, because the lowest value if used in this method.

Tip: you can use the java equivalent of minMaxLoc() in order to get the minimum and maximum values. It's very useful when used in conjunction with matchtemplate. I believe 'minMaxLoc' that is located inside the class Core.

Here's a C++ implementation:

matchTemplate( input_mat, template_mat, result_mat, method_NORMED );

double minVal, maxVal; 

double percentage;

Point minLoc; Point maxLoc;

minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
if( method_NORMED == CV_TM_SQDIFF_NORMED )
{
   percentage=1-minVal;
}
else
{
   percentage=maxVal;
}

Useful C++ docs: Match template description along with available methods: http://docs.opencv.org/modules/imgproc/doc/object_detection.html MinMaxLoc documentation: http://docs.opencv.org/modules/core/doc/operations_on_arrays.html?highlight=minmaxloc#minmaxloc

Upvotes: 3

Related Questions