Android OpenCV 模板匹配多目标、多匹配

Android OpenCV 模板匹配多目标、多匹配

在网上搜了许多文章和博客居然没有一个介绍如何使用java opencv 进行模板匹配多目标的,翻看了opencv官网的文档也都没有找到,网上基本上都是介绍如何用python 和 c++ 进行opencv操作的,哎~ 看来只能靠自己了,废话不多说 先看效果图:
在这里插入图片描述

这里把小日本的图标都给匹配到了,用到的模板图片是下面这个:

在这里插入图片描述

具体代码


    public void Matching() {
        Mat muban = Imgcodecs.imread("/storage/emulated/0/muban2.jpg");     //todo  模板图
        Mat src = Imgcodecs.imread(getExternalFilesDir("") + "/jietu.jpg");     //todo 待匹配的图
        Mat clone = src.clone();
        if(muban.empty()){
            Log.e(TAG, "未找到资源");
            return;
        }

        int templatW, templatH, resultH, resultW;
        templatW = muban.width();
        templatH = muban.height();

        resultH = src.rows() - muban.rows() + 1;
        resultW = src.cols() - muban.cols() + 1;
        Mat result = new Mat(new Size(resultH,resultW), CvType.CV_32FC1);
        Imgproc.matchTemplate(clone, muban, result, Imgproc.TM_CCOEFF_NORMED);   //是标准相关性系数匹配  值越大越匹配
        Core.MinMaxLocResult mmr;
        mmr = Core.minMaxLoc(result);
        //在原图上的对应模板可能位置画一个绿色矩形
        Imgproc.rectangle(src, mmr.maxLoc, new Point( mmr.maxLoc.x + templatW, mmr.maxLoc.y + templatH), new Scalar(0, 255, 0),5);
        Log.e(TAG, "匹配的值:"+mmr.maxVal+"   ------坐标:"+mmr.maxLoc.x+","+mmr.maxLoc.y);
         for (int i=0;i<8;i++){
            if(mmr.maxVal>0.8){   //这里是判断相似程度的
                mmr = getMaxLoc(clone,muban,templatW,templatH,mmr.maxLoc);
                if(mmr.maxVal>0.8){
                    Imgproc.rectangle(src, mmr.maxLoc, new Point( mmr.maxLoc.x + templatW, mmr.maxLoc.y + templatH), new Scalar(0, 255, 0),5);
                    Log.e(TAG, "匹配的值:"+mmr.maxVal+"   ------坐标:"+mmr.maxLoc.x+","+mmr.maxLoc.y);
                }
            }
          }

         //将结果输出到对应位置
        Imgcodecs.imwrite(getExternalFilesDir("") +"/匹配结果.jpeg", src);
    }

这里自己写了个 getMaxLoc 方法循环调用把匹配的目标全部找出来


    private Core.MinMaxLocResult getMaxLoc(Mat clone,Mat result, int templatW, int templatH, Point maxLoc){
        int startY,startX,endY,endX;

        //计算大矩形的坐标
        startY = (int)maxLoc.y;
        startX = (int)maxLoc.x;

        //计算大矩形的的坐标
        endY = (int)maxLoc.y + templatH;
        endX = (int)maxLoc.x + templatW;

        //将大矩形内部 赋值为最大值 使得 以后找的最小值 不会位于该区域  避免找到重叠的目标
        int ch = clone.channels();     //通道数 (灰度: 1, RGB: 3, etc.)
        for (int i = startX; i < endX;  i++) {
            for (int j = startY; j < endY ;  j++) {
                double[] data = clone.get(j, i);    //读取像素值,并存储在double数组中
                for (int k = 0; k < ch; k++){        //RGB值或灰度值
                    data[k] =255;      //对每个像素值(灰度值或RGB通道值,取值0~255)进行处理
                }
                clone.put(j, i,data);         //把处理后的像素值写回到Mat
            }
        }

        int resultH = clone.rows() - result.rows() + 1;
        int resultW = clone.cols() - result.cols() + 1;
        Mat result2 = new Mat(new Size(resultH,resultW), CvType.CV_32FC1);
        Imgproc.matchTemplate(clone, result, result2, Imgproc.TM_CCOEFF_NORMED);   //是标准相关性系数匹配  值越大越匹配


//        Imgcodecs.imwrite(getExternalFilesDir("") +"/匹配结果.jpeg", clone);
        //查找result中的最大值 及其所在坐标
       return Core.minMaxLoc(result2);
    }

**思路主要是 循环调用 opencv的 matchTemplate 方法不断进行匹配,每次匹配的时候把上次的目标位置在图片中抹除,这样下次再匹配的时候就不会匹配到重复的目标,匹配是从大到小依次把目标位置筛选出来的
在这里插入图片描述

注意事项

[1] 该博客是本人原创博客,转载时请注明出处~
[2] 由于个人能力有限,上面实现的方案可能不是最优的,如果你有更好的实现方案,欢迎留言告诉我
我会及时回复

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值