Как получить точное соответствие с помощью сопоставления шаблонов в OpenCV (в Android)?

Я новичок в OpenCV. Я делаю приложение, которое сообщает пользователю, что данное изображение имеет заданный шаблон или нет. Я использовал этот код. Он отлично сочетается. Но он не определяет, нет ли у данного изображения соответствующего шаблона. Когда я читаю, он достигает самого высокого значения и показывает мне ложный результат (показывает где-то еще на изображении). Я читал о minVal и maxVal. Но все же я не мог хорошо понять даже то, что он делает. Потому что я отлаживал код. каждый раз, когда minVal равен 0,0, а maxVal равен 255,0 (даже изображение содержит шаблон или нет, я имею в виду каждый раз). Я застрял здесь. Пожалуйста, помогите мне показать только правильные результаты.

        Utils.bitmapToMat(bmp2, mFind);
        Utils.bitmapToMat(bmp1, Input);
        Utils.bitmapToMat(bmp3, mResult9u);

        Imgproc.matchTemplate(mFind, Input, mResult, matcher);

        Core.normalize(mResult, mResult8u, 0, 255, Core.NORM_MINMAX, CvType.CV_8U);

        Point matchLoc;

        MinMaxLocResult minMaxLoc = Core.minMaxLoc(mResult8u);

        /// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better
        if (matcher == Imgproc.TM_SQDIFF || matcher == Imgproc.TM_SQDIFF_NORMED)
        {
            matchLoc = minMaxLoc.minLoc;
        }
        else
        {
            matchLoc = minMaxLoc.maxLoc;
        }
        float thresholdMatchForMin = 0.02f;
        float thresholdMatchForMax = 0.08f;
        //                minMaxLoc.minVal < thresholdMatchForMin ||
        if (minMaxLoc.maxVal > thresholdMatchForMax)
        {
            /// Show me what you got
            Core.rectangle(mResult9u, matchLoc,
                new Point(matchLoc.x + Input.cols(), matchLoc.y + Input.rows()), new Scalar(0, 255, 255, 0));
            Utils.matToBitmap(mFind, bmp2);
            Utils.matToBitmap(mResult9u, bmp3);
            Paint paint = new Paint();
            paint.setColor(Color.RED);
            Canvas canvas = new Canvas(bmp2);
            canvas.drawRect(new Rect((int) matchLoc.x, (int) matchLoc.y, (int) (matchLoc.x + Input.cols()),
                (int) (matchLoc.y + Input.rows())), paint);
        }

person ssdehero    schedule 22.08.2013    source источник


Ответы (1)


Линия:

Core.normalize(mResult, mResult8u, 0, 255, Core.NORM_MINMAX, CvType.CV_8U);

нормализует результат. Он делает любой диапазон равным 0-255. Если вам нужны реальные значения корреляции, используйте ненормализованный mResult.

person Andrey Smorodov    schedule 22.08.2013
comment
Спасибо. Вы имеете в виду передать mResult в Core.minMaxLoc()? Я старался. Но я получил тот же результат. - person ssdehero; 22.08.2013
comment
Вы смотрели какое значение в матрице mResult в координатах matchLoc? TM_SQDIFF_NORMED должен давать результат в диапазоне 0-1. - person Andrey Smorodov; 22.08.2013
comment
Неа. Всегда я получаю 0-255. Я думаю, что я что-то пропустил здесь. Но я не знаю, что... - person ssdehero; 23.08.2013
comment
Если TM_SQDIFF_NORMED, тогда диапазон будет всем диапазоном значений элемента, потому что он нормализован :) . Когда вы используете TM_SQDIFF (или другие ненормированные метрики), диапазон тот же? И какой тип матричного элемента имеет mResult? это должно быть CV_32FC1. - person Andrey Smorodov; 23.08.2013