OpenCV官方演示[模板匹配] [MatchTemplate_Demo.cpp]
http://docs.opencv.org/3.2.0/de/da9/tutorial_template_matching.html
我是用java写的。
MatchTemplateDemo.java
package Histogram_Matching;
import org.opencv.core.Core;
import org.opencv.core.Core.MinMaxLocResult;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import util.Highgui;
class MatchTemplateDemoOperationsRun {
boolean use_mask;
Mat img;
Mat templ;
Mat mask;
Mat result = new Mat();
final String image_window = "Source Image";
final String result_window = "Result window";
int match_method;
int max_Trackbar = 5;
void run() {
img = Imgcodecs.imread("./res/Template_Matching_Original_Image.jpg", Imgcodecs.IMREAD_COLOR);
templ = Imgcodecs.imread("./res/Template_Matching_Template_Image.jpg", Imgcodecs.IMREAD_COLOR);
// Highgui.imshow("img", img);
// Highgui.imshow("templ", templ);
// use_mask = true;
// mask = Imgcodecs.imread("", Imgcodecs.IMREAD_COLOR);
Highgui.namedWindow(image_window, Highgui.WINDOW_AUTOSIZE);
Highgui.namedWindow(result_window, Highgui.WINDOW_AUTOSIZE);
final String trackbar_label = "Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED";
Highgui.createTrackbar(trackbar_label, image_window, max_Trackbar, new Highgui.TrackbarCallback() {
@Override
public void onChange(int i) {
match_method = i;
MatchingMethod(i);
}
});
MatchingMethod(0);
}
void MatchingMethod(int value) {
Mat img_display = new Mat();
img.copyTo(img_display);
int result_cols = img.cols() - templ.cols() + 1;
int result_rows = img.rows() - templ.rows() + 1;
result.create(result_rows, result_cols, CvType.CV_32FC1);
boolean method_accepts_mask = (Imgproc.TM_SQDIFF == match_method || match_method == Imgproc.TM_CCORR_NORMED);
if (use_mask && method_accepts_mask) {
Imgproc.matchTemplate(img, templ, result, match_method, mask);
} else {
Imgproc.matchTemplate(img, templ, result, match_method);
}
Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
// double minVal;
// double maxVal;
// Point minLoc;
// Point maxLoc;
MinMaxLocResult res;
Point matchLoc;
res = Core.minMaxLoc(result, new Mat());
if (match_method == Imgproc.TM_SQDIFF || match_method == Imgproc.TM_SQDIFF_NORMED) {
matchLoc = res.minLoc;
} else {
matchLoc = res.maxLoc;
}
Imgproc.rectangle(img_display, matchLoc, new Point(matchLoc.x + templ.cols(), matchLoc.y + templ.rows()),
Scalar.all(0), 2, Imgproc.LINE_8, 0);
Imgproc.rectangle(result, matchLoc, new Point(matchLoc.x + templ.cols(), matchLoc.y + templ.rows()),
Scalar.all(0), 2, Imgproc.LINE_8, 0);
Highgui.imshow(image_window, img_display);
Highgui.imshow(result_window, result); // HERE!!!!!!
}
}
public class MatchTemplateDemo {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
new MatchTemplateDemoOperationsRun().run();
}
}
Highgui.imshow():核心方法是
private static Image toBufferedImage(Mat m) {
System.out.println("m.channels():" + m.channels());
System.out.println("m.dump():" + m.dump());
int type = BufferedImage.TYPE_BYTE_GRAY;
if (m.channels() > 1) {
type = BufferedImage.TYPE_3BYTE_BGR;
}
int bufferSize = m.channels() * m.cols() * m.rows();
byte[] b = new byte[bufferSize];
m.get(0, 0, b); // get all the pixels // !!!HERE!!!
BufferedImage image = new BufferedImage(m.cols(), m.rows(), type);
final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
System.arraycopy(b, 0, targetPixels, 0, b.length);
return image;
}
OpenCV没有Highgui util,所以我写了一个简单的Highgui.java:
注意!!!这里!!!评论!!!
Highgui.java
package util;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import javax.swing.ImageIcon;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.opencv.core.Mat;
public class Highgui {
public static final int WINDOW_NORMAL = 0;
public static int WINDOW_AUTOSIZE = -1;
static Map<String, Window> windows = new HashMap<>();
static Window getWindow(String windowname) {
Window window = windows.get(windowname);
if (window == null) {
window = new Window();
window.addKeyListener(keyListnere);
window.setVisible(true);
windows.put(windowname, window);
}
return window;
}
public static void namedWindow(String title, int size) {
Window window = getWindow(title);
window.setWindowName(title);
}
public static void imshow(String title, Mat mat) {
Window window = getWindow(title);
ImageIcon icon = new ImageIcon(toBufferedImage(mat));
window.setIcon(icon);
}
public static void moveWindow(String title, int x, int y) {
Window window = getWindow(title);
window.setLocation(x, y);
}
public static void createTrackbar(String trackbarname, String winname, int count, TrackbarCallback callback) {
Window window = getWindow(winname);
window.createTrackbar(trackbarname, count, new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (callback != null) {
JSlider slider = (JSlider) e.getSource();
callback.onChange(slider.getValue());
}
}
});
}
public interface TrackbarCallback {
void onChange(int i);
}
public interface MouseCallback {
void onMouse(int event, int x, int y, int flags);
}
private static Image toBufferedImage(Mat m) {
System.out.println("m.channels():" + m.channels());
System.out.println("m.dump():" + m.dump());
int type = BufferedImage.TYPE_BYTE_GRAY;
if (m.channels() > 1) {
type = BufferedImage.TYPE_3BYTE_BGR;
}
int bufferSize = m.channels() * m.cols() * m.rows();
byte[] b = new byte[bufferSize];
m.get(0, 0, b); // get all the pixels // !!!HERE!!!
BufferedImage image = new BufferedImage(m.cols(), m.rows(), type);
final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
System.arraycopy(b, 0, targetPixels, 0, b.length);
return image;
}
// private static BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(1024);
private static Queue<Integer> keys = new PriorityQueue<>();
public static int waitKey(int delay) {
long start = System.currentTimeMillis();
for (;;) {
long current = System.currentTimeMillis();
if (delay > 0 && current - start > delay) {
return -1;
}
Integer poll = keys.poll();
if (poll != null) {
return (int) poll;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// return -1;
}
private static KeyListener keyListnere = new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
System.out.println("keyTyped() e: " + e);
}
@Override
public void keyReleased(KeyEvent e) {
System.out.println("keyReleased() e: " + e);
}
@Override
public void keyPressed(KeyEvent e) {
System.out.println("keyPressed() e: " + e);
keys.add((int) e.getKeyChar());
}
};
public static void setTrackbarPos(String trackbarname, String winname, int pos) {
Window window = getWindow(winname);
// window.getFrame().revalidate();
// window.getFrame().repaint();
}
public static void setMouseCallback(String winname, MouseCallback onMouse) {
Window window = getWindow(winname);
}
}
控制台
Exception in thread "main" java.lang.UnsupportedOperationException: Mat data type is not compatible: 5
at org.opencv.core.Mat.get(Mat.java:1015)
at util.Highgui.toBufferedImage(Highgui.java:98)
at util.Highgui.imshow(Highgui.java:54)
at Histogram_Matching.MatchTemplateDemoOperationsRun.MatchingMethod(MatchTemplateDemo.java:92)
at Histogram_Matching.MatchTemplateDemoOperationsRun.run(MatchTemplateDemo.java:50)
at Histogram_Matching.MatchTemplateDemo.main(MatchTemplateDemo.java:100)
Highgui.toBufferedImage()有问题,它是从opencv的java演示版中复制的,但是当它通过&#39;结果&#39时,它在这里不能正常工作;相信它。
at org.opencv.core.Mat.get(Mat.java:1015)
at util.Highgui.toBufferedImage(Highgui.java:98)
(Highgui.java:98)在Highgui.toBufferedImage()中:
m.get(0, 0, b); // get all the pixels