7

テンプレート マッチングを使用して単純な openCV アプリケーションを作成しています。ここでは、比較して大きな画像内の小さな画像を見つけ、結果を true (一致が見つかった場合) または false (一致が見つからなかった場合) として返す必要があります。

    Imgproc.matchTemplate(largeImage, smallImage, result, matchMethod);
    Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());

    MinMaxLocResult mmr = Core.minMaxLoc(result);

    double minMaxValue = 1;
    if (matchMethod== Imgproc.TM_SQDIFF || matchMethod== Imgproc.TM_SQDIFF_NORMED)
    {
        minMaxValue = mmr.minVal;
        useMinThreshold = true;
    }
    else
    {
        minMaxValue = mmr.maxVal;
    }

問題は、この minMaxValue を使用して決定 (true/false) を行うことです。上記の 2 つのメソッド TM_SQDIFF と TM_SQDIFF_NORMED は低い値を返し、他のメソッドは高い値を返すことを知っているので、2 つの異なるしきい値を設定し、しきい値の 1 つを比較できます (テンプレート メソッドの種類によって異なります)。

そのため、MinMaxLocResult が返す minVal と maxVal の範囲を誰かが説明できれば幸いです。

0~1の範囲ですか?

はいの場合、Max タイプ テンプレート メソッドの値 1 は完全に一致しますか?

4

4 に答える 4

10

MinMaxLocResultminVal戻り ませんmaxValリンクminValmaxVal見られるように、最小および最大の一致スコアです。

構造体には と タイプのプロパティMinMaxLocResultminLocあり、一致する場所を示します。またはを一致基準として使用すると、最適な一致場所は になります。maxLocPointTM_SQDIFFTM_SQDIFF_NORMEDmmr.minLoc

検出のしきい値を設定するために、変数を宣言し、double thresholdMatch実験的にその値を設定できます。minVal < thresholdMatch の場合、ターゲット オブジェクトが検出されたと言えます。

于 2013-07-22T10:20:27.830 に答える
4

結果を正規化しないでください。適切な値が得られます。つまり、この行を削除します

   Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
于 2013-12-17T07:27:07.493 に答える
0

faithkの答えは素晴らしいですが、本質的にそれを実装する実際のコードを次に示します。0.1しきい値として使用して、良好な結果を記録しました。

import lombok.val;
import org.opencv.core.*;
import org.springframework.core.io.ClassPathResource;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import static javax.imageio.ImageIO.read;
import static javax.imageio.ImageIO.write;
import static javax.swing.SwingUtilities.invokeAndWait;
import static org.opencv.core.CvType.CV_32FC1;
import static org.opencv.highgui.HighGui.imshow;
import static org.opencv.highgui.HighGui.waitKey;
import static org.opencv.imgcodecs.Imgcodecs.CV_LOAD_IMAGE_UNCHANGED;
import static org.opencv.imgcodecs.Imgcodecs.imdecode;
import static org.opencv.imgproc.Imgproc.*;

public class TemplateMatcher
{
    static
    {
        // loadNativeOpenCVLibrary();
    }

    private static final int MATCH_METHOD = TM_SQDIFF_NORMED;

    private static Mat BufferedImage2Mat(BufferedImage image) throws IOException
    {
        try (val byteArrayOutputStream = new ByteArrayOutputStream())
        {
            write(image, "jpg", byteArrayOutputStream);
            byteArrayOutputStream.flush();
            val matOfByte = new MatOfByte(byteArrayOutputStream.toByteArray());
            return imdecode(matOfByte, CV_LOAD_IMAGE_UNCHANGED);
        }
    }

    public static Point performTemplateMatching(BufferedImage bigImage, BufferedImage templateImage,
                                                double detectionThreshold, boolean showMatch) throws IOException
    {
        val image = BufferedImage2Mat(bigImage);
        val template = BufferedImage2Mat(templateImage);

        // Create the result matrix
        val result_cols = image.cols() - template.cols() + 1;
        val result_rows = image.rows() - template.rows() + 1;
        val result = new Mat(result_rows, result_cols, CV_32FC1);

        // Do the matching
        matchTemplate(image, template, result, MATCH_METHOD);

        // Localize the best match
        val minMaxLocResult = Core.minMaxLoc(result);

        // / Show me what you got
        val matchedLocation = minMaxLocResult.minLoc;
        rectangle(image, matchedLocation, new Point(matchedLocation.x + template.cols(),
                matchedLocation.y + template.rows()), new Scalar(0, 255, 0));

        if (showMatch)
        {
            try
            {
                invokeAndWait(() -> imshow("Image Search", image));
            } catch (InterruptedException | InvocationTargetException exception)
            {
                exception.printStackTrace();
            }
            waitKey();
        }

        // Determine whether this sub image has been found
        val minVal = minMaxLocResult.minVal;
        if (minVal < detectionThreshold)
        {
            return minMaxLocResult.maxLoc;
        }

        return null;
    }

    public static BufferedImage getBufferedImage(String classpathFile) throws IOException
    {
        val classPathResource = new ClassPathResource(classpathFile);
        val filePath = classPathResource.getFile();
        return read(filePath);
    }
}
于 2018-08-11T14:47:25.490 に答える