简体   繁体   中英

Java opencv template matching and floodfill behavior.

I've been playing around with opencv and I cant understand how floodfill works. I have one larger image and one "template" image, trying to find all matches (in this case I know that there should be two matches). My idea is to find the first match, use floodfill to fill it with w/e pixels and run template matching again and so on. Here is my code

import org.opencv.core.*;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.*;



public class Main {
    public static void main(String[] args) {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        Mat template = Imgcodecs.imread("imgs/template.jpg");
        Mat image = Imgcodecs.imread("imgs/imagetwo.jpg");


        int result_cols = image.cols() - template.cols() + 1;
        int result_rows = image.rows() - template.rows() + 1;
        Mat result = new Mat(result_rows, result_cols, CvType.CV_32FC1);

        Imgproc.matchTemplate(image, template, result, Imgproc.TM_CCOEFF);
        Core.normalize(result, result, 0.9, 1, Core.NORM_MINMAX, -1);

        Core.MinMaxLocResult res = Core.minMaxLoc(result);
        Point loc = res.maxLoc;
        double x = res.maxLoc.x;
        System.out.println(loc);

        Imgproc.rectangle(image, loc, new Point(loc.x + template.width(), loc.y + template.height()), new Scalar(0));
        Imgproc.floodFill(image, new Mat(), loc, new Scalar(0, 255, 0));
        Imgproc.matchTemplate(image, template, result, Imgproc.TM_CCOEFF);
        Core.normalize(result, result, 0.8, 1, Core.NORM_MINMAX, -1);
        res = Core.minMaxLoc(result);
        if (res.maxVal >= 0.9) {
            loc = res.maxLoc;
        } else {
            System.out.println("No matches");
        }
        System.out.println(loc);

        Imgproc.rectangle(image, loc, new Point(loc.x + template.width(), loc.y + template.height()), new Scalar(0));
        Imgproc.floodFill(image, new Mat(), loc, new Scalar(0, 255, 0));
        Imgproc.matchTemplate(image, template, result, Imgproc.TM_CCOEFF);
        Core.normalize(result, result, 0.8, 1, Core.NORM_MINMAX, -1);
        res = Core.minMaxLoc(result);
        if (res.maxVal >= 0.9) {
            loc = res.maxLoc;
        } else {
            System.out.println("No matches");
        }
        System.out.println(loc);

    }
}

And the result I am getting:

{151.0, 167.0}
{142.0, 167.0}
{151.0, 167.0}

So basically floodfill works fine the first time I use it and I am able to find the second match, but when I run the "loop" for the third time instead of getting "No matches" I get first Point again, which means my first floodfill is gone??

I'll admit that even after reading all I could find online about floodfill I'm still very uncertain on how it's supposed to work and I feel that I messed up somewhere in it's definition but I have no idea where.

Any help is appreciated, Thanks.

You need to initialize the Mask, which is the second parameter of the floodFill method. It is supposed to be set up to zero. Because the algorithm can't go across the non zero pixels. Additionally you need to consider the size of the matrix. It should be 2 pixels wider and 2 pixels taller than the image.

Probably this is too late but you can use Core.rectangle to draw the rectangle of matched template. Ofcourse, since you find multiple matches you need to draw multiple times.So, better save the "loc" into a vector of Points for every iteration of loop and then draw when the loop is done.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM