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);
}
}