|
@@ -0,0 +1,120 @@
|
|
|
+package com.management.platform.util;
|
|
|
+
|
|
|
+import org.opencv.core.*;
|
|
|
+import org.opencv.features2d.DescriptorMatcher;
|
|
|
+import org.opencv.highgui.HighGui;
|
|
|
+import org.opencv.imgcodecs.Imgcodecs;
|
|
|
+import org.opencv.imgproc.Imgproc;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+
|
|
|
+import static java.lang.Math.E;
|
|
|
+
|
|
|
+public class ImageReconizeUtil {
|
|
|
+ public static final double YUZHI = Math.pow(0.1, 10);
|
|
|
+ static {
|
|
|
+ System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
|
|
|
+ //注意程序运行的时候需要在VM option添加该行 指明opencv的dll文件所在路径
|
|
|
+ //-Djava.library.path=$PROJECT_DIR$\opencv\x64
|
|
|
+ }
|
|
|
+ public static void main(String[] args) {
|
|
|
+// boolean match = isTemplateMatch("C:\\Users\\seya\\Desktop\\360_2.jpg",
|
|
|
+// "C:\\picrecongnize\\360Safe\\2.jpg");
|
|
|
+ boolean match = isTemplateMatch("C:\\Users\\seya\\Desktop\\qyt_2.jpg",
|
|
|
+ "C:\\\\picrecongnize\\\\360Safe\\\\2.jpg");
|
|
|
+ }
|
|
|
+
|
|
|
+ public static boolean isTemplateMatch(String sourcePic, String targetPic) {
|
|
|
+ double matchVal = templete(Imgproc.TM_SQDIFF_NORMED, sourcePic, targetPic);
|
|
|
+ if (Math.abs(matchVal) < YUZHI) {
|
|
|
+ System.out.println("找到啦");
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ System.out.println("没匹配上");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * OpenCV-4.1.0 模板匹配
|
|
|
+ * <table border="1" cellpadding="8">
|
|
|
+ * <tr><th>输入参数</th><th>参数解释</th></tr>
|
|
|
+ * <tr><td align="left">TM_SQDIFF是平方差匹配、TM_SQDIFF_NORMED是标准平方差匹配</td><td>利用平方差来进行匹配,最好匹配为0.匹配越差,匹配值越大。</td></tr>
|
|
|
+ * <tr><td align="left">TM_CCORR是相关性匹配、TM_CCORR_NORMED是标准相关性匹配</td><td>采用模板和图像间的乘法操作,数越大表示匹配程度较高, 0表示最坏的匹配效果。</td></tr>
|
|
|
+ * <tr><td align="left">TM_CCOEFF是相关性系数匹配、TM_CCOEFF_NORMED是标准相关性系数匹配</td><td>将模版对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性(随机序列)。</td></tr>
|
|
|
+ * <tr><td colspan="2">随着从简单的测量(平方差)到更复杂的测量(相关系数),我们可获得越来越准确的匹配(同时也意味着越来越大的计算代价)。</td></tr>
|
|
|
+ * <tr><td colspan="2">相关性是越接近1越大越好,平方差是越小越好,所以TM_SQDIFF在使用时和其他的是有所区别的。</td></tr>
|
|
|
+ * <tr><td colspan="2">模板匹配结果Mat要是32位的。</td></tr>
|
|
|
+ * </table>
|
|
|
+ * @return: void
|
|
|
+ * @date: 2019年5月7日12:16:55
|
|
|
+ */
|
|
|
+ public static double templete(int method, String sourcePic, String targetPic) {
|
|
|
+ // 1 获取待匹配图片
|
|
|
+ Mat templete=Imgcodecs.imread(sourcePic);
|
|
|
+ //将rgb灰化处理
|
|
|
+ Imgproc.cvtColor(templete, templete,Imgproc.COLOR_BGR2GRAY);
|
|
|
+
|
|
|
+ // 2 获取匹配模板
|
|
|
+ Mat demo=Imgcodecs.imread(targetPic);
|
|
|
+ Imgproc.cvtColor(demo, demo,Imgproc.COLOR_BGR2GRAY);
|
|
|
+
|
|
|
+ Core.MinMaxLocResult mmr = getLocResult(method, templete, demo);
|
|
|
+ // 7 绘制匹配到的结果
|
|
|
+ double x,y;
|
|
|
+ double matchVal = 0;
|
|
|
+ if (method==Imgproc.TM_SQDIFF_NORMED || method==Imgproc.TM_SQDIFF) {
|
|
|
+ x = mmr.minLoc.x;
|
|
|
+ y = mmr.minLoc.y;
|
|
|
+ matchVal = mmr.minVal;
|
|
|
+ } else {
|
|
|
+ x = mmr.maxLoc.x;
|
|
|
+ y = mmr.maxLoc.y;
|
|
|
+ matchVal = mmr.maxVal;
|
|
|
+ }
|
|
|
+ //if not match , resize the targetPic and try to match again!
|
|
|
+ if (Math.abs(matchVal) > YUZHI) {
|
|
|
+ System.out.println("第一次没匹配上, 尝试125%尺寸再次匹配~~");
|
|
|
+ Mat demoResize = demo.clone();
|
|
|
+ float scale=1.25f;
|
|
|
+ float widthT=demo.width();
|
|
|
+ float heightT=demo.height();
|
|
|
+ Imgproc.resize(demo, demoResize, new Size(widthT*scale,heightT*scale));
|
|
|
+ demo = demoResize;
|
|
|
+ mmr = getLocResult(method, templete, demo);
|
|
|
+ // 7 绘制匹配到的结果
|
|
|
+ matchVal = 0;
|
|
|
+ if (method==Imgproc.TM_SQDIFF_NORMED || method==Imgproc.TM_SQDIFF) {
|
|
|
+ x = mmr.minLoc.x;
|
|
|
+ y = mmr.minLoc.y;
|
|
|
+ matchVal = mmr.minVal;
|
|
|
+ } else {
|
|
|
+ x = mmr.maxLoc.x;
|
|
|
+ y = mmr.maxLoc.y;
|
|
|
+ matchVal = mmr.maxVal;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ System.out.println("匹配度=="+matchVal);
|
|
|
+ System.out.println("x="+x+", y=" + y);
|
|
|
+ Imgproc.rectangle(templete,new Point(x,y),new Point(x+demo.cols(),y+demo.rows()),new Scalar( 0, 0, 255),2,Imgproc.LINE_AA);
|
|
|
+ Imgproc.putText(templete,"Match Success",new Point(x,y),Imgproc.FONT_HERSHEY_SCRIPT_COMPLEX, 1.0, new Scalar(0, 255, 0),1,Imgproc.LINE_AA);
|
|
|
+// // 8 显示结果
|
|
|
+ HighGui.imshow("模板匹配", templete);
|
|
|
+ HighGui.waitKey(0);
|
|
|
+ return matchVal;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Core.MinMaxLocResult getLocResult(int method, Mat templete, Mat demo) {
|
|
|
+ int width=templete.cols()-demo.cols()+1;
|
|
|
+ int height=templete.rows()-demo.rows()+1;
|
|
|
+ // 3 创建32位模板匹配结果Mat
|
|
|
+ Mat result=new Mat(width,height,CvType.CV_32FC1);
|
|
|
+ // 4 调用 模板匹配函数
|
|
|
+ Imgproc.matchTemplate(templete, demo, result, method);
|
|
|
+ // 5 归一化
|
|
|
+ Core.normalize(result, result,0, 1, Core.NORM_MINMAX, -1, new Mat());
|
|
|
+ // 6 获取模板匹配结果
|
|
|
+ Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
|
|
|
+ return mmr;
|
|
|
+ }
|
|
|
+}
|