Search code examples
javaandroidopencvimage-processingtemplate-matching

Template Matching - Why the result matrix is smaller than specified?


So I'm doing the template matching for specific region from input image using OpenCVCameraView. Below is what my code looks like.

Mat input;
Rect bigRect = ...; //specific size

public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    input = inputFrame.rgba();
    ...
}

public void Template(View view) {
    Mat mImage = input.submat(bigRect);
    Mat mTemplate = Utils.loadResource(this, R.id.sample, Highgui.CV_LOAD_IMAGE_COLOR);
    Mat mResult = new Mat(mImage.rows(), mImage.cols(), CvType.CV_32FC1); // I use the same size as mImage because mImage's size is already smaller than inputFrame

    Imgproc.cvtColor(mImage, mImage, Imgproc.COLOR_RGBA2RGB); //convert is needed to make mImage and mTemplate to be the same type

    Imgproc.matchTemplate(mImage, mTemplate, mResult, match_method);        
    Core.normalize(mResult, mResult, 0, 1, Core.NORM_MINMAX, -1, new Mat());

    mResult.convertTo(mResult, CvType.CV_8UC1); // I convert the matrix because I need to show it to imageview via bitmap

    Bitmap bmResult1 = Bitmap.createBitmap(mImage.width(), mImage.height(), Bitmap.Config.RGB_565);
    Bitmap bmResult2 = Bitmap.createBitmap(mResult.width(), mResult.height(), Bitmap.Config.RGB_565);
    Utils.matToBitmap(mImage, bmResult1);
    Utils.matToBitmap(mResult, bmResult2);
    ImageView1.setImageBitmap(bmResult1);
    ImageView2.setImageBitmap(bmResult2);
}

The I try to output the matrix using toString() and got these results:

mImage: Mat [250*178*CV_8UC3, isCont=true, isSubmat=false, ...]
mResult: Mat [180*94*CV_8UC1, isCont=true, usSubmat=false, ...]

And my questions are:

  1. Why the mResult size is smaller than mImage despite already declared that mResult size is based on mImage size?
  2. Turns out that by using CV_8UC1 type, the content is only available in black or white, while mResult is supposed to have floating value, but Utils.matToBitmap method doesn't support mat types other than CV_8UC1, CV_8UC3, and CV_8UC4. Is there any way to show CV_32FC1 to Bitmap that it shows the real grayscale of mResult?

Solution

  • Why the mResult size is smaller than mImage despite already declared that mResult size is based on mImage size?

    As template matching is basically a spatial convolution, when performed with images of height H and h, the result will be H-h+1. Same with result width (W-w+1). But you can still resizethe result back to (mImage.rows(), mImage.cols()) after template matching.

    Turns out that by using CV_8UC1 type, the content is only available in black or white, while mResult is supposed to have floating value, but Utils.matToBitmap method doesn't support mat types other than CV_8UC1, CV_8UC3, and CV_8UC4. Is there any way to show CV_32FC1 to Bitmap that it shows the real grayscale of mResult?

    The key is in these two lines, I think:

    Core.normalize(mResult, mResult, 0, 1, Core.NORM_MINMAX, -1, new Mat());
    mResult.convertTo(mResult, CvType.CV_8UC1); // I convert the matrix because I need to show it to imageview via bitmap
    

    Can't you just normalize it to take values between 0 and 255?

    Core.normalize(mResult, mResult, 0, 255, Core.NORM_MINMAX, -1, new Mat());