可以opencv templateMatch支持大小不匹配的模板吗?

时间:2015-02-11 07:33:57

标签: android opencv

我正在使用openCV识别来自不同密度设备的图标,图标以不同的尺寸显示不同密度的设备。 如果模板大小与screencapture中显示的图标相同,则可以找到正确的位置,但如果没有,则无法找到正确的位置,甚至完全错误。 那么,我想知道opencv templateMatch支持大小不匹配模板吗?

这是我的代码:

    imgPath = "/sdcard/screencapture.png";
    Mat img = getMatFromFile(imgPath);
    Mat templ = null;
    try {
        templ = getMatFromInputStream(getAssets().open("home_big.png"));
    } catch (IOException e) {
        e.printStackTrace();
    }
    Log.i(TAG, "templ.type()="+templ.type());
    Log.i(TAG, "img.type()="+img.type());
    Log.i(TAG, "templ.depth()="+templ.depth());
    Log.i(TAG, "img.depth()="+img.depth());

    Mat result = new Mat();
    Imgproc.matchTemplate(img, templ, result, Imgproc.TM_CCORR_NORMED);

    MinMaxLocResult minMaxLocResult = Core.minMaxLoc(result, new Mat());
    Point matchLoc = minMaxLocResult.maxLoc;
    Log.i(TAG, "match result="+matchLoc);
    Log.i(TAG, "maxVal ="+minMaxLocResult.maxVal);

我也尝试了特征检测,我打印匹配的点,并参考图像和模板的x,y,但看结果,match.distance = 0匹配点,这意味着特征等于, x,y不在匹配区域,我不能依赖于此来找出图像中模板的正确位置。任何人都可以帮忙吗? 这是我的代码:     事实上我试图使用特征检测,但结果让我感到困惑,这是我的代码:

    imgPath = "/sdcard/screencapture_htc.png";
    Mat img = getMatFromFile(imgPath, Highgui.CV_LOAD_IMAGE_GRAYSCALE);
    Mat templ = null;
    try {
        templ = getMatFromInputStream(getAssets().open("icon.png"), Highgui.CV_LOAD_IMAGE_GRAYSCALE);
    } catch (IOException e) {
        e.printStackTrace();
    }

    FeatureDetector detector = FeatureDetector.create(FeatureDetector.FAST);
    DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.BRIEF);
    DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_L1);


    Mat descriptors1 = new Mat();
    Mat descriptors2 = new Mat();
    MatOfKeyPoint keypoints1 = new MatOfKeyPoint();
    MatOfKeyPoint keypoints2 = new MatOfKeyPoint();
    detector.detect(img, keypoints1);
    detector.detect(templ, keypoints2);

    List<KeyPoint> keypoints1List = keypoints1.toList();
    List<KeyPoint> keypoints2List = keypoints2.toList();

    extractor.compute( img, keypoints1, descriptors1 );  
    extractor.compute( templ, keypoints2, descriptors2); 

    MatOfDMatch matches= new MatOfDMatch();  
    matcher.match( descriptors1, descriptors2, matches);  

    Log.i(TAG, "matches.size() = "+matches.size());
    Log.i(TAG, "matches.toArray() = "+matches.toArray());

    List<DMatch> matchList = matches.toList();

    if(matchList != null){
        matchList =  filterGoodMatch(matchList);

        MatchComparator matchComparator = new MatchComparator();
        Collections.sort(matchList, matchComparator);

        int goodMatchCount = matchList.size();
        List<DMatch> goodMatchList = matchList.subList(0, goodMatchCount >    MAX ? MAX - 1 : goodMatchCount - 1);

        Log.i(TAG, "match result:");
        Log.i(TAG, "**************************");
        for(DMatch match:goodMatchList){
            Log.i(TAG, "match.distance = "+match.distance);
            Log.i(TAG, "img point = "+keypoints1List.get(match.queryIdx));
            Log.i(TAG, "train point = "+keypoints2List.get(match.trainIdx));
            Log.i(TAG, "**************************");
        }
    }else{
        Log.i(TAG, "no match");
    }

2 个答案:

答案 0 :(得分:0)

模板匹配就是这样,它寻找“像素像素”相关性。它无法处理规模变化。

如果您有不同尺寸的图像,则应重新缩放图像或模板。

如果只有几个可能的比例,你可以保留多个预先缩放的模板,并为每个案例使用正确的模板,或者只是尝试所有模板并且只是最佳匹配。

答案 1 :(得分:0)

如果模板的比例或方向可能不同,则matchTemplate将失败。 matchTemplate是opencv中用于检测场景中对象的最简单,最弱的方法 我想你看到了特征检测,描述和匹配的主题。它认为以下将是一个很好的起点: