Java + OpenCV 模板匹配

何为模板匹配

模板匹配就是在指定模板图片中,在模板区域内找寻与待匹配图片中最相似的。通过不断滑动模板图片,计算其与待匹配图片区域的匹配度,将匹配度最高的区域视为最终匹配结果。

实现方法

Imgproc.matchTemplate(src, template, result, method);

参考示例

package com.polar.core.bdata.templateMatch;

import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.util.HashMap;
import java.util.Map;

/**
 * 描述: OpenCv匹配图像模板工具类
 * 创建时间:2023/1/30 11:18
 * @author Perpetual
 */
public class OpenCVUtil{
    //静态代码块加载动态链接库
    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }

    /**
     * 描述:通过图片地址进行图片比对方法
     * 作者:Perpetual
     * 创建时间:2023/1/30 11:19
     * @param mainPic 待匹配图片-主模板
     * @param comPic  获取匹配模板-图片模块
     * @return code == 200/500 比对成功/比对失败(成功包含x/y/itemWidth/itemHeight)
     */
    public static Map<String, Object> getCoordinates(String mainPic, String comPic) {
        Map<String, Object> reason = new HashMap<>();
        try {

//                                  读入的模式
//            模式	                            说明
//            IMREAD_UNCHANGED	            按原样返回加载的图像(使用alpha通道,否则会被裁剪)。
//            IMREAD_GRAYSCALE	            将图像转换为单通道灰度图像(编解码器内部转换)。
//            IMREAD_COLOR	                将图像转换为3通道BGR彩色图像。
//            IMREAD_ANYDEPTH	            当输入图像具有深度时,返回16位/32位图像,否则将其转换为8位。
//            IMREAD_ANYCOLOR	            图像以任何可能的颜色格式读取。
//            IMREAD_LOAD_GDAL	            使用gdal驱动程序加载图像。
//            IMREAD_REDUCED_GRAYSCALE_2	将图像转换为单通道灰度图像,图像大小缩小1/2。
//            IMREAD_REDUCED_COLOR_2	    将图像转换为3通道BGR彩色图像,图像大小缩小1/2。
//            IMREAD_REDUCED_GRAYSCALE_4	将图像转换为单通道灰度图像,图像大小缩小1/4。
//            IMREAD_REDUCED_COLOR_4	    始终将图像转换为3通道BGR彩色图像,图像大小缩小1/4。
//            IMREAD_REDUCED_GRAYSCALE_8	始终将图像转换为单通道灰度图像,图像大小减小1/8。
//            IMREAD_REDUCED_COLOR_8	    将图像转换为3通道BGR彩色图像,图像大小缩小1/8。
//            IMREAD_IGNORE_ORIENTATION	    不要根据EXIF的方向标志旋转图像。

            // 待匹配图片---主模板
            Mat src = Imgcodecs.imread(mainPic);
            // 获取匹配模板---图片模块
            Mat template = Imgcodecs.imread(comPic);

            /*
             * TM_SQDIFF = 0, 平方差匹配法,最好的匹配为0,值越大匹配越差
             * TM_SQDIFF_NORMED = 1,归一化平方差匹配法
             * TM_CCORR = 2,相关匹配法,采用乘法操作,数值越大表明匹配越好
             * TM_CCORR_NORMED = 3,归一化相关匹配法
             * TM_CCOEFF = 4,相关系数匹配法,最好的匹配为1,-1表示最差的匹配
             * TM_CCOEFF_NORMED = 5;归一化相关系数匹配法
             */
            int method = Imgproc.TM_CCOEFF;
            int width = src.cols() - template.cols() + 1;
            int height = src.rows() - template.rows() + 1;
            // 创建32位模板匹配结果Mat
            Mat result = new Mat(width, height, CvType.CV_32FC1);
            /*
             * 将模板与重叠的图像区域进行比较。
             * @param src运行搜索的图像。 它必须是8位或32位浮点。
             * @param template。 它必须不大于源图像并且具有相同的数据类型。
             * @param result比较结果图。 它必须是单通道32位浮点。 如果image是(W * H)并且templ是(w * h),则结果是((W-w + 1)*(H-h + 1))。
             * @param方法用于指定比较方法的参数,请参阅默认情况下未设置的#TemplateMatchModes。
             * 当前,仅支持#TM_SQDIFF和#TM_CCORR_NORMED方法。
             */
            Imgproc.matchTemplate(src, template, result, method);

            // 归一化
            Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());

            // 获取模板匹配结果
            Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
            double x = mmr.minLoc.x;
            double y = mmr.minLoc.y;

            /*
             * FILLED = -1,
             * LINE_4 = 4, 下一个点和上一个点边相连(没有角了),这样就消除了8联通法线断裂的瑕疵
             * LINE_8 = 8, 下一个点连接上一个点的边或角
             * LINE_AA = 16; 边缘像素采用高斯滤波,抗锯齿
             */
            Imgproc.rectangle(src,new Point(x,y),new Point(x+template.cols(),y+template.rows()),new Scalar( 0, 0, 255),2,Imgproc.LINE_4);

//            Imgproc.rectangle(template,new Point(0,0),new Point(template.cols(),template.rows()),new Scalar( 0, 0, 255),2,Imgproc.INTER_LINEAR_EXACT);
//            HighGui.imshow("wda",template);

            HighGui.imshow("对比结果", src);
        } catch (Exception e) {
			e.printStackTrace();
        }
    }
}

对比结果

1 模板图片:

在这里插入图片描述

2 待匹配区域图片

在这里插入图片描述

3 对比结果

在这里插入图片描述

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值