opencv-matchTemplate模板匹配(大圖中尋找小圖)


單個匹配

11.png

 

 12.png

 

 

#include<opencv2/opencv.hpp>
#include<iostream>

int main(int argc, char** argv) {
    
    cv::Mat src = cv::imread("D:/bb/tu/11.png");
    cv::Mat templ = cv::imread("D:/bb/tu/12.png");
    cv::Mat ftmp;
    cv::matchTemplate(src, templ, ftmp,5);   //模板匹配
    /*
    參數1:src用於搜索的輸入圖像, 8U 或 32F, 大小 W-H
    參數2:用於匹配的模板,和src類型相同, 大小 w-h
    參數3:匹配結果圖像, 類型 32F, 大小 (W-w+1)-(H-h+1)
    參數4:用於比較的方法(有六種)
          cv::TM_SQDIFF=0 該方法使用平方差進行匹配,因此最佳的匹配結果在結果為0處,值越大匹配結果越差
          cv::TM_SQDIFF_NORMED=1:該方法使用歸一化的平方差進行匹配,最佳匹配也在結果為0處
          cv::TM_CCORR=2:相關性匹配方法,該方法使用源圖像與模板圖像的卷積結果進行匹配,因此,最佳
                匹配位置在值最大處,值越小匹配結果越差  【個人測試:匹配性很差】
          cv::TM_CCORR_NORMED=3:歸一化的相關性匹配方法,與相關性匹配方法類似,最佳匹配位置也是在值最大處
          cv::TM_CCOEFF=4:相關性系數匹配方法,該方法使用源圖像與其均值的差、模板與其均值的差二者之間的相
                關性進行匹配,最佳匹配結果在值等於1處,最差匹配結果在值等於-1處,值等於0直接表示二者不相關
          cv::TM_CCOEFF_NORMED=5:歸一化的相關性系數匹配方法,正值表示匹配的結果較好,負值則表示匹配的效
                果較差,也是值越大,匹配效果也好
    */

    std::cerr << cv::TM_CCOEFF_NORMED << std::endl;

    normalize(ftmp, ftmp, 1, 0, cv::NORM_MINMAX);//可以不歸一化
    double minVal; double maxVal;
    cv::Point minLoc; 
    cv::Point maxLoc;
    minMaxLoc(ftmp, &minVal, &maxVal, &minLoc, &maxLoc); //找到最佳匹配點
    //從匹配結果圖像中找出最佳匹配點
    rectangle(src, cv::Rect(maxLoc.x, maxLoc.y, templ.cols, templ.rows), cv::Scalar(0, 0, 255), 2, 8);//畫出匹配到的矩形框
    //注意:與方法有關,有的是最小值是最佳匹配;有的是最大值是最佳匹配

    cv::imshow("src", src);
    cv::waitKey();
    return 0;
}

 

多個匹配

13.png

 

 14.png

 

 

#include<opencv2/opencv.hpp>
#include<iostream>


int main(int argc, char** argv) {
    
    cv::Mat src = cv::imread("D:/bb/tu/13.png");
    cv::Mat tem = cv::imread("D:/bb/tu/14.png");

    cv::Mat resultImage;
    matchTemplate(src, tem, resultImage, 5);//模板匹配

    /*
    我尋找多個匹配的思路:
    matchTemplate之后,resultImage中保存了匹配相似度
    匹配方法是cv::TM_CCOEFF_NORMED=5,值越大,相似度越高
    相似度大於0.97,我就認為匹配非常好,所以我要遍歷出相似度
    大於0.97的坐標
    */

    std::vector<cv::Point> point;
    for (int i = 0; i < resultImage.rows; i++) {  //i是行號
        for (int j = 0; j < resultImage.cols; j++) {  //j是列號
            float t = resultImage.at<float>(i, j); //返回指點坐標的數據
            if (t > 0.97) {
                point.insert(point.end(), cv::Point(j,i));
            }
            
        }
    }
    
    //畫出多個匹配
    for (int i = 0; i < point.size(); i++)
    {
        rectangle(src, cv::Rect(point[i].x, point[i].y, tem.cols, tem.rows), cv::Scalar(0, 0, 255), 2, 8);
    }

    cv::imshow("src", src);
    cv::waitKey();
    return 0;
}

 

  

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM