Что такое шаблон OpenCV, соответствующий максимальному минимальному диапазону значений? Необходимо использовать как theshold / C++ / java
Я создаю простое приложение 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;
}
теперь проблема заключается в принятии решения (true/false) с использованием этого minMaxValue. Я знаю, что два вышеуказанных метода TM_SQDIFF и TM_SQDIFF_NORMED возвращают низкие значения, а другие возвращают высокие значения, поэтому я могу иметь 2 разных порога и сравнивать один из порогов (в зависимости от типа метода шаблона).
поэтому было бы здорово, если бы кто-нибудь мог объяснить, что такое диапазон minVal и maxVal, который возвращает MinMaxLocResult.
это диапазон от 0 до 1?
если да, то для Max type template значение метода 1 идеально подходит?
3 ответов
не нормализуйте результат, тогда он даст правильное значение, я имею в виду удалить эту строку
Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
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);
}
}